From f3ea0095dfe20e97f061fedcf08693ec8405b775 Mon Sep 17 00:00:00 2001 From: hellisabove <59116609+hellisabove@users.noreply.github.com> Date: Sat, 18 Mar 2023 20:26:52 +0200 Subject: [PATCH] Added source code --- attach.c | 1318 ++++++++++++++ basic.c | 878 +++++++++ bind.c | 420 +++++ blddate.c | 56 + browse.c | 2586 ++++++++++++++++++++++++++ buffer.c | 367 ++++ cc5.sol | 74 + composer.c | 4296 ++++++++++++++++++++++++++++++++++++++++++++ display.c | 2572 ++++++++++++++++++++++++++ ebind.h | 165 ++ edef.h | 181 ++ efunc.h | 342 ++++ estruct.h | 439 +++++ file.c | 1011 +++++++++++ fileio.c | 159 ++ headers.h | 80 + line.c | 783 ++++++++ main.c | 707 ++++++++ makefile.3b1 | 94 + makefile.a32 | 88 + makefile.a41 | 88 + makefile.aix | 88 + makefile.att | 89 + makefile.aux | 88 + makefile.bs2 | 88 + makefile.bsd | 89 + makefile.bsf | 90 + makefile.bsi | 88 + makefile.bso | 102 ++ makefile.cvx | 88 + makefile.cyg | 90 + makefile.d-g | 91 + makefile.dpx | 95 + makefile.dyn | 88 + makefile.epx | 91 + makefile.ga4 | 88 + makefile.gen | 89 + makefile.gh9 | 89 + makefile.go5 | 94 + makefile.gso | 99 + makefile.gsu | 89 + makefile.gul | 89 + makefile.hpp | 90 + makefile.isc | 89 + makefile.lnx | 94 + makefile.lyn | 88 + makefile.mct | 89 + makefile.mnt | 88 + makefile.msc | 116 ++ makefile.neb | 88 + makefile.nto | 88 + makefile.nxt | 89 + makefile.os2 | 134 ++ makefile.osf | 88 + makefile.osx | 88 + makefile.pt1 | 88 + makefile.ptx | 88 + makefile.s40 | 88 + makefile.sc5 | 94 + makefile.sco | 93 + makefile.sgi | 88 + makefile.soc | 90 + makefile.sol | 97 + makefile.sun | 88 + makefile.sv4 | 90 + makefile.ult | 88 + makefile.uw2 | 90 + makefile.vul | 88 + msdlg.c | 1003 +++++++++++ msmem.c | 1301 ++++++++++++++ msmenu.h | 107 ++ osdep/dos | 624 +++++++ osdep/dos_gen.h | 41 + osdep/dosgen | 1274 +++++++++++++ osdep/fsync.non | 50 + osdep/getcwd | 17 + osdep/header | 32 + osdep/includer.c | 76 + osdep/makedep | 26 + osdep/makefile | 73 + osdep/makefile.bas | 35 + osdep/makefile.dl | 73 + osdep/makefile.dos | 27 + osdep/os-3b1.h | 191 ++ osdep/os-3b1.ic | 15 + osdep/os-a32.h | 189 ++ osdep/os-a32.ic | 15 + osdep/os-a41.h | 184 ++ osdep/os-a41.ic | 15 + osdep/os-aix.h | 181 ++ osdep/os-aix.ic | 15 + osdep/os-att.h | 181 ++ osdep/os-att.ic | 15 + osdep/os-aux.h | 189 ++ osdep/os-aux.ic | 15 + osdep/os-bs2.h | 178 ++ osdep/os-bs2.ic | 15 + osdep/os-bsd.h | 184 ++ osdep/os-bsd.ic | 17 + osdep/os-bsf.h | 182 ++ osdep/os-bsf.ic | 15 + osdep/os-bsi.h | 179 ++ osdep/os-bsi.ic | 15 + osdep/os-bso.h | 180 ++ osdep/os-bso.ic | 15 + osdep/os-cvx.h | 181 ++ osdep/os-cvx.ic | 15 + osdep/os-cyg.h | 192 ++ osdep/os-cyg.ic | 15 + osdep/os-dos.h | 195 ++ osdep/os-dos.ic | 11 + osdep/os-dpx.h | 180 ++ osdep/os-dpx.ic | 15 + osdep/os-dyn.h | 190 ++ osdep/os-dyn.ic | 17 + osdep/os-gen.h | 173 ++ osdep/os-gen.ic | 15 + osdep/os-gso.h | 178 ++ osdep/os-gsu.h | 174 ++ osdep/os-hpp.h | 175 ++ osdep/os-hpp.ic | 15 + osdep/os-isc.h | 193 ++ osdep/os-isc.ic | 17 + osdep/os-lnx.h | 194 ++ osdep/os-lnx.ic | 15 + osdep/os-lyn.h | 175 ++ osdep/os-lyn.ic | 17 + osdep/os-mct.h | 173 ++ osdep/os-mnt.h | 188 ++ osdep/os-mnt.ic | 15 + osdep/os-neb.h | 183 ++ osdep/os-neb.ic | 15 + osdep/os-nto.h | 179 ++ osdep/os-nto.ic | 15 + osdep/os-nxt.h | 172 ++ osdep/os-nxt.ic | 17 + osdep/os-os2.h | 186 ++ osdep/os-os2.ic | 11 + osdep/os-osf.h | 187 ++ osdep/os-osf.ic | 15 + osdep/os-osx.h | 194 ++ osdep/os-osx.ic | 15 + osdep/os-pt1.h | 188 ++ osdep/os-pt1.ic | 15 + osdep/os-ptx.h | 185 ++ osdep/os-ptx.ic | 15 + osdep/os-s40.h | 183 ++ osdep/os-s40.ic | 15 + osdep/os-sc5.h | 187 ++ osdep/os-sc5.ic | 15 + osdep/os-sco.h | 195 ++ osdep/os-sco.ic | 19 + osdep/os-sgi.h | 183 ++ osdep/os-sgi.ic | 15 + osdep/os-sol.h | 178 ++ osdep/os-sun.h | 181 ++ osdep/os-sun.ic | 15 + osdep/os-sv4.h | 183 ++ osdep/os-sv4.ic | 15 + osdep/os-ult.h | 173 ++ osdep/os-ult.ic | 15 + osdep/os2 | 1712 ++++++++++++++++++ osdep/raw.brk | 216 +++ osdep/raw.io | 178 ++ osdep/raw.ios | 182 ++ osdep/read.pol | 95 + osdep/read.sel | 90 + osdep/spell.ms | 246 +++ osdep/spell.os2 | 117 ++ osdep/spell.unx | 255 +++ osdep/term.ans | 166 ++ osdep/term.cap | 774 ++++++++ osdep/term.dos | 648 +++++++ osdep/term.inf | 751 ++++++++ osdep/truncate | 27 + osdep/unix | 4170 ++++++++++++++++++++++++++++++++++++++++++ pico-win.lnk | 6 + pico.c | 1749 ++++++++++++++++++ pico.h | 605 +++++++ picolib.def | 94 + pilot.c | 350 ++++ random.c | 469 +++++ region.c | 373 ++++ resource.h | 134 ++ search.c | 874 +++++++++ vmsbuild.com | 62 + window.c | 60 + word.c | 644 +++++++ 188 files changed, 48888 insertions(+) create mode 100644 attach.c create mode 100644 basic.c create mode 100644 bind.c create mode 100644 blddate.c create mode 100644 browse.c create mode 100644 buffer.c create mode 100755 cc5.sol create mode 100644 composer.c create mode 100644 display.c create mode 100644 ebind.h create mode 100644 edef.h create mode 100644 efunc.h create mode 100644 estruct.h create mode 100644 file.c create mode 100644 fileio.c create mode 100644 headers.h create mode 100644 line.c create mode 100755 main.c create mode 100644 makefile.3b1 create mode 100644 makefile.a32 create mode 100644 makefile.a41 create mode 100644 makefile.aix create mode 100644 makefile.att create mode 100644 makefile.aux create mode 100644 makefile.bs2 create mode 100644 makefile.bsd create mode 100644 makefile.bsf create mode 100644 makefile.bsi create mode 100644 makefile.bso create mode 100644 makefile.cvx create mode 100644 makefile.cyg create mode 100644 makefile.d-g create mode 100644 makefile.dpx create mode 100644 makefile.dyn create mode 100644 makefile.epx create mode 100644 makefile.ga4 create mode 100644 makefile.gen create mode 100644 makefile.gh9 create mode 100644 makefile.go5 create mode 100644 makefile.gso create mode 100644 makefile.gsu create mode 100644 makefile.gul create mode 100644 makefile.hpp create mode 100644 makefile.isc create mode 100644 makefile.lnx create mode 100644 makefile.lyn create mode 100644 makefile.mct create mode 100644 makefile.mnt create mode 100644 makefile.msc create mode 100644 makefile.neb create mode 100644 makefile.nto create mode 100644 makefile.nxt create mode 100644 makefile.os2 create mode 100644 makefile.osf create mode 100644 makefile.osx create mode 100644 makefile.pt1 create mode 100644 makefile.ptx create mode 100644 makefile.s40 create mode 100644 makefile.sc5 create mode 100644 makefile.sco create mode 100644 makefile.sgi create mode 100644 makefile.soc create mode 100644 makefile.sol create mode 100644 makefile.sun create mode 100644 makefile.sv4 create mode 100644 makefile.ult create mode 100644 makefile.uw2 create mode 100644 makefile.vul create mode 100644 msdlg.c create mode 100644 msmem.c create mode 100644 msmenu.h create mode 100644 osdep/dos create mode 100644 osdep/dos_gen.h create mode 100644 osdep/dosgen create mode 100644 osdep/fsync.non create mode 100644 osdep/getcwd create mode 100644 osdep/header create mode 100644 osdep/includer.c create mode 100755 osdep/makedep create mode 100644 osdep/makefile create mode 100644 osdep/makefile.bas create mode 100644 osdep/makefile.dl create mode 100644 osdep/makefile.dos create mode 100644 osdep/os-3b1.h create mode 100644 osdep/os-3b1.ic create mode 100644 osdep/os-a32.h create mode 100644 osdep/os-a32.ic create mode 100644 osdep/os-a41.h create mode 100644 osdep/os-a41.ic create mode 100644 osdep/os-aix.h create mode 100644 osdep/os-aix.ic create mode 100644 osdep/os-att.h create mode 100644 osdep/os-att.ic create mode 100644 osdep/os-aux.h create mode 100644 osdep/os-aux.ic create mode 100644 osdep/os-bs2.h create mode 100644 osdep/os-bs2.ic create mode 100644 osdep/os-bsd.h create mode 100644 osdep/os-bsd.ic create mode 100644 osdep/os-bsf.h create mode 100644 osdep/os-bsf.ic create mode 100644 osdep/os-bsi.h create mode 100644 osdep/os-bsi.ic create mode 100644 osdep/os-bso.h create mode 100644 osdep/os-bso.ic create mode 100644 osdep/os-cvx.h create mode 100644 osdep/os-cvx.ic create mode 100644 osdep/os-cyg.h create mode 100644 osdep/os-cyg.ic create mode 100644 osdep/os-dos.h create mode 100644 osdep/os-dos.ic create mode 100644 osdep/os-dpx.h create mode 100644 osdep/os-dpx.ic create mode 100644 osdep/os-dyn.h create mode 100644 osdep/os-dyn.ic create mode 100644 osdep/os-gen.h create mode 100644 osdep/os-gen.ic create mode 100644 osdep/os-gso.h create mode 100644 osdep/os-gsu.h create mode 100644 osdep/os-hpp.h create mode 100644 osdep/os-hpp.ic create mode 100644 osdep/os-isc.h create mode 100644 osdep/os-isc.ic create mode 100644 osdep/os-lnx.h create mode 100644 osdep/os-lnx.ic create mode 100644 osdep/os-lyn.h create mode 100644 osdep/os-lyn.ic create mode 100644 osdep/os-mct.h create mode 100644 osdep/os-mnt.h create mode 100644 osdep/os-mnt.ic create mode 100644 osdep/os-neb.h create mode 100644 osdep/os-neb.ic create mode 100644 osdep/os-nto.h create mode 100644 osdep/os-nto.ic create mode 100644 osdep/os-nxt.h create mode 100644 osdep/os-nxt.ic create mode 100644 osdep/os-os2.h create mode 100644 osdep/os-os2.ic create mode 100644 osdep/os-osf.h create mode 100644 osdep/os-osf.ic create mode 100644 osdep/os-osx.h create mode 100644 osdep/os-osx.ic create mode 100644 osdep/os-pt1.h create mode 100644 osdep/os-pt1.ic create mode 100644 osdep/os-ptx.h create mode 100644 osdep/os-ptx.ic create mode 100644 osdep/os-s40.h create mode 100644 osdep/os-s40.ic create mode 100644 osdep/os-sc5.h create mode 100644 osdep/os-sc5.ic create mode 100644 osdep/os-sco.h create mode 100644 osdep/os-sco.ic create mode 100644 osdep/os-sgi.h create mode 100644 osdep/os-sgi.ic create mode 100644 osdep/os-sol.h create mode 100644 osdep/os-sun.h create mode 100644 osdep/os-sun.ic create mode 100644 osdep/os-sv4.h create mode 100644 osdep/os-sv4.ic create mode 100644 osdep/os-ult.h create mode 100644 osdep/os-ult.ic create mode 100644 osdep/os2 create mode 100644 osdep/raw.brk create mode 100644 osdep/raw.io create mode 100644 osdep/raw.ios create mode 100644 osdep/read.pol create mode 100644 osdep/read.sel create mode 100644 osdep/spell.ms create mode 100644 osdep/spell.os2 create mode 100644 osdep/spell.unx create mode 100644 osdep/term.ans create mode 100644 osdep/term.cap create mode 100644 osdep/term.dos create mode 100644 osdep/term.inf create mode 100644 osdep/truncate create mode 100755 osdep/unix create mode 100644 pico-win.lnk create mode 100644 pico.c create mode 100644 pico.h create mode 100644 picolib.def create mode 100644 pilot.c create mode 100644 random.c create mode 100644 region.c create mode 100644 resource.h create mode 100644 search.c create mode 100755 vmsbuild.com create mode 100644 window.c create mode 100644 word.c diff --git a/attach.c b/attach.c new file mode 100644 index 0000000..3c39444 --- /dev/null +++ b/attach.c @@ -0,0 +1,1318 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: attach.c 13711 2004-06-15 22:22:35Z hubert $"; +#endif +/* + * Program: Routines to support attachments in the Pine composer + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +#include "headers.h" +#include + +#ifdef ATTACHMENTS + + +#ifdef ANSI + int ParseAttach(struct hdr_line **,int *,char *, + int,char *,char *,int,int *); + PATMT *NewAttach(char *, long, char *); + void ZotAttach(struct pico_atmt *); + void sinserts(char *, int, char *, int); + int AttachUpload(char *, char *); + int AttachCancel(char *); +#else + int ParseAttach(); + PATMT *NewAttach(); + void ZotAttach(); + void sinserts(); + int AttachUpload(); + int AttachCancel(); +#endif + +#define HIBIT_WARN "Only ASCII characters allowed in attachment comments" + + +/* + * AskAttach - ask for attachment fields and build resulting structure + * return pointer to that struct if OK, NULL otherwise + */ +AskAttach(cmnt, lm) +char *cmnt; +LMLIST **lm; +{ + int i, status, fbrv, upload = 0; + int fb_flags = FB_READ | FB_ATTACH; + off_t attsz = 0; + char bfn[NLINE]; + char fn[NLINE], sz[32]; + LMLIST *new; + + i = 2; + fn[0] = '\0'; + sz[0] = '\0'; + cmnt[0] = '\0'; + + while(i){ + if(i == 2){ + EXTRAKEYS menu_attach[4]; + int n; + + menu_attach[n = 0].name = "^T"; + menu_attach[n].label = "To Files"; + menu_attach[n].key = (CTRL|'T'); + + if(gmode & MDCMPLT){ + menu_attach[++n].name = "TAB"; + menu_attach[n].label = "Complete"; + menu_attach[n].key = (CTRL|'I'); + } + +#if !defined(DOS) && !defined(MAC) + if(Pmaster && Pmaster->upload){ + /* + * The Plan: ^R prompts for uploaded file's name which + * is passed to the defined upload command when the user + * hits Return to confirm the name. + * NOTE: this is different than upload into message + * text in which case the uploaded name isn't useful so + * a temp file is ok (be sure to fix the file mode). + */ + menu_attach[++n].name = "^Y"; + menu_attach[n].key = (CTRL|'Y'); + menu_attach[n].label = upload ? "Read File" : "RcvUpload"; + } +#endif + + menu_attach[++n].name = NULL; + KS_OSDATASET(&menu_attach[0], KS_NONE); + status = mlreply(upload ? "Name to give uploaded attachment: " + : "File to attach: ", + fn, NLINE, QNORML, menu_attach); + } + else + status = mlreply("Attachment comment: ", cmnt, NLINE, QNODQT, NULL); + + switch(status){ + case HELPCH: + if(Pmaster){ + VARS_TO_SAVE *saved_state; + + saved_state = save_pico_state(); + (*Pmaster->helper)(Pmaster->attach_help, "Attach Help", 1); + if(saved_state){ + restore_pico_state(saved_state); + free_pico_state(saved_state); + } + + pico_refresh(FALSE, 1); + update(); + continue; + } + else{ + emlwrite("No Attachment %s help yet!", + (i == 2) ? "file" : "comment"); + sleep(3); + } + + break; + + case (CTRL|'I') : + if(i == 2){ + char *fname, *p; + int dirlen, l = NLINE; /* length of buffer space for bfn */ + + bfn[0] = '\0'; + if(*fn && (p = strrchr(fn, C_FILESEP))){ + fname = p + 1; + l -= fname - fn; + dirlen = p - fn; + if(p == fn) + strcpy(bfn, S_FILESEP); +#ifdef DOS + else if(fn[0] == C_FILESEP + || (isalpha((unsigned char)fn[0]) + && fn[1] == ':')){ + if(fn[1] == ':' && p == fn+2) + dirlen = fname - fn; +#else + else if (fn[0] == C_FILESEP || fn[0] == '~') { +#endif + strncpy(bfn, fn, dirlen); + bfn[dirlen] = '\0'; + } + else + sprintf(bfn, "%s%c%.*s", + (gmode & MDCURDIR) + ? "." + : ((gmode & MDTREE) || opertree[0]) + ? opertree : gethomedir(NULL), + C_FILESEP, p - fn, fn); + } + else{ + fname = fn; + strcpy(bfn, (gmode & MDCURDIR) + ? "." + : ((gmode & MDTREE) || opertree[0]) + ? opertree : gethomedir(NULL)); + } + + if(!pico_fncomplete(bfn, fname, l - 1)) + (*term.t_beep)(); + } + else + (*term.t_beep)(); + + break; + + case (CTRL|'T'): + if(i != 2){ + (*term.t_beep)(); + break; + } + + *bfn = '\0'; + if(*fn == '\0' || !isdir(fn, NULL, NULL)) + strcpy(fn, (gmode & MDCURDIR) + ? (browse_dir[0] ? browse_dir : ".") + : ((gmode & MDTREE) || opertree[0]) + ? opertree + : (browse_dir[0] ? browse_dir + : gethomedir(NULL))); + if((fbrv = FileBrowse(fn, NLINE, bfn, NLINE, sz, + upload ? fb_flags + : fb_flags|FB_LMODEPOS, + upload ? NULL + : lm)) == 1){ + if (upload && (strlen(fn)+strlen(S_FILESEP)+strlen(bfn)) < NLINE){ + + if((new=(LMLIST *)malloc(sizeof(*new))) == NULL + || (new->fname=malloc(strlen(bfn)+1)) == NULL + || (new->dir=malloc(strlen(fn)+1)) == NULL){ + emlwrite("\007Can't malloc space for filename", NULL); + return(-1); + } + + strcpy(new->fname, bfn); + strcpy(new->dir, fn); + strncpy(new->size, sz, sizeof(new->size)-1); + new->size[sizeof(new->size)-1] = '\0'; + new->next = NULL; + *lm = new; + + strcat(fn, S_FILESEP); + strcat(fn, bfn); + if(!AttachUpload(fn, sz)){ + i = 2; /* keep prompting for file */ + sleep(3); /* problem, show error! */ + } + else{ + i--; /* go prompt for comment */ + } + } + else if(!upload){ + if(lm && *lm && !(*lm)->next) /* get comment */ + i--; + else{ /* no comments if multiple files */ + update(); + return(1); + } + } + else{ /* trouble */ + *fn = '\0'; + AttachCancel(fn); + pico_refresh(FALSE,1); + update(); + emlwrite("\007File name too BIG, cannot select!", NULL); + sleep(3); + } + } + else if (!fbrv) + *fn = '\0'; + else{ + *fn = '\0'; + AttachCancel(fn); + pico_refresh(FALSE, 1); + update(); + emlwrite("\007File name too big, cannot select!", NULL); + sleep(3); + } + + /* fall thru to clean up the screen */ + + case (CTRL|'L'): + pico_refresh(FALSE, 1); + update(); + continue; + +#if !defined(DOS) && !defined(MAC) + case (CTRL|'Y'): /* upload? */ + if(i == 2) + upload ^= 1; /* flip mode */ + else + (*term.t_beep)(); + + break; +#endif + + case ABORT: + return(AttachCancel((upload && i == 1) ? fn : NULL)); + + case TRUE: /* some comment */ + case FALSE: /* No comment */ + if(i-- == 2){ + if(upload){ + fixpath(fn, NLINE); /* names relative to ~ */ + status = AttachUpload(fn, sz); + pico_refresh(FALSE, 1); + update(); + if(!status){ + i = 2; /* keep prompting for file */ + sleep(3); /* problem, show error! */ + } + } + else { + if(*fn == '\"' && fn[strlen(fn)-1] == '\"'){ + int j; + + for(j = 0; fn[j] = fn[j+1]; j++) + ; + + fn[j-1] = '\0'; + } + + if(fn[0]){ + if((gmode & MDTREE) + && !compresspath(opertree, fn, NLINE)){ + emlwrite( + "Restricted mode allows attachments from %s only: too many ..'s", + (gmode&MDSCUR) ? "home directory" : opertree); + return(0); + } + else{ + fixpath(fn, NLINE); /* names relative to ~ */ + if((gmode&MDTREE) && !in_oper_tree(fn)){ + emlwrite( + "\007Restricted mode allows attachments from %s only", + (gmode&MDSCUR) ? "home directory" : opertree); + return(0); + } + } + + if((status = fexist(fn, "r", &attsz)) != FIOSUC){ + fioperr(status, fn); /* file DOESN'T exist! */ + return(0); + } + + if((new=(LMLIST *)malloc(sizeof(*new))) == NULL + || (new->fname=malloc(strlen(fn)+1)) == NULL){ + emlwrite("\007Can't malloc space for filename", NULL); + return(-1); + } + + new->dir = NULL; + strcpy(new->fname, fn); + strcpy(new->size, prettysz(attsz)); + new->next = NULL; + *lm = new; + } + else + return(AttachCancel((upload && i == 1) ? fn : NULL)); + } + } + else{ + mlerase(); + return(1); /* mission accomplished! */ + } + + break; + default: + break; + } + } + + return(0); +} + + +/* + * AttachUpload - Use call back to run the external upload command. + */ +int +AttachUpload(fn, sz) + char *fn, *sz; +{ + long l; + + if(gmode&MDSCUR){ + emlwrite("\007Restricted mode disallows uploaded command", NULL); + return(0); + } + + if(Pmaster && Pmaster->upload && (*Pmaster->upload)(fn, &l)){ + strcpy(sz, prettysz((off_t)l)); + return(1); + } + + return(0); +} + + +/* + * AttachCancel - + */ +int +AttachCancel(fn) + char *fn; +{ + emlwrite("Attach cancelled", NULL); + if(fn && fn[0]) + unlink(fn); /* blast uploaded file */ + + return(0); +} + + +extern struct headerentry *headents; + +/* + * SyncAttach - given a pointer to a linked list of attachment structures, + * return with that structure sync'd with what's displayed. + * delete any attachments in list of structs that's not on + * the display, and add any that aren't in list but on display. + */ +SyncAttach() +{ + int offset = 0, /* the offset to begin */ + rv = 0, + ki = 0, /* number of known attmnts */ + bi = 0, /* build array index */ + nbld = 0, /* size of build array */ + na, /* old number of attachmnt */ + status, i, j, n = 0; + char file[NLINE], /* buffers to hold it all */ + size[32], + comment[1024]; + struct hdr_line *lp; /* current line in header */ + struct headerentry *entry; + PATMT *tp, **knwn = NULL, **bld; + + for(entry = headents; entry->name != NULL; entry++) { + if(entry->is_attach) + break; + } + + if(Pmaster == NULL) + return(-1); + + for(tp = Pmaster->attachments; tp; tp = tp->next) + ki++; /* Count known attachments */ + + if(ki){ + if((knwn = (PATMT **)malloc((ki+1) * (sizeof(PATMT *)))) == NULL){ + emlwrite("\007Can't allocate space for %d known attachment array entries", + (void *) (ki + 1)); + rv = -1; + goto exit_early; + } + for(i=0, tp = Pmaster->attachments; i < ki; i++, tp = tp->next){ + knwn[i] = tp; /* fill table of */ + /* known attachments */ + } + } + + + /* + * As a quick hack to avoid too many reallocs, check to see if + * there are more header lines than known attachments. + */ + for(lp = entry->hd_text; lp ; lp = lp->next) + nbld++; /* count header lines */ + nbld = nbld > ki ? nbld : ki + 1; + + if((bld = (PATMT **)malloc(nbld * (sizeof(PATMT *)))) == NULL){ + emlwrite("\007Can't allocate space for %d build array entries", + (void *) nbld); + rv = -1; + goto exit_early; + } + + lp = entry->hd_text; + while(lp != NULL){ + char fn[NLINE]; + na = ++n; + + if(bi == nbld){ /* need to grow build array? */ + if((bld = (PATMT **)realloc(bld, ++nbld * sizeof(PATMT *))) == NULL){ + emlwrite("\007Can't resize build array to %d entries ", + (void *) nbld); + rv = -1; + goto exit_early; + } + } + + if(status = ParseAttach(&lp, &offset, file, NLINE, size, + comment, 1024, &na)) + rv = (rv < 0) ? rv : status ; /* remember worst case */ + + if(*file == '\0'){ + if(n != na && na > 0 && na <= ki && (knwn[na-1]->flags & A_FLIT)){ + bld[bi++] = knwn[na-1]; + knwn[na-1] = NULL; + } + continue; + } + + if((gmode&MDTREE) + && file[0] != '[' + && (!in_oper_tree(file) + || !compresspath(file, fn, NLINE))) + /* no attachments outside ~ in secure mode! */ + continue; + + tp = NULL; + for(i = 0; i < ki; i++){ /* already know about it? */ + /* + * this is kind of gruesome. what we want to do is keep track + * of literal attachment entries because they may not be + * actual files we can access or that the user can readily + * access. + */ + if(knwn[i] + && ((!(knwn[i]->flags&A_FLIT) + && !strcmp(file, knwn[i]->filename)) + || ((knwn[i]->flags&A_FLIT) && i+1 == na))){ + tp = knwn[i]; + knwn[i] = NULL; /* forget we know about it */ + + if(status == -1) /* ignore garbage! */ + break; + + if((tp->flags&A_FLIT) && strcmp(file, tp->filename)){ + rv = 1; + if((j=strlen(file)) > strlen(tp->filename)){ + if((tp->filename = (char *)realloc(tp->filename, + sizeof(char)*(j+1))) == NULL){ + emlwrite("\007Can't realloc filename space",NULL); + rv = -1; + goto exit_early; + } + } + + strcpy(tp->filename, file); + } + else if(tp->size && strcmp(tp->size, size)){ + rv = 1; + if((j=strlen(size)) > strlen(tp->size)){ + if((tp->size=(char *)realloc(tp->size, + sizeof(char)*(j+1))) == NULL){ + emlwrite("\007Can't realloc space for size", NULL); + rv = -1; + goto exit_early; + } + } + + strcpy(tp->size, size); + } + + if(strcmp(tp->description, comment)){ /* new comment */ + rv = 1; + if((j=strlen(comment)) > strlen(tp->description)){ + if((tp->description=(char *)realloc(tp->description, + sizeof(char)*(j+1))) == NULL){ + emlwrite("\007Can't realloc description", NULL); + rv = -1; + goto exit_early; + } + } + + strcpy(tp->description, comment); + } + break; + } + } + + if(tp){ + bld[bi++] = tp; + } + else{ + if(file[0] != '['){ + if((tp = NewAttach(file, atol(size), comment)) == NULL){ + rv = -1; + goto exit_early; + } + bld[bi++] = tp; + } + else break; + } + + if(status < 0) + tp->flags |= A_ERR; /* turn ON error bit */ + else + tp->flags &= ~(A_ERR); /* turn OFF error bit */ + } + + if(bi){ + for(i=0; i < bi-1; i++) /* link together newly built list */ + bld[i]->next = bld[i+1]; + + bld[i]->next = NULL; /* tie it off */ + Pmaster->attachments = bld[0]; + } + else + Pmaster->attachments = NULL; + +exit_early: + if(knwn){ + for(i = 0; i < ki; i++){ /* kill old/unused references */ + if(knwn[i]){ + ZotAttach(knwn[i]); + free((char *) knwn[i]); + } + } + free((void *)knwn); + } + + if(bld) + free((void *)bld); + + return(rv); +} + + + + +/* + * ParseAttach - given a header line and an offset into it, return with + * the three given fields filled in. Size of fn and cmnt + * buffers should be passed in fnlen and cmntlen. + * Always updates header fields that have changed or are + * fixed. An error advances offset to next attachment. + * + * returns: 1 if a field changed + * 0 nothing changed + * -1 on error + */ +ParseAttach(lp, off, fn, fnlen, sz, cmnt, cmntlen, no) +struct hdr_line **lp; /* current header line */ +int *off; /* offset into that line */ +char *fn; /* return file name field */ +int fnlen; /* fn buffer size */ +char *sz, *cmnt; /* places to return fields */ +int cmntlen, *no; /* attachment number */ +{ + int j, status, bod, eod = -1, + rv = 0, /* return value */ + orig_offset, + lbln = 0, /* label'd attachment */ + hibit = 0, + quoted = 0, + escaped = 0; + off_t attsz; /* attachment length */ + char tmp[1024], + c, + c_lookahead, + *p, + *lblsz = NULL, /* label'd attchmnt's size */ + number[8]; + register struct hdr_line *lprev; + enum { /* parse levels */ + LWS, /* leading white space */ + NUMB, /* attachment number */ + WSN, /* white space after number */ + TAG, /* attachments tag (fname) */ + WST, /* white space after tag */ + ASIZE, /* attachments size */ + SWS, /* white space after size */ + CMMNT, /* attachment comment */ + TG} level; /* trailing garbage */ + + *fn = *sz = *cmnt = '\0'; /* initialize return strings */ + p = tmp; + orig_offset = bod = *off; + + level = LWS; /* start at beginning */ + while(*lp != NULL){ + + if((c=(*lp)->text[*off]) == '\0'){ /* end of display line */ + if(level == LWS && bod != *off){ + (*lp)->text[bod] = '\0'; + rv = 1; + } + lprev = *lp; + if((*lp = (*lp)->next) != NULL) + c = (*lp)->text[*off = bod = 0]; /* reset offset */ + } + + if(c != '\0') + c_lookahead = (*lp)->text[*off + 1]; + + switch(level){ + case LWS: /* skip leading white space */ + if(isspace((unsigned char)c) || c == ','){ + c = ' '; + break; + } + + if(c == '\0'){ + if(bod > 0 && *off >= bod && lprev){ + lprev->text[bod - 1] = '\0'; + rv = 1; + } + } + else if(*off > bod && *lp){ /* wipe out whitespace */ + (void)bcopy(&(*lp)->text[*off], &(*lp)->text[bod], + strlen(&(*lp)->text[*off]) + 1); + *off = bod; /* reset pointer */ + rv = 1; + } + + if(c == '\0') + break; + + if(!isdigit((unsigned char)c)){ /* add a number */ + sprintf(number, "%d. ", *no); + *no = 0; /* no previous number! */ + sinserts((*lp == NULL) ? &lprev->text[*off] + : &(*lp)->text[*off], + 0, number, j=strlen(number)); + *off += j - 1; + rv = 1; + level = TAG; /* interpret the name */ + break; + } + level = NUMB; + case NUMB: /* attachment number */ + if(c == '\0' || c == ','){ /* got to end, no number yet */ + *p = '\0'; + sprintf(number, "%d. ", *no); + *no = 0; /* no previous number! */ + if(c == '\0') + *lp = lprev; /* go back and look at prev */ + + c = (*lp)->text[*off = orig_offset]; /* reset offset */ + sinserts((*lp == NULL) ? &lprev->text[*off] + : &(*lp)->text[*off], + 0, number, j=strlen(number)); + *off += j - 1; + rv = 1; + p = tmp; + level = WSN; /* what's next... */ + break; + } + else if(c == '.' && isspace((unsigned char)c_lookahead)){ + /* finished grabbing number */ + /* if not space is not number */ + /* + * replace number if it's not right + */ + *p = '\0'; + sprintf(number, "%d", *no); /* record the current... */ + *no = atoi(tmp); /* and the old place in list */ + if(strcmp(number, tmp)){ + if(p-tmp > *off){ /* where to begin replacemnt */ + j = (p-tmp) - *off; + sinserts((*lp)->text, *off, "", 0); + sinserts(&lprev->text[strlen(lprev->text)-j], j, + number, strlen(number)); + *off = 0; + } + else{ + j = (*off) - (p-tmp); + sinserts((*lp == NULL) ? &lprev->text[j] + : &(*lp)->text[j], + p-tmp , number, strlen(number)); + *off += strlen(number) - (p-tmp); + } + rv = 1; + } + + p = tmp; + level = WSN; /* what's next... */ + } + else if(c < '0' || c > '9'){ /* Must be part of tag */ + sprintf(number, "%d. ", *no); + sinserts((*lp == NULL) ? &lprev->text[(*off) - (p - tmp)] + : &(*lp)->text[(*off) - (p - tmp)], + 0, number, j=strlen(number)); + *off += j; + level = TAG; /* interpret the name */ + goto process_tag; /* in case already past end of tag */ + } + else + *p++ = c; + + break; + + case WSN: /* blast whitespace */ + if(isspace((unsigned char)c) || c == '\0'){ + break; + } + else if(c == '['){ /* labeled attachment */ + lbln++; + } + else if(c == ',' || c == ' '){ + emlwrite("\007Attchmnt: '%c' not allowed in file name", + (void *)(int)c); + rv = -1; + level = TG; /* eat rest of garbage */ + break; + } + level = TAG; + case TAG: /* get and check filename */ + /* or labeled attachment */ +process_tag: /* enclosed in [] */ + if(c == '\0' + || (lbln && c == ']') + || (quoted && p != tmp && c == '\"') + || (!(lbln || quoted) + && (isspace((unsigned char) c) || strchr(",(\"", c)))){ + if(p == tmp){ + if(c == '\"') + quoted++; + } + else{ + *p = '\0'; /* got something */ + + if (strlen(tmp) > fnlen) + emlwrite("File name too big!",NULL); + strncpy(fn, tmp, fnlen); /* store file name */ + if(!lbln){ /* normal file attachment */ + if((gmode & MDTREE) + && !compresspath(opertree, fn, fnlen)){ + emlwrite( + "Attachments allowed only from %s: too many ..'s", + (gmode&MDSCUR) ? "home directory" : opertree); + rv = -1; + level = TG; + break; + } + else{ + fixpath(fn, fnlen); + if((status=fexist(fn, "r", &attsz)) != FIOSUC){ + fioperr(status, fn); + rv = -1; + level = TG; /* munch rest of garbage */ + break; + } + + if((gmode & MDTREE) && !in_oper_tree(fn)){ + emlwrite("\007Attachments allowed only from %s", + (gmode&MDSCUR) ? "home directory" + : opertree); + rv = -1; + level = TG; + break; + } + } + + if(strcmp(fn, tmp)){ /* fn changed: display it */ + if(*off >= p - tmp){ /* room for it? */ + sinserts((*lp == NULL)? + &lprev->text[(*off)-(p-tmp)] : + &(*lp)->text[(*off)-(p-tmp)], + p-tmp, fn, j=strlen(fn)); + *off += j - (p - tmp); /* advance offset */ + rv = 1; + } + else{ + emlwrite("\007Attchmnt: Problem displaying real file path", NULL); + } + } + } + else{ /* labelled attachment! */ + /* + * should explain about labelled attachments: + * these are attachments that came into the composer + * with meaningless file names (up to caller of + * composer to decide), for example, attachments + * being forwarded from another message. here, we + * just make sure the size stays what was passed + * to us. The user is SOL if they change the label + * since, as it is now, after changed, it will + * just get dropped from the list of what gets + * passed back to the caller. + */ + PATMT *tp; + + if(c != ']'){ /* legit label? */ + emlwrite("\007Attchmnt: Expected ']' after \"%s\"", + fn); + rv = -1; + level = TG; + break; + } + strcat(fn, "]"); + + /* + * This is kind of cheating since otherwise + * ParseAttach doesn't know about the attachment + * struct. OK if filename's not found as it will + * get taken care of later... + */ + tp = Pmaster->attachments; /* caller check Pmaster! */ + j = 0; + while(tp != NULL){ + if(++j == *no){ + lblsz = tp->size; + break; + } + tp = tp->next; + } + + if(tp == NULL){ + emlwrite("\007Attchmnt: Unknown reference: %s",fn); + lblsz = "XXX"; + } + } + + p = tmp; /* reset p in tmp */ + level = WST; + } + + if(!lbln && c == '(') /* no space 'tween file, size*/ + level = ASIZE; + else if(c == '\0' + || (!(lbln || quoted) && (c == ',' || c == '\"'))){ + strcpy(sz, (lblsz) ? lblsz : prettysz(attsz)); + sprintf(tmp, " (%s) %s", sz, (c == '\"') ? "" : "\"\""); + sinserts((*lp == NULL) ? &lprev->text[*off] + : &(*lp)->text[*off], + 0, tmp, j = strlen(tmp)); + *off += j; + rv = 1; + level = (c == '\"') ? CMMNT : TG;/* cmnt or eat trash */ + } + } + else if(!(lbln || quoted) + && (c == ',' || c == ' ' || c == '[' || c == ']')){ + emlwrite("\007Attchmnt: '%c' not allowed in file name", + (void *)(int)c); + rv = -1; /* bad char in file name */ + level = TG; /* gobble garbage */ + } + else + *p++ = c; /* add char to name */ + + break; + + case WST: /* skip white space */ + if(!isspace((unsigned char)c)){ + /* + * whole attachment, comment or done! + */ + if(c == ',' || c == '\0' || c == '\"'){ + strcpy(sz, (lblsz) ? lblsz : prettysz(attsz)); + sprintf(tmp, " (%s) %s", sz, + (c == '\"') ? "" : "\"\""); + sinserts((*lp == NULL) ? &lprev->text[*off] + : &(*lp)->text[*off], + 0, tmp, j = strlen(tmp)); + *off += j; + rv = 1; + level = (c == '\"') ? CMMNT : TG; + lbln = 0; /* reset flag */ + } + else if(c == '('){ /* get the size */ + level = ASIZE; + } + else{ + emlwrite("\007Attchmnt: Expected '(' or '\"' after %s",fn); + rv = -1; /* bag it all */ + level = TG; + } + } + break; + + case ASIZE: /* check size */ + if(c == ')'){ /* finished grabbing size */ + *p = '\0'; + /* + * replace sizes if they don't match! + */ + strcpy(sz, tmp); + if(strcmp(sz, (lblsz) ? lblsz : prettysz(attsz))){ + strcpy(sz, (lblsz) ? lblsz : prettysz(attsz)); + if(p-tmp > *off){ /* where to begin replacemnt */ + j = (p-tmp) - *off; + sinserts((*lp)->text, *off, "", 0); + sinserts(&lprev->text[strlen(lprev->text)-j], j, + sz, strlen(sz)); + *off = 0; + } + else{ + j = (*off) - (p-tmp); + sinserts((*lp == NULL) ? &lprev->text[j] + : &(*lp)->text[j], + p-tmp , sz, strlen(sz)); + *off += strlen(sz) - (p-tmp); + } + rv = 1; + } + + p = tmp; + level = SWS; /* what's next... */ + } + else if(c == '\0' || c == ','){ + *p = '\0'; + emlwrite("\007Attchmnt: Size field missing ')': \"%s\"", tmp); + rv = -1; + level = TG; + } + else + *p++ = c; + + break; + + case SWS: /* skip white space */ + if(!isspace((unsigned char)c)){ + if(c == ','){ /* no description */ + level = TG; /* munch rest of garbage */ + lbln = 0; /* reset flag */ + } + else if(c != '\"' && c != '\0'){ + emlwrite("\007Attchmnt: Malformed comment, quotes required", NULL); + rv = -1; + level = TG; + } + else + level = CMMNT; + } + break; + + case CMMNT: /* slurp up comment */ + if((c == '\"' && !escaped) || c == '\0'){ + *p = '\0'; /* cap it off */ + p = tmp; /* reset p */ + if (strlen(tmp) > cmntlen){ + emlwrite("Comment too long!",NULL); + } + + strncpy(cmnt,tmp,cmntlen-1); /* copy the comment */ + if(c == '\0'){ + emlwrite("\007Attchmnt: Closing quote required at end of comment", NULL); + rv = -1; + } + level = TG; /* prepare for next one */ + lbln = 0; /* reset flag */ + } + else if(c == '\\' && !escaped){ /* something escaped? */ + escaped = 1; + } + else{ + if(escaped){ + if(c != '\"') /* we only quote escapes */ + *p++ = '\\'; + + escaped = 0; + } + + if(((*p++ = c) & 0x80) && (gmode & MDHBTIGN) && !hibit++) + emlwrite(HIBIT_WARN, NULL); + } + + break; + + case TG: /* get comma or final EOL */ + if(eod < 0) + eod = *off; + if(!isspace((unsigned char)c)){ + switch(c){ + case '\0': + if(eod != *off) + lprev->text[*off = eod] = '\0'; + break; + case ',': + if(eod != *off){ + (void)bcopy(&(*lp)->text[*off], &(*lp)->text[eod], + strlen(&(*lp)->text[*off]) + 1); + *off = eod; + rv = 1; + } + break; + default: + if(rv != -1) + emlwrite("\007Attchmnt: Comma must separate attachments", NULL); + rv = -1; + } + } + break; + + default: /* something's very wrong */ + emlwrite("\007Attchmnt: Weirdness in ParseAttach", NULL); + return(-1); /* just give up */ + } + + if(c == '\0') /* we're done */ + break; + + (*off)++; + + /* + * not in comment or label name? done. + */ + if(c == ',' && (level != TAG && level != CMMNT && !lbln)) + break; /* put offset past ',' */ + } + + return(rv); +} + + + +/* + * NewAttach - given a filename (assumed to accessible) and comment, creat + */ +PATMT *NewAttach(f, l, c) +char *f; +long l; +char *c; +{ + PATMT *tp; + + if((tp=(PATMT *)malloc(sizeof(PATMT))) == NULL){ + emlwrite("No memory to add attachment", NULL); + return(NULL); + } + else + memset(tp, 0, sizeof(PATMT)); + + /* file and size malloc */ + if((tp->filename = (char *)malloc(strlen(f)+1)) == NULL){ + emlwrite("Can't malloc name for attachment", NULL); + free((char *) tp); + return(NULL); + } + strcpy(tp->filename, f); + + if(l > -1){ + tp->size = (char *)malloc(sizeof(char)*(strlen(prettysz((off_t)l))+1)); + if(tp->size == NULL){ + emlwrite("Can't malloc size for attachment", NULL); + free((char *) tp->filename); + free((char *) tp); + return(NULL); + } + else + strcpy(tp->size, prettysz((off_t)l)); + } + + /* description malloc */ + if((tp->description = (char *)malloc(strlen(c)+1)) == NULL){ + emlwrite("Can't malloc description for attachment", NULL); + free((char *) tp->size); + free((char *) tp->filename); + free((char *) tp); + return(NULL); + } + strcpy(tp->description, c); + + /* callback to show user the mime type that will be used for attachment */ + if(Pmaster->mimetype && (*Pmaster->mimetype)(f) > 0){ + int rv ; + + clearcursor(); + mlerase(); + rv = (*Pmaster->showmsg)('x'); + ttresize(); + picosigs(); + if(rv) /* Did showmsg corrupt the screen? */ + PaintBody(0); /* Yes, repaint it */ + mpresf = 1; + } + + return(tp); +} + + + +/* + * AttachError - Sniff list of attachments, returning TRUE if there's + * any sign of trouble... + */ +int +AttachError() +{ + PATMT *ap; + + if(!Pmaster) + return(0); + + ap = Pmaster->attachments; + while(ap){ + if((ap->flags) & A_ERR) + return(1); + + ap = ap->next; + } + + return(FALSE); +} + + +char * +QuoteAttach(fn) +char *fn; +{ + char *p; + + if(*fn && strpbrk(fn, " \t,(\"")){ /* Quote it? */ + p = &fn[strlen(fn)]; + *(p+2) = '\0'; + *(p+1) = '\"'; + do + *p = *(p-1); + while(--p != fn); + *p = '\"'; + } + + return(fn); +} + + + +void ZotAttach(p) +PATMT *p; +{ + if(!p) + return; + if(p->description) + free((char *)p->description); + if(p->filename){ + if(p->flags & A_TMP) + unlink(p->filename); + + free((char *)p->filename); + } + if(p->size) + free((char *)p->size); + if(p->id) + free((char *)p->id); + p->next = NULL; +} +#endif /* ATTACHMENTS */ + + +/* + * intag - return TRUE if i is in a column that makes up an + * attachment line number + */ +intag(s, i) +char *s; +int i; +{ + char *p = s; + int n = 0; + + while(*p != '\0' && (p-s) < 5){ /* is there a tag? it */ + if(n && *p == '.') /* can't be more than 4 */ + return(i <= p-s); /* chars long! */ + + if(*p < '0' || *p > '9') + break; + else + n = (n * 10) + (*p - '0'); + + p++; + } + + return(FALSE); +} + + +/* + * prettysz - return pointer to string containing nice + */ +char *prettysz(l) + off_t l; +{ + static char b[32]; + long sz, left, right; + + sz = (long) l; + b[0] = '\0'; + + if(sz < 1000L){ + sprintf(b, "%ld B", sz); /* xxx B */ + } + else if(sz < 9950L){ + left = (sz + 50L) / 1000L; + right = ((sz + 50L) - left * 1000L) / 100L; + sprintf(b, "%ld.%ld KB", left, right); /* x.x KB */ + } + else if(sz < 999500L){ + sprintf(b, "%ld KB", (sz + 500L) / 1000L); /* xxx KB */ + } + else if(sz < 9950000L){ + left = (sz + 50000L) / 1000000L; + right = ((sz + 50000L) - left * 1000000L) / 100000L; + sprintf(b, "%ld.%ld MB", left, right); /* x.x MB */ + } + else{ + sprintf(b, "%ld MB", (sz + 500000L) / 1000000L); /* xxx MB */ + } + + return(b); +} + + +/* + * sinserts - s insert into another string + */ +void +sinserts(ds, dl, ss, sl) + char *ds, *ss; /* dest. and source strings */ + int dl, sl; /* their lengths */ +{ + char *dp, *edp; /* pointers into dest. */ + int j; /* jump difference */ + + if(sl >= dl){ /* source bigger than dest. */ + dp = ds + dl; /* shift dest. to make room */ + if((edp = strchr(dp, '\0')) != NULL){ + j = sl - dl; + + for( ;edp >= dp; edp--) + edp[j] = *edp; + + while(sl--) + *ds++ = *ss++; + } + else + emlwrite("\007No end of line???", NULL); /* can this happen? */ + } + else{ /* dest is longer, shrink it */ + j = dl - sl; /* difference in lengths */ + + while(sl--) /* copy ss onto ds */ + *ds++ = *ss++; + + if(strlen(ds) > j){ /* shuffle the rest left */ + do + *ds = ds[j]; + while(*ds++ != '\0'); + } + else + *ds = '\0'; + } +} diff --git a/basic.c b/basic.c new file mode 100644 index 0000000..bfdd3f8 --- /dev/null +++ b/basic.c @@ -0,0 +1,878 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: basic.c 13654 2004-05-07 21:43:40Z jpf $"; +#endif +/* + * Program: Cursor manipulation functions + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* + * The routines in this file move the cursor around on the screen. They + * compute a new value for the cursor, then adjust ".". The display code + * always updates the cursor location, so only moves between lines, or + * functions that adjust the top line in the window and invalidate the + * framing, are hard. + */ +#include "headers.h" + +#ifdef ANSI + int getgoal(struct LINE *); +#else + int getgoal(); +#endif + + +/* + * Move the cursor to the + * beginning of the current line. + * Trivial. + */ +gotobol(f, n) +int f, n; +{ + curwp->w_doto = 0; + return (TRUE); +} + +/* + * Move the cursor backwards by "n" characters. If "n" is less than zero call + * "forwchar" to actually do the move. Otherwise compute the new cursor + * location. Error if you try and move out of the buffer. Set the flag if the + * line pointer for dot changes. + */ +backchar(f, n) +int f; +register int n; +{ + register LINE *lp; + + if (n < 0) + return (forwchar(f, -n)); + + while (n--) { + if (curwp->w_doto == 0) { + if ((lp=lback(curwp->w_dotp)) == curbp->b_linep){ + if(Pmaster && Pmaster->headents) + /* + * go up into editing the mail header if on + * the top line and the user hits the left arrow!!! + * + * if the editor returns anything except -1, the + * user requested something special, so let + * pico know... + */ + return(HeaderEditor(2, 1)); + else + return (FALSE); + } + + curwp->w_dotp = lp; + curwp->w_doto = llength(lp); + curwp->w_flag |= WFMOVE; + } else + curwp->w_doto--; + } + + return (TRUE); +} + + +/* + * Move the cursor to the end of the current line. Trivial. No errors. + */ +gotoeol(f, n) +int f, n; +{ + curwp->w_doto = llength(curwp->w_dotp); + return (TRUE); +} + + +/* + * Move the cursor forwwards by "n" characters. If "n" is less than zero call + * "backchar" to actually do the move. Otherwise compute the new cursor + * location, and move ".". Error if you try and move off the end of the + * buffer. Set the flag if the line pointer for dot changes. + */ +forwchar(f, n) +int f; +register int n; +{ + if (n < 0) + return (backchar(f, -n)); + + while (n--) { + if (curwp->w_doto == llength(curwp->w_dotp)) { + if (curwp->w_dotp == curbp->b_linep) + return (FALSE); + + curwp->w_dotp = lforw(curwp->w_dotp); + curwp->w_doto = 0; + curwp->w_flag |= WFMOVE; + } + else + curwp->w_doto++; + } + + return (TRUE); +} + + +/* + * move to a particular line. + * argument (n) must be a positive integer for + * this to actually do anything + */ +gotoline(f, n) +int f, n; +{ + if (n < 1) /* if a bogus argument...then leave */ + return(FALSE); + + /* first, we go to the start of the buffer */ + curwp->w_dotp = lforw(curbp->b_linep); + curwp->w_doto = 0; + return(forwline(f, n-1)); +} + + +/* + * Goto the beginning of the buffer. Massive adjustment of dot. This is + * considered to be hard motion; it really isn't if the original value of dot + * is the same as the new value of dot. Normally bound to "M-<". + */ +gotobob(f, n) +int f, n; +{ + curwp->w_dotp = lforw(curbp->b_linep); + curwp->w_doto = 0; + curwp->w_flag |= WFHARD; + return (TRUE); +} + + +/* + * Move to the end of the buffer. Dot is always put at the end of the file + * (ZJ). The standard screen code does most of the hard parts of update. + * Bound to "M->". + */ +gotoeob(f, n) +int f, n; +{ + curwp->w_dotp = curbp->b_linep; + curwp->w_doto = 0; + curwp->w_flag |= WFHARD; + return (TRUE); +} + + +/* + * Move forward by full lines. If the number of lines to move is less than + * zero, call the backward line function to actually do it. The last command + * controls how the goal column is set. Bound to "C-N". No errors are + * possible. + */ +forwline(f, n) +int f, n; +{ + register LINE *dlp; + + if (n < 0) + return (backline(f, -n)); + + if ((lastflag&CFCPCN) == 0) /* Reset goal if last */ + curgoal = getccol(FALSE); /* not C-P or C-N */ + + thisflag |= CFCPCN; + dlp = curwp->w_dotp; + while (n-- && dlp!=curbp->b_linep) + dlp = lforw(dlp); + + curwp->w_dotp = dlp; + curwp->w_doto = getgoal(dlp); + curwp->w_flag |= WFMOVE; + return (TRUE); +} + + +/* + * This function is like "forwline", but goes backwards. The scheme is exactly + * the same. Check for arguments that are less than zero and call your + * alternate. Figure out the new line and call "movedot" to perform the + * motion. No errors are possible. Bound to "C-P". + */ +backline(f, n) +int f, n; +{ + register LINE *dlp; + + if (n < 0) + return (forwline(f, -n)); + + if(Pmaster && Pmaster->headents){ + /* + * go up into editing the mail header if on the top line + * and the user hits the up arrow!!! + */ + if (lback(curwp->w_dotp) == curbp->b_linep) + /* + * if the editor returns anything except -1 then the user + * has requested something special, so let pico know... + */ + return(HeaderEditor(1, 1)); + } + + if ((lastflag&CFCPCN) == 0) /* Reset goal if the */ + curgoal = getccol(FALSE); /* last isn't C-P, C-N */ + + thisflag |= CFCPCN; + dlp = curwp->w_dotp; + while (n-- && lback(dlp)!=curbp->b_linep) + dlp = lback(dlp); + + curwp->w_dotp = dlp; + curwp->w_doto = getgoal(dlp); + curwp->w_flag |= WFMOVE; + return (TRUE); +} + + +/* + * go back to the begining of the current paragraph + * here we look for a or or + * combination to delimit the begining of a paragraph + */ +gotobop(f, n) +int f, n; /* default Flag & Numeric argument */ +{ + int quoted, qlen; + char qstr[NLINE], qstr2[NLINE]; + + if (n < 0) /* the other way...*/ + return(gotoeop(f, -n)); + + while (n-- > 0) { /* for each one asked for */ + + while(lisblank(curwp->w_dotp) + && lback(curwp->w_dotp) != curbp->b_linep){ + curwp->w_dotp = lback(curwp->w_dotp); + curwp->w_doto = 0; + } + + /* scan line by line until we come to a line ending with + * a or or + * + * PLUS: if there's a quote string, a quoted-to-non-quoted + * line transition. + */ + quoted = (glo_quote_str || (Pmaster && Pmaster->quote_str)) + ? quote_match(glo_quote_str ? glo_quote_str : Pmaster->quote_str, + curwp->w_dotp, qstr, NLINE) : 0; + qlen = quoted ? strlen(qstr) : 0; + while(lback(curwp->w_dotp) != curbp->b_linep + && llength(lback(curwp->w_dotp)) > qlen + && ((glo_quote_str || (Pmaster && Pmaster->quote_str)) + ? (quoted == quote_match(glo_quote_str ? glo_quote_str + : Pmaster->quote_str, + lback(curwp->w_dotp), + qstr2, NLINE) + && !strcmp(qstr, qstr2)) + : 1) + && lgetc(curwp->w_dotp, qlen).c != TAB + && lgetc(curwp->w_dotp, qlen).c != ' ') + curwp->w_dotp = lback(curwp->w_dotp); + + if(n){ + /* keep looking */ + if(lback(curwp->w_dotp) == curbp->b_linep) + break; + else + curwp->w_dotp = lback(curwp->w_dotp); + + curwp->w_doto = 0; + } + else{ + /* leave cursor on first word in para */ + curwp->w_doto = 0; + while(isspace((unsigned char)lgetc(curwp->w_dotp, curwp->w_doto).c)) + if(++curwp->w_doto >= llength(curwp->w_dotp)){ + curwp->w_doto = 0; + curwp->w_dotp = lforw(curwp->w_dotp); + if(curwp->w_dotp == curbp->b_linep) + break; + } + } + } + + curwp->w_flag |= WFMOVE; /* force screen update */ + return(TRUE); +} + + +/* + * go forword to the end of the current paragraph + * here we look for a or or + * combination to delimit the begining of a paragraph + */ +gotoeop(f, n) +int f, n; /* default Flag & Numeric argument */ + +{ + int quoted, qlen; + char qstr[NLINE], qstr2[NLINE]; + + if (n < 0) /* the other way...*/ + return(gotobop(f, -n)); + + while (n-- > 0) { /* for each one asked for */ + + while(lisblank(curwp->w_dotp)){ + curwp->w_doto = 0; + if((curwp->w_dotp = lforw(curwp->w_dotp)) == curbp->b_linep) + break; + } + + /* scan line by line until we come to a line ending with + * a or or + * + * PLUS: if there's a quote string, a quoted-to-non-quoted + * line transition. + */ + quoted = ((glo_quote_str || (Pmaster && Pmaster->quote_str)) + ? quote_match(glo_quote_str ? glo_quote_str : Pmaster->quote_str, + curwp->w_dotp, qstr, NLINE) : 0); + qlen = quoted ? strlen(qstr) : 0; + + while(curwp->w_dotp != curbp->b_linep + && llength(lforw(curwp->w_dotp)) > qlen + && ((glo_quote_str || (Pmaster && Pmaster->quote_str)) + ? (quoted == quote_match(glo_quote_str ? glo_quote_str + : Pmaster->quote_str, + lforw(curwp->w_dotp), + qstr2, NLINE) + && !strcmp(qstr, qstr2)) + : 1) + && lgetc(lforw(curwp->w_dotp), qlen).c != TAB + && lgetc(lforw(curwp->w_dotp), qlen).c != ' ') + curwp->w_dotp = lforw(curwp->w_dotp); + + curwp->w_doto = llength(curwp->w_dotp); + + /* still looking? */ + if(n){ + if(curwp->w_dotp == curbp->b_linep) + break; + else + curwp->w_dotp = lforw(curwp->w_dotp); + + curwp->w_doto = 0; + } + } + + curwp->w_flag |= WFMOVE; /* force screen update */ + return(curwp->w_dotp != curbp->b_linep); +} + +/* + * This routine, given a pointer to a LINE, and the current cursor goal + * column, return the best choice for the offset. The offset is returned. + * Used by "C-N" and "C-P". + */ +getgoal(dlp) +register LINE *dlp; +{ + register int c; + register int col; + register int newcol; + register int dbo; + + col = 0; + dbo = 0; + while (dbo != llength(dlp)) { + c = lgetc(dlp, dbo).c; + newcol = col; + if (c == '\t') + newcol |= 0x07; + else if (c<0x20 || c==0x7F) + ++newcol; + + ++newcol; + if (newcol > curgoal) + break; + + col = newcol; + ++dbo; + } + + return (dbo); +} + + + +/* + * Scroll the display forward (up) n lines. + */ +scrollforw (n, movedot) +register int n; +int movedot; +{ + register LINE *lp; + LINE *lp2; + register int nl; + int i; + + nl = n; + lp = curwp->w_linep; + while (n-- && lp!=curbp->b_linep) + lp = lforw(lp); + + if (movedot) { /* Move dot to top of page. */ + curwp->w_dotp = lp; + curwp->w_doto = 0; + } + + curwp->w_flag |= WFHARD; + if(lp == curbp->b_linep) + return(TRUE); + else + curwp->w_linep = lp; + + /* + * if the header is open, close it ... + */ + if(Pmaster && Pmaster->headents && ComposerTopLine != COMPOSER_TOP_LINE){ + n -= ComposerTopLine - COMPOSER_TOP_LINE; + ToggleHeader(0); + } + + /* + * scroll down from the top the same number of lines we've moved + * forward + */ + if(optimize) + scrollup(curwp, -1, nl-n-1); + + if(!movedot){ + /* Requested to not move the dot. Look for the dot in the current + * window. loop through all lines, stop when at end of window + * or endof buffer. If the dot is found, it can stay where it + * is, otherwise we do need to move it. + */ + movedot = TRUE; + for ( lp2 = lp, i = 0; + lp2 != curbp->b_linep && i < curwp->w_ntrows; + lp2 = lforw(lp2), ++i) { + if (curwp->w_dotp == lp2) { + movedot = FALSE; + break; + } + } + if (movedot) { + /* Dot not found in window. Move to first line of window. */ + curwp->w_dotp = lp; + curwp->w_doto = 0; + } + } + + return (TRUE); +} + + +/* + * Scroll forward by a specified number of lines, or by a full page if no + * argument. Bound to "C-V". The "2" in the arithmetic on the window size is + * the overlap; this value is the default overlap value in ITS EMACS. Because + * this zaps the top line in the display window, we have to do a hard update. + */ +forwpage(f, n) +int f; +register int n; +{ + + if (f == FALSE) { + n = curwp->w_ntrows - 2; /* Default scroll. */ + if (n <= 0) /* Forget the overlap */ + n = 1; /* if tiny window. */ + } else if (n < 0) + return (backpage(f, -n)); +#if CVMVAS + else /* Convert from pages */ + n *= curwp->w_ntrows; /* to lines. */ +#endif + return (scrollforw (n, TRUE)); +} + + +/* + * Scroll back (down) number of lines. + */ +scrollback (n, movedot) +register int n; +int movedot; +{ + register LINE *lp, *tp; + register int nl; + int i; + + if(Pmaster && Pmaster->headents){ + /* + * go up into editing the mail header if on the top line + * and the user hits the up arrow!!! + */ + if (lback(curwp->w_dotp) == curbp->b_linep){ + /* + * if the editor returns anything except -1 then the user + * has requested something special, so let pico know... + */ + return(HeaderEditor(1, 1)); + } + } + + /* + * Count back the number of lines requested. + */ + nl = n; + lp = curwp->w_linep; + while (n-- && lback(lp)!=curbp->b_linep) + lp = lback(lp); + + curwp->w_linep = lp; + curwp->w_flag |= WFHARD; + + /* + * scroll down from the top the same number of lines we've moved + * forward + * + * This isn't too cool, but it has to be this way so we can + * gracefully scroll in the message header + */ + if(Pmaster && Pmaster->headents){ + if((lback(lp)==curbp->b_linep) && (ComposerTopLine==COMPOSER_TOP_LINE)) + n -= entry_line(1000, TRUE); /* never more than 1000 headers */ + if(nl-n-1 < curwp->w_ntrows) + if(optimize) + scrolldown(curwp, -1, nl-n-1); + } + else + if(optimize) + scrolldown(curwp, -1, nl-n-1); + + if(Pmaster && Pmaster->headents){ + /* + * if we're at the top of the page, and the header is closed, + * open it ... + */ + if((lback(lp) == curbp->b_linep) + && (ComposerTopLine == COMPOSER_TOP_LINE)){ + ToggleHeader(1); + movecursor(ComposerTopLine, 0); + } + } + + /* + * Decide if we move the dot or not. Calculation done AFTER deciding + * if we display the header because that will change the number of + * lines on the screen. + */ + if (movedot) { + /* Dot gets put at top of window. */ + curwp->w_dotp = curwp->w_linep; + curwp->w_doto = 0; + } + else { + /* Requested not to move dot, but we do need to keep in on + * the screen. Verify that it is still in the range of lines + * visable in the window. Loop from the first line to the + * last line, until we reach the end of the buffer or the end + * of the window. If we find the dot, then we don't need + * to move it. */ + movedot = TRUE; + for ( tp = curwp->w_linep, i = 0; + tp != curbp->b_linep && i < curwp->w_ntrows; + tp = lforw(tp), ++i) { + if (curwp->w_dotp == tp) { + movedot = FALSE; + break; + } + } + if (movedot) { + /* Dot not found in window. Move to last line of window. */ + curwp->w_dotp = lback (tp); + curwp->w_doto = 0; + } + } + + return (TRUE); +} + + + + +/* + * This command is like "forwpage", but it goes backwards. The "2", like + * above, is the overlap between the two windows. The value is from the ITS + * EMACS manual. Bound to "M-V". We do a hard update for exactly the same + * reason. + */ +backpage(f, n) +int f; +register int n; +{ + + if (f == FALSE) { + n = curwp->w_ntrows - 2; /* Default scroll. */ + if (n <= 0) /* Don't blow up if the */ + n = 1; /* window is tiny. */ + } else if (n < 0) + return (forwpage(f, -n)); +#if CVMVAS + else /* Convert from pages */ + n *= curwp->w_ntrows; /* to lines. */ +#endif + return (scrollback (n, TRUE)); +} + + + +scrollupline (f, n) +int f, n; +{ + return (scrollback (1, FALSE)); +} + + +scrolldownline (f, n) +int f, n; +{ + return (scrollforw (1, FALSE)); +} + + + +/* + * Scroll to a position. + */ +scrollto (f, n) +int f, n; +{ +#ifdef _WINDOWS + long scrollLine; + LINE *lp; + int i; + + scrollLine = mswin_getscrollto (); + + /* + * Starting at the first data line in the buffer, step forward + * 'scrollLine' lines to find the new top line. It is a circular + * list of buffers, so watch for the first line to reappear. if + * it does, we have some sort of internal error, abort scroll + * operation. Also watch for NULL, just in case. + */ + lp = lforw (curbp->b_linep); + for (i = 0; i < scrollLine && lp != curbp->b_linep && lp != NULL; ++i) + lp = lforw(lp); + + if (lp == curbp->b_linep || lp == NULL) + return (FALSE); /* Whoops! */ + + + /* Set the new top line for the window and flag a redraw. */ + curwp->w_linep = lp; + curwp->w_dotp = lp; + curwp->w_doto = 0; + curwp->w_flag |= WFHARD; + + if(Pmaster && Pmaster->headents){ + /* + * If we are at the top of the page and header not open, open it. + * If we are not at the top of the page and the header is open, + * close it. + */ + if((lback(lp) == curbp->b_linep) + && (ComposerTopLine == COMPOSER_TOP_LINE)){ + ToggleHeader(1); + movecursor(ComposerTopLine, 0); + } + else if((lback(lp) != curbp->b_linep) + && (ComposerTopLine != COMPOSER_TOP_LINE)){ + ToggleHeader (0); + } + } +#endif + + return (TRUE); +} + + + +/* + * Set the mark in the current window to the value of "." in the window. No + * errors are possible. Bound to "M-.". If told to set an already set mark + * unset it. + */ +setmark(f, n) +int f, n; +{ + if(!curwp->w_markp){ + curwp->w_markp = curwp->w_dotp; + curwp->w_marko = curwp->w_doto; + emlwrite("Mark Set", NULL); + } + else{ + /* clear inverse chars between here and dot */ + markregion(0); + curwp->w_markp = NULL; + emlwrite("Mark UNset", NULL); + } + +#ifdef _WINDOWS + mswin_allowcopycut(curwp->w_markp ? kremove : NULL); +#endif + return (TRUE); +} + + +/* + * Swap the values of "." and "mark" in the current window. This is pretty + * easy, bacause all of the hard work gets done by the standard routine + * that moves the mark about. The only possible error is "no mark". Bound to + * "C-X C-X". + */ +swapmark(f, n) +int f, n; +{ + register LINE *odotp; + register int odoto; + + if (curwp->w_markp == NULL) { + if(Pmaster == NULL) + emlwrite("No mark in this window", NULL); + return (FALSE); + } + + odotp = curwp->w_dotp; + odoto = curwp->w_doto; + curwp->w_dotp = curwp->w_markp; + curwp->w_doto = curwp->w_marko; + curwp->w_markp = odotp; + curwp->w_marko = odoto; + curwp->w_flag |= WFMOVE; + return (TRUE); +} + + +/* + * Set the mark in the current window to the value of "." in the window. No + * errors are possible. Bound to "M-.". If told to set an already set mark + * unset it. + */ +setimark(f, n) +int f, n; +{ + curwp->w_imarkp = curwp->w_dotp; + curwp->w_imarko = curwp->w_doto; + return(TRUE); +} + + +/* + * Swap the values of "." and "mark" in the current window. This is pretty + * easy, bacause all of the hard work gets done by the standard routine + * that moves the mark about. The only possible error is "no mark". Bound to + * "C-X C-X". + */ +swapimark(f, n) +int f, n; +{ + register LINE *odotp; + register int odoto; + + if (curwp->w_imarkp == NULL) { + if(Pmaster == NULL) + emlwrite("Programmer botch! No mark in this window", NULL); + return (FALSE); + } + + odotp = curwp->w_dotp; + odoto = curwp->w_doto; + curwp->w_dotp = curwp->w_imarkp; + curwp->w_doto = curwp->w_imarko; + curwp->w_imarkp = odotp; + curwp->w_imarko = odoto; + curwp->w_flag |= WFMOVE; + return (TRUE); +} + + + +#ifdef MOUSE + +/* + * Handle a mouse down. + */ +mousepress (f, n) +int f, n; +{ + MOUSEPRESS mp; + LINE *lp; + int i; + + + mouse_get_last (NULL, &mp); + + + lp = curwp->w_linep; + i = mp.row - ((Pmaster && Pmaster->headents) ? ComposerTopLine : 2); + if (i < 0) { + if (Pmaster) { + /* Clear existing region. */ + if (curwp->w_markp) + setmark(0,1); + + /* Move to top of document before editing header. */ + curwp->w_dotp = curwp->w_linep; + curwp->w_doto = 0; + curwp->w_flag |= WFMOVE; + update (); /* And update. */ + + return (HeaderEditor (1, 1)); + } + } + else { + while(i-- && lp != curbp->b_linep) + lp = lforw(lp); + + curgoal = mp.col; + curwp->w_dotp = lp; + curwp->w_doto = getgoal(lp); + curwp->w_flag |= WFMOVE; + + if(mp.doubleclick) + setmark(0, 1); + } + + return(FALSE); +} +#endif diff --git a/bind.c b/bind.c new file mode 100644 index 0000000..3bb76f2 --- /dev/null +++ b/bind.c @@ -0,0 +1,420 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: bind.c 11330 2000-11-09 21:53:43Z hubert $"; +#endif +/* + * Program: Key binding routines + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2000 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* This file is for functions having to do with key bindings, + descriptions, help commands, and command line execution. + + written 11-feb-86 by Daniel Lawrence + */ + +#include "headers.h" + +#ifdef ANSI + int arraylen(char **); +#else + int arraylen(); +#endif + +/* + * help - help function for pico (UW pared down version of uemacs). + * this function will intentionally garbage with helpful + * tips and then wait for a ' ' to be hit to then update the + * screen. + */ + + +static char *helptext[] = { + "\tPico Help Text", + " ", + "\tPico is designed to be a simple, easy-to-use text editor with a", + "\tlayout very similar to the pine mailer. The status line at the", + "\ttop of the display shows pico's version, the current file being", + "\tedited and whether or not there are outstanding modifications", + "\tthat have not been saved. The third line from the bottom is used", + "\tto report informational messages and for additional command input.", + "\tThe bottom two lines list the available editing commands.", + " ", + "\tEach character typed is automatically inserted into the buffer", + "\tat the current cursor position. Editing commands and cursor", + "\tmovement (besides arrow keys) are given to pico by typing", + "\tspecial control-key sequences. A caret, '^', is used to denote", + "~\tthe control key, sometimes marked \"CTRL\", so the ~C~T~R~L~-~q key", + "~\tcombination is written as ~^~Q.", + " ", + "\tThe following functions are available in pico (where applicable,", + "\tcorresponding function key commands are in parentheses).", + " ", + "~\t~^~G (~F~1) Display this help text.", + " ", + "~\t~^~F move Forward a character.", + "~\t~^~B move Backward a character.", + "~\t~^~P move to the Previous line.", + "~\t~^~N move to the Next line.", + "~\t~^~A move to the beginning of the current line.", + "~\t~^~E move to the End of the current line.", + "~\t~^~V (~F~8) move forward a page of text.", + "~\t~^~Y (~F~7) move backward a page of text.", + " ", + "~\t~^~W (~F~6) Search for (where is) text, neglecting case.", + "~\t~^~L Refresh the display.", + " ", + "~\t~^~D Delete the character at the cursor position.", + "~\t~^~^ Mark cursor position as beginning of selected text.", + "\t\t Note: Setting mark when already set unselects text.", + "~\t~^~K (~F~9) Cut selected text (displayed in inverse characters).", + "\t\t Note: The selected text's boundary on the cursor side", + "\t\t ends at the left edge of the cursor. So, with ", + "\t\t selected text to the left of the cursor, the ", + "\t\t character under the cursor is not selected.", + "~\t~^~U (~F~1~0) Uncut (paste) last cut text inserting it at the", + "\t\t current cursor position.", + "~\t~^~I Insert a tab at the current cursor position.", + " ", + "~\t~^~J (~F~4) Format (justify) the current paragraph.", + "\t\t Note: paragraphs delimited by blank lines or indentation.", + "~\t~^~T (~F~1~2) To invoke the spelling checker", + "~\t~^~C (~F~1~1) Report current cursor position", + " ", + "~\t~^~R (~F~5) Insert an external file at the current cursor position.", + "~\t~^~O (~F~3) Output the current buffer to a file, saving it.", + "~\t~^~X (~F~2) Exit pico, saving buffer.", + " ", + "\tPine and Pico are trademarks of the University of Washington.", + "\tNo commercial use of these trademarks may be made without prior", + "\twritten permission of the University of Washington.", + " ", + " End of Help.", + " ", + NULL +}; + + +/* + * arraylen - return the number of bytes in an array of char + */ +arraylen(array) +char **array; +{ + register int i=0; + + while(array[i++] != NULL) ; + return(i); +} + + +/* + * whelp - display help text for the composer and pico + */ +whelp(f, n) + int f, n; +{ + if(term.t_mrow == 0){ /* blank keymenu in effect */ + if(km_popped == 0){ + /* cause keymenu display */ + km_popped = 2; + if(!Pmaster) + sgarbf = TRUE; + + return(TRUE); + } + } + + if(Pmaster){ + VARS_TO_SAVE *saved_state; + + saved_state = save_pico_state(); + (*Pmaster->helper)(Pmaster->composer_help, + Pmaster->headents + ? "Help on the Pine Composer" + : "Help on Signature Editor", + 1); + if(saved_state){ + restore_pico_state(saved_state); + free_pico_state(saved_state); + } + + ttresize(); + picosigs(); /* restore any altered handlers */ + curwp->w_flag |= WFMODE; + if(km_popped) /* this will unpop us */ + curwp->w_flag |= WFHARD; + } + else{ + int mrow_was_zero = 0; + + /* always want keyhelp showing during help */ + if(term.t_mrow == 0){ + mrow_was_zero++; + term.t_mrow = 2; + } + + pico_help(helptext, "Help for Pico", 1); + /* put it back the way it was */ + if(mrow_was_zero) + term.t_mrow = 0; + } + + sgarbf = TRUE; + return(FALSE); +} + +static KEYMENU menu_scroll[] = { + {NULL, NULL, KS_NONE}, {NULL, NULL, KS_NONE}, + {NULL, NULL, KS_NONE}, {NULL, NULL, KS_NONE}, + {NULL, NULL, KS_NONE}, {NULL, NULL, KS_NONE}, + {"^X", "Exit Help", KS_NONE}, {NULL, NULL, KS_NONE}, + {NULL, NULL, KS_NONE}, {NULL, NULL, KS_NONE}, + {NULL, NULL, KS_NONE}, {NULL, NULL, KS_NONE} +}; +#define PREV_KEY 3 +#define NEXT_KEY 9 + + +#define OVERLAP 2 /* displayed page overlap */ + +/* + * scrollw - takes beginning row and ending row to diplay an array + * of text lines. returns either 0 if scrolling terminated + * normally or the value of a ctrl character typed to end it. + * + * updates - + * 01/11/89 - added stripe call if 1st char is tilde - '~' + * + */ +wscrollw(begrow, endrow, textp, textlen) +int begrow, endrow; +char *textp[]; +int textlen; +{ + register int loffset = 0; + register int prevoffset = -1; + register int dlines; + register int i; + register int cont; + register int done = 0; + register char *buf; + int c; + + dlines = endrow - begrow - 1; + while(!done) { + /* + * diplay a page loop ... + */ + if(prevoffset != loffset){ + for(i = 0; i < dlines; i++){ + movecursor(i + begrow, 0); + peeol(); + if((loffset+i) < textlen){ + buf = &(textp[loffset+i][0]); + if(*buf == '~'){ + buf++; + wstripe(begrow+i, 0, buf, '~'); + } + else{ + pputs(buf, 0); + } + } + } + /* + * put up the options prompt + */ + movecursor(begrow + dlines, 0); + cont = (loffset+dlines < textlen); + if(cont){ /* continue ? */ + menu_scroll[NEXT_KEY].name = "^V"; + menu_scroll[NEXT_KEY].label = "Next Pg"; + } + else + menu_scroll[NEXT_KEY].name = NULL; + + if(loffset){ + menu_scroll[PREV_KEY].name = "^Y"; + menu_scroll[PREV_KEY].label = "Prev Pg"; + } + else + menu_scroll[PREV_KEY].name = NULL; + + wkeyhelp(menu_scroll); + } + + (*term.t_flush)(); + + c = GetKey(); + + prevoffset = loffset; + switch(c){ + case (CTRL|'X') : /* quit */ + case F2 : + done = 1; + break; + case (CTRL|'Y') : /* prev page */ + case F7 : /* prev page */ + if((loffset-dlines-OVERLAP) > 0){ + loffset -= (dlines-OVERLAP); + } + else{ + if(loffset != 0){ + prevoffset = -1; + } + else{ + (*term.t_beep)(); + } + loffset = 0; + } + break; + case (CTRL|'V') : /* next page */ + case F8 : + if(cont){ + loffset += (dlines-OVERLAP); + } + else{ + (*term.t_beep)(); + } + break; + case '\016' : /* prev-line */ + case (CTRL|'N') : + if(cont) + loffset++; + else + (*term.t_beep)(); + break; + case '\020' : /* prev-line */ + case (CTRL|'P') : + if(loffset > 0) + loffset--; + else + (*term.t_beep)(); + break; + case '\014' : /* refresh */ + case (CTRL|'L') : /* refresh */ + modeline(curwp); + update(); + prevoffset = -1; + break; + case NODATA : + break; + default : + emlwrite("Unknown Command.", NULL); + (*term.t_beep)(); + break; + } + } + return(TRUE); +} + + +/* + * normalize_cmd - given a char and list of function key to command key + * mappings, return, depending on gmode, the right command. + * The list is an array of (Fkey, command-key) pairs. + * sc is the index in the array that means to ignore fkey + * vs. command key mapping + * + * rules: 1. if c not in table (either fkey or command), let it thru + * 2. if c matches, but in other mode, punt it + */ +normalize_cmd(c, list, sc) +int c, sc; +int list[][2]; +{ + register int i; + + for(i=0; i < 12; i++){ + if(c == list[i][(FUNC&c) ? 0 : 1]){ /* in table? */ + if(i == sc) /* SPECIAL CASE! */ + return(list[i][1]); + + if(list[i][1] == NODATA) /* no mapping ! */ + return(c); + + if(((FUNC&c) == FUNC) ^ ((gmode&MDFKEY) == MDFKEY)) + return(BADESC); /* keystroke not allowed! */ + else + return(list[i][1]); /* never return func keys */ + } + } + +#ifdef _WINDOWS + /* + * Menu's get alpha key commands assigned to them. Well, if we are in PF + * key mode then the alpha key commands don't work. So, we flag them with + * a bit (MENU defined in estruct.h) so we can recognize them as different + * from a keyboard press. Here we clear that flag so the command can be + * processed. + */ + c &= ~MENU; +#endif + + return(c); +} + + +/* + * rebind - replace the first function with the second + */ +void +rebindfunc(a, b) + int (*a) PROTO((int, int)), (*b) PROTO((int, int)); +{ + KEYTAB *kp; + + kp = (Pmaster) ? &keytab[0] : &pkeytab[0]; + + while(kp->k_fp != NULL){ /* go thru whole list, and */ + if(kp->k_fp == a) + kp->k_fp = b; /* replace all occurances */ + kp++; + } +} + + +/* + * bindtokey - bind function f to command c + */ +bindtokey(c, f) +int c, (*f) PROTO((int, int)); +{ + KEYTAB *kp, *ktab = (Pmaster) ? &keytab[0] : &pkeytab[0]; + + for(kp = ktab; kp->k_fp; kp++) + if(kp->k_code == c){ + kp->k_fp = f; /* set to new function */ + break; + } + + /* not found? create new binding */ + if(!kp->k_fp && kp < &ktab[NBINDS]){ + kp->k_code = c; /* assign new code and function */ + kp->k_fp = f; + (++kp)->k_code = 0; /* and null out next slot */ + kp->k_fp = NULL; + } + + return(TRUE); +} diff --git a/blddate.c b/blddate.c new file mode 100644 index 0000000..522108b --- /dev/null +++ b/blddate.c @@ -0,0 +1,56 @@ +#include +#include + +/* + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-1996 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + */ + +main(argc, argv) + int argc; + char **argv; +{ + struct tm *t; + FILE *outfile=stdout; + time_t ltime; +#ifdef OS2 + char hostname[256]; + + gethostname(hostname, sizeof hostname - 1); +#endif + + if(argc > 1 && (outfile = fopen(argv[1], "w")) == NULL){ + fprintf(stderr, "can't create '%s'\n", argv[1]); + exit(1); + } + + time(<ime); + t = localtime(<ime); + fprintf(outfile,"char datestamp[]=\"%02d-%s-%d\";\n", t->tm_mday, + (t->tm_mon == 0) ? "Jan" : + (t->tm_mon == 1) ? "Feb" : + (t->tm_mon == 2) ? "Mar" : + (t->tm_mon == 3) ? "Apr" : + (t->tm_mon == 4) ? "May" : + (t->tm_mon == 5) ? "Jun" : + (t->tm_mon == 6) ? "Jul" : + (t->tm_mon == 7) ? "Aug" : + (t->tm_mon == 8) ? "Sep" : + (t->tm_mon == 9) ? "Oct" : + (t->tm_mon == 10) ? "Nov" : + (t->tm_mon == 11) ? "Dec" : "UKN", + 1900 + t->tm_year); +#ifdef OS2 + fprintf(outfile, "char hoststamp[]=\"%s\";\n", hostname); +#else + fprintf(outfile, "char hoststamp[]=\"random-pc\";\n"); +#endif + exit(0); +} diff --git a/browse.c b/browse.c new file mode 100644 index 0000000..a74e2d4 --- /dev/null +++ b/browse.c @@ -0,0 +1,2586 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: browse.c 13704 2004-06-11 21:50:29Z hubert $"; +#endif +/* + * Program: Routines to support file browser in pico and Pine composer + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + * + * NOTES: + * + * Misc. thoughts (mss, 5 Apr 92) + * + * This is supposed to be just a general purpose browser, equally + * callable from either pico or the pine composer. Someday, it could + * even be used to "wrap" the unix file business for really novice + * users. The stubs are here for renaming, copying, creating directories, + * deleting, undeleting (thought is delete just moves files to + * ~/.pico.deleted directory or something and undelete offers the + * files in there for undeletion: kind of like the mac trashcan). + * + * Nice side effects + * + * Since the full path name is always maintained and referencing ".." + * stats the path stripped of its trailing name, the unpleasantness of + * symbolic links is hidden. + * + * Fleshed out the file managements stuff (mss, 24 June 92) + * + * + */ +#include "headers.h" + +#ifndef _WINDOWS + +#if defined(bsd) || defined(lnx) +extern int errno; +#endif + + +/* + * directory cell structure + */ +struct fcell { + char *fname; /* file name */ + unsigned mode; /* file's mode */ + char size[16]; /* file's size in s */ + struct fcell *next; + struct fcell *prev; +}; + + +/* + * master browser structure + */ +static struct bmaster { + struct fcell *head; /* first cell in list */ + struct fcell *top; /* cell in top left */ + struct fcell *current; /* currently selected */ + int longest; /* longest file name */ + int fpl; /* file names per line */ + int cpf; /* chars / file / line */ + int flags; + char dname[NLINE]; /* this dir's name */ + char *names; /* malloc'd name array */ + LMLIST *lm; +} *gmp; /* global master ptr */ + + +/* + * title for exported browser display + */ +static char *browser_title = NULL; + + +#ifdef ANSI + struct bmaster *getfcells(char *, int); + int PaintCell(int, int, int, struct fcell *, int); + int PaintBrowser(struct bmaster *, int, int *, int *); + void BrowserKeys(void); + void layoutcells(struct bmaster *); + void percdircells(struct bmaster *); + int PlaceCell(struct bmaster *, struct fcell *, int *, int *); + void zotfcells(struct fcell *); + void zotmaster(struct bmaster **); + struct fcell *FindCell(struct bmaster *, char *); + int sisin(char *, char *); + void p_chdir(struct bmaster *); + void BrowserAnchor(char *); + void ClearBrowserScreen(void); + void BrowserRunChild(char *, char *); + int LikelyASCII(char *); + int fcell_is_selected(struct fcell *, struct bmaster *); + void add_cell_to_lmlist(struct fcell *, struct bmaster *); + void del_cell_from_lmlist(struct fcell *, struct bmaster *); +#else + struct bmaster *getfcells(); + int PaintCell(); + int PaintBrowser(); + void BrowserKeys(); + void layoutcells(); + void percdircells(); + int PlaceCell(); + void zotfcells(); + void zotmaster(); + struct fcell *FindCell(); + int sisin(); + void p_chdir(); + void BrowserAnchor(); + void ClearBrowserScreen(); + void BrowserRunChild(); + int LikelyASCII(); + int fcell_is_selected(); + void add_cell_to_lmlist(); + void del_cell_from_lmlist(); +#endif + + +static KEYMENU menu_browse[] = { + {"?", "Get Help", KS_SCREENHELP}, {NULL, NULL, KS_NONE}, + {NULL, NULL, KS_NONE}, {"-", "Prev Pg", KS_PREVPAGE}, + {"D", "Delete", KS_NONE}, {"C","Copy", KS_NONE}, + {NULL, NULL, KS_NONE}, {NULL, NULL, KS_NONE}, + {"W", "Where is", KS_NONE}, {"Spc", "Next Pg", KS_NEXTPAGE}, + {"R", "Rename", KS_NONE}, {NULL, NULL, KS_NONE} +}; +#define QUIT_KEY 1 +#define EXEC_KEY 2 +#define GOTO_KEY 6 +#define SELECT_KEY 7 +#define PICO_KEY 11 + + +/* + * Default pager used by the stand-alone file browser. + */ +#define BROWSER_PAGER ((gmode & MDFKEY) ? "pine -k -F" : "pine -F") + + +/* + * function key mappings for callable browser + */ +static int bfmappings[2][12][2] = { { { F1, '?'}, /* stand alone */ + { F2, NODATA }, /* browser function */ + { F3, 'q'}, /* key mappings... */ + { F4, 'v'}, + { F5, 'l'}, + { F6, 'w'}, + { F7, '-'}, + { F8, ' '}, + { F9, 'd'}, + { F10, 'r'}, + { F11, 'c'}, + { F12, 'e'} }, + { { F1, '?'}, /* callable browser */ + { F2, NODATA }, /* function key */ + { F3, 'e'}, /* mappings... */ + { F4, 's'}, + { F5, NODATA }, + { F6, 'w'}, + { F7, '-'}, + { F8, ' '}, + { F9, 'd'}, + { F10, 'r'}, + { F11, 'c'}, + { F12, 'a'} } }; + + +/* + * Browser help for pico (pine composer help handed to us by pine) + */ +static char *BrowseHelpText[] = { +"Help for Browse Command", +" ", +"\tPico's file browser is used to select a file from the", +"\tfile system for inclusion in the edited text.", +" ", +"~\tBoth directories and files are displayed. Press ~S", +"~\tor ~R~e~t~u~r~n to select a file or directory. When a file", +"\tis selected during the \"Read File\" command, it is", +"\tinserted into edited text. Answering \"yes\" to the", +"\tverification question after a directory is selected causes", +"\tthe contents of that directory to be displayed for selection.", +" ", +"\tThe file named \"..\" is special, and means the \"parent\"", +"\tof the directory being displayed. Select this directory", +"\tto move upward in the directory tree.", +" ", +"End of Browser Help.", +" ", +NULL +}; + +/* + * Help for standalone browser (pilot) + */ +static char *sa_BrowseHelpText[] = { +"Help for Pilot (PIne's Looker-upper Of Things", +" ", +"\tPilot is a simple, display-oriented file system browser based on the", +"~\tPine message system composer. As with Pine, commands are displayed at", +"~\tthe bottom of the screen, and context-sensitive help is provided.", +" ", +"~\tPilot displays the current working directory at the top of the screen.", +"~\tThe directory's contents are displayed in columns of file name, file", +"~\tsize pairs. Names that are directories are indicated by the name", +"~\t~(~d~i~r~) in place of the file size. The parent of the current working", +"~\tdirectory is indicated by the file name ~.~. and size of ~(~p~a~r~e~n~t~ ~d~i~r~).", +"~\tFile names that are symbolic links to other files are displayed with a", +"~\tfile size of ~-~-.", +" ", +"\tThe following function keys are available in Pilot:", +" ", +"~\t~?\tDisplay this help text.", +"~\t~Q\tQuit Pilot.", +" ", +"~\t~V\tView the currently selected file or open the selected directory.", +"~\t\tNote: Pilot invokes ~p~i~n~e ~-~F, or the program defined by the ~P~A~G~E~R", +"~\t\t environment variable, to view the file.", +"~\t~L\tLaunch an external application program.", +" ", +"~\t~W\tSearch for a file by name.", +"~\t~-\tScroll up one page.", +"~\t~S~p~a~c~e\tScroll down one page.", +"~\t~N,~^~F\tMove forward (right) one column.", +"~\t~P,~^~B\tMove back (left) one column.", +"~\t~^~N\tMove down one row.", +"~\t~^~P\tMove up one row.", +" ", +"~\t~D\tDelete the selected file.", +"~\t~R\tRename the selected file or directory.", +"~\t~C\tCopy the selected file.", +"~\t~E\tEdit the selected file.", +"~\t\tNote: Pilot invokes ~p~i~c~o, or the program defined by the ~E~D~I~T~O~R", +"~\t\t environment variable, to edit the file.", +" ", +" ", +"\tPine and Pico are trademarks of the University of Washington.", +"\tNo commercial use of these trademarks may be made without prior", +"\twritten permission of the University of Washington.", +" ", +"End of Pilot Help.", +NULL +}; + + + +/* + * pico_file_browse - Exported version of FileBrowse below. + */ +pico_file_browse(pdata, dir, dirlen, fn, fnlen, sz, flags) + PICO *pdata; + char *dir, *fn, *sz; + int dirlen, fnlen, flags; +{ + int rv; + char title_buf[64]; + + Pmaster = pdata; + gmode = pdata->pine_flags | MDEXTFB; + km_popped = 0; + + /* only init screen bufs for display and winch handler */ + if(!vtinit()) + return(-1); + + if(Pmaster){ + term.t_mrow = Pmaster->menu_rows; + if(Pmaster->oper_dir) + strncpy(opertree, Pmaster->oper_dir, NLINE); + + if(*opertree) + fixpath(opertree, NLINE); + } + + /* install any necessary winch signal handler */ + ttresize(); + + sprintf(title_buf, "%s FILE", pdata->pine_anchor); + set_browser_title(title_buf); + rv = FileBrowse(dir, dirlen, fn, fnlen, sz, flags, NULL); + set_browser_title(NULL); + vttidy(); /* clean up tty handling */ + zotdisplay(); /* and display structures */ + Pmaster = NULL; /* and global config structure */ + return(rv); +} + + + +/* + * FileBrowse - display contents of given directory dir + * + * intput: + * dir points to initial dir to browse. + * dirlen- buffer size of dir + * fn initial file name. + * fnlen- buffer size of fn + * + * returns: + * dir points to currently selected directory (without + * trailing file system delimiter) + * fn points to currently selected file + * sz points to size of file if ptr passed was non-NULL + * flags + * + * Special dispensation for FB_LMODE. If the caller sets + * FB_LMODEPOS, and the caller passes a non-null lmreturn, + * then the return values will be in lmreturn instead of + * in dir and fn. The caller is responsible for freeing + * the contents of lmreturn. + * + * 1 if a file's been selected + * 0 if no files selected + * -1 if there were problems + */ +FileBrowse(dir, dirlen, fn, fnlen, sz, fb_flags, lmreturn) +char *dir, *fn, *sz; /* dir, name and optional size */ +int dirlen, fnlen, fb_flags; +LMLIST **lmreturn; +{ + int status, i, j, c, new_c; + int row, col, crow, ccol; + char *p, *envp, child[NLINE], tmp[NLINE]; + struct bmaster *mp; + struct fcell *tp; +#ifdef MOUSE + MOUSEPRESS mousep; +#endif + + child[0] = '\0'; + + if((gmode&MDTREE) && !in_oper_tree(dir)){ + emlwrite("\007Can't read outside of %s in restricted mode", opertree); + sleep(2); + return(0); + } + + if(gmode&MDGOTO){ + /* fix up function key mapping table */ + /* fix up key menu labels */ + } + + /* build contents of cell structures */ + if((gmp = getfcells(dir, fb_flags)) == NULL) + return(-1); + + tp = NULL; + if(fn && *fn){ + if((tp = FindCell(gmp, fn)) != NULL){ + gmp->current = tp; + PlaceCell(gmp, gmp->current, &row, &col); + } + } + + /* paint screen */ + PaintBrowser(gmp, 0, &crow, &ccol); + + while(1){ /* the big loop */ + if(!(gmode&MDSHOCUR)){ + crow = term.t_nrow-term.t_mrow; + ccol = 0; + } + + if(gmp->flags & FB_LMODEPOS){ + if(gmp->flags & FB_LMODE && gmp->current->mode != FIODIR) + movecursor(crow, ccol+1); + else + movecursor(crow, ccol+4); + } + else + movecursor(crow, ccol); + + if(km_popped){ + km_popped--; + if(km_popped == 0) + /* cause bottom three lines to repaint */ + PaintBrowser(gmp, 0, &crow, &ccol); + } + + if(km_popped){ /* temporarily change to cause menu to paint */ + term.t_mrow = 2; + movecursor(term.t_nrow-2, 0); /* clear status line */ + peeol(); + BrowserKeys(); + term.t_mrow = 0; + } + + (*term.t_flush)(); + +#ifdef MOUSE + mouse_in_content(KEY_MOUSE, -1, -1, 0, 0); + register_mfunc(mouse_in_content,2,0,term.t_nrow-(term.t_mrow+1), + term.t_ncol); +#endif + c = GetKey(); +#ifdef MOUSE + clear_mfunc(mouse_in_content); +#endif + + if(Pmaster){ + if(Pmaster->newmail && (c == NODATA || time_to_check())){ + if((*Pmaster->newmail)(c == NODATA ? 0 : 2, 1) >= 0){ + int rv; + + if(km_popped){ /* restore display */ + km_popped = 0; + PaintBrowser(gmp, 0, &crow, &ccol); + } + + clearcursor(); + mlerase(); + rv = (*Pmaster->showmsg)(c); + ttresize(); + picosigs(); + if(rv) /* Did showmsg corrupt the display? */ + PaintBrowser(gmp, 0, &crow, &ccol); /* Yes, repaint */ + + mpresf = 1; + } + + clearcursor(); + if(gmp->flags & FB_LMODEPOS){ + if(gmp->flags & FB_LMODE && gmp->current->mode != FIODIR) + movecursor(crow, ccol+1); + else + movecursor(crow, ccol+4); + } + else + movecursor(crow, ccol); + } + } + else{ + if(timeo && (c == NODATA || time_to_check())) + if(pico_new_mail()) + emlwrite("You may possibly have new mail.", NULL); + } + + if(km_popped) + switch(c){ + case NODATA: + case (CTRL|'L'): + km_popped++; + break; + + default: + /* clear bottom three lines */ + movecursor(term.t_nrow-2, 0); + peeol(); + movecursor(term.t_nrow-1, 0); + peeol(); + movecursor(term.t_nrow, 0); + peeol(); + break; + } + + if(c == NODATA) /* GetKey timed out */ + continue; + else if(Pmaster) + (*Pmaster->keybinput)(); + + + if(mpresf){ /* blast old messages */ + if(mpresf++ > MESSDELAY){ /* every few keystrokes */ + mlerase(); + } + } + + /* process commands */ + switch(new_c = normalize_cmd(c,bfmappings[(gmode&MDBRONLY)?0:1],2)){ + + case KEY_RIGHT: /* move right */ + case (CTRL|'@'): + case (CTRL|'F'): /* forward */ + case 'n' : + case 'N' : + if(gmp->current->next == NULL){ + (*term.t_beep)(); + break; + } + + PlaceCell(gmp, gmp->current, &row, &col); + PaintCell(row, col, gmp->cpf, gmp->current, 0); + gmp->current = gmp->current->next; + if(PlaceCell(gmp, gmp->current, &row, &col)){ + PaintBrowser(gmp, 1, &crow, &ccol); + } + else{ + PaintCell(row, col, gmp->cpf, gmp->current, 1); + crow = row; + ccol = col; + } + break; + + case KEY_LEFT: /* move left */ + case (CTRL|'B'): /* back */ + case 'p' : + case 'P' : + if(gmp->current->prev == NULL){ + (*term.t_beep)(); + break; + } + + PlaceCell(gmp, gmp->current, &row, &col); + PaintCell(row, col, gmp->cpf, gmp->current, 0); + gmp->current = gmp->current->prev; + if(PlaceCell(gmp, gmp->current, &row, &col)){ + PaintBrowser(gmp, 1, &crow, &ccol); + } + else{ + PaintCell(row, col, gmp->cpf, gmp->current, 1); + crow = row; + ccol = col; + } + break; + + case (CTRL|'A'): /* beginning of line */ + tp = gmp->current; + i = col; + while(i > 0){ + i -= gmp->cpf; + if(tp->prev != NULL) + tp = tp->prev; + } + PlaceCell(gmp, gmp->current, &row, &col); + PaintCell(row, col, gmp->cpf, gmp->current, 0); + gmp->current = tp; + if(PlaceCell(gmp, tp, &row, &col)){ + PaintBrowser(gmp, 1, &crow, &ccol); + } + else{ + PaintCell(row, col, gmp->cpf, gmp->current, 1); + crow = row; + ccol = col; + } + break; + + case (CTRL|'E'): /* end of line */ + tp = gmp->current; + i = col + gmp->cpf; + while(i+gmp->cpf <= gmp->cpf * gmp->fpl){ + i += gmp->cpf; + if(tp->next != NULL) + tp = tp->next; + } + + PlaceCell(gmp, gmp->current, &row, &col); + PaintCell(row, col, gmp->cpf, gmp->current, 0); + gmp->current = tp; + if(PlaceCell(gmp, tp, &row, &col)){ + PaintBrowser(gmp, 1, &crow, &ccol); + } + else{ + PaintCell(row, col, gmp->cpf, gmp->current, 1); + crow = row; + ccol = col; + } + break; + + case (CTRL|'V'): /* page forward */ + case ' ': + case KEY_PGDN : + case KEY_END : + tp = gmp->top; + i = term.t_nrow - term.t_mrow - 2; + + while(i-- && tp->next != NULL){ + j = 0; + while(++j <= gmp->fpl && tp->next != NULL) + tp = tp->next; + } + + if(tp == NULL) + continue; + + PlaceCell(gmp, gmp->current, &row, &col); + PaintCell(row, col, gmp->cpf, gmp->current, 0); + gmp->current = tp; + if(PlaceCell(gmp, tp, &row, &col)){ + PaintBrowser(gmp, 1, &crow, &ccol); + } + else{ + PaintCell(row, col, gmp->cpf, gmp->current, 1); + crow = row; + ccol = col; + } + break; + + case '-' : + case (CTRL|'Y'): /* page backward */ + case KEY_PGUP : + case KEY_HOME : + tp = gmp->top; + i = term.t_nrow - term.t_mrow - 4; + while(i-- && tp != NULL){ + j = gmp->fpl; + while(j-- && tp != NULL) + tp = tp->prev; + } + + if(tp || (gmp->current != gmp->top)){ /* clear old hilite */ + PlaceCell(gmp, gmp->current, &row, &col); + PaintCell(row, col, gmp->cpf, gmp->current, 0); + } + + if(tp) /* new page ! */ + gmp->current = tp; + else if(gmp->current != gmp->top) /* goto top of page */ + gmp->current = gmp->top; + else /* do nothing */ + continue; + + if(PlaceCell(gmp, gmp->current, &row, &col)){ + PaintBrowser(gmp, 1, &crow, &ccol); + } + else{ + PaintCell(row, col, gmp->cpf, gmp->current, 1); + crow = row; + ccol = col; + } + + break; + + case KEY_DOWN : + case (CTRL|'N'): /* next */ + tp = gmp->current; + i = gmp->fpl; + while(i--){ + if(tp->next == NULL){ + (*term.t_beep)(); + break; + } + else + tp = tp->next; + } + if(i != -1) /* can't go down */ + break; + + PlaceCell(gmp, gmp->current, &row, &col); + PaintCell(row, col, gmp->cpf, gmp->current, 0); + gmp->current = tp; + if(PlaceCell(gmp, tp, &row, &col)){ + PaintBrowser(gmp, 1, &crow, &ccol); + } + else{ + PaintCell(row, col, gmp->cpf, gmp->current, 1); + crow = row; + ccol = col; + } + break; + + case KEY_UP : + case (CTRL|'P'): /* previous */ + tp = gmp->current; + i = gmp->fpl; + while(i-- && tp) + tp = tp->prev; + + if(tp == NULL) + break; + + PlaceCell(gmp, gmp->current, &row, &col); + PaintCell(row, col, gmp->cpf, gmp->current, 0); + gmp->current = tp; + if(PlaceCell(gmp, tp, &row, &col)){ + PaintBrowser(gmp, 1, &crow, &ccol); + } + else{ + PaintCell(row, col, gmp->cpf, gmp->current, 1); + crow = row; + ccol = col; + } + break; + +#ifdef MOUSE + case KEY_MOUSE: + mouse_get_last (NULL, &mousep); + if (mousep.doubleclick) { + goto Selected; + } + else { + row = mousep.row -= 2; /* Adjust for header*/ + col = mousep.col; + i = row * gmp->fpl + (col / gmp->cpf); /* Count from top */ + tp = gmp->top; /* start at top. */ + for (; i > 0 && tp != NULL; --i) /* Count cells. */ + tp = tp->next; + if (tp != NULL) { /* Valid cell? */ + PlaceCell(gmp, gmp->current, &row, &col); + PaintCell(row, col, gmp->cpf, gmp->current, 0); + gmp->current = tp; + if(PlaceCell(gmp, tp, &row, &col)){ + PaintBrowser(gmp, 1, &crow, &ccol); + } + else{ + PaintCell(row, col, gmp->cpf, gmp->current, 1); + crow = row; + ccol = col; + } + } + } + break; +#endif + + case 'e': /* exit or edit */ + case 'E': + if(gmode&MDBRONLY){ /* run "pico" */ + sprintf(child, "%s%c%s", gmp->dname, C_FILESEP, + gmp->current->fname); + /* make sure selected isn't a directory or executable */ + if(!LikelyASCII(child)){ + emlwrite("Can't edit non-text file. Try Launch.", NULL); + break; + } + + if(envp = (char *) getenv("EDITOR")) + sprintf(tmp, "%s \'%s\'", envp, child); + else + sprintf(tmp, "pico%s%s%s \'%s\'", + (gmode & MDFKEY) ? " -f" : "", + (gmode & MDSHOCUR) ? " -g" : "", + (gmode & MDMOUSE) ? " -m" : "", + child); + + BrowserRunChild(tmp, gmp->dname); /* spawn pico */ + PaintBrowser(gmp, 0, &crow, &ccol); /* redraw browser */ + } + else{ + zotmaster(&gmp); + return(0); + } + + break; + + case 'q': /* user exits wrong */ + case 'Q': + if(gmode&MDBRONLY){ + zotmaster(&gmp); + return(0); + } + + emlwrite("\007Unknown command '%c'", (void *)c); + break; + + case 'x': /* toggle selection */ + case 'X': + if(!(gmp->flags & FB_LMODE)){ + if(gmp->flags & FB_LMODEPOS) + emlwrite("\007Type L command to use ListMode", NULL); + else + emlwrite("\007Unknown command '%c'", (void *)c); + + break; + } + + if(gmp->current->mode == FIODIR){ + emlwrite("\007Can't Set directories", NULL); + break; + } + + if(fcell_is_selected(gmp->current, gmp)) + del_cell_from_lmlist(gmp->current, gmp); + else + add_cell_to_lmlist(gmp->current, gmp); + + PlaceCell(gmp, gmp->current, &row, &col); + PaintCell(row, col, gmp->cpf, gmp->current, 1); + break; + + case 'l': /* run Command */ + case 'L': /* or ListMode */ + if(gmp->flags & FB_LMODEPOS){ + if(gmp->flags & FB_LMODE){ + /* + * Unless we make it so you can get out of ListMode + * once you're in ListMode, this must be an error. + */ + emlwrite("\007Already in ListMode", NULL); + break; + } + else{ + gmp->flags |= FB_LMODE; + PaintBrowser(gmp, 0, &crow, &ccol); + } + + break; + } + + if(!(gmode&MDBRONLY)){ + emlwrite("\007Unknown command '%c'", (void *)c); + break; + } + +/* add subcommands to invoke pico and insert selected filename */ +/* perhaps: add subcmd to scroll command history */ + + tmp[0] = '\0'; + i = 0; + sprintf(child, "%s%c%s", gmp->dname, C_FILESEP, + gmp->current->fname); + while(!i){ + static EXTRAKEYS opts[] = { + {"^X", "Add Name", CTRL|'X', KS_NONE}, + {NULL, NULL, 0, KS_NONE}, + }; + + status = mlreply("Command to execute: ", + tmp, NLINE, QNORML, opts); + switch(status){ + case HELPCH: + emlwrite("\007No help yet!", NULL); +/* remove break and sleep after help text is installed */ + sleep(3); + break; + case (CTRL|'X'): + strcat(tmp, child); + break; + case (CTRL|'L'): + PaintBrowser(gmp, 0, &crow, &ccol); + break; + case ABORT: + emlwrite("Command cancelled", NULL); + i++; + break; + case FALSE: + case TRUE: + i++; + + if(tmp[0] == '\0'){ + emlwrite("No command specified", NULL); + break; + } + + BrowserRunChild(tmp, gmp->dname); + PaintBrowser(gmp, 0, &crow, &ccol); + break; + default: + break; + } + } + + BrowserKeys(); + break; + + case 'd': /* delete */ + case 'D': + if(gmp->current->mode == FIODIR){ +/* BUG: if dir is empty it should be deleted */ + emlwrite("\007Can't delete a directory", NULL); + break; + } + + if(gmode&MDSCUR){ /* not allowed! */ + emlwrite("Delete not allowed in restricted mode",NULL); + break; + } + + sprintf(child, "%s%c%s", gmp->dname, C_FILESEP, + gmp->current->fname); + + i = 0; + while(i++ < 2){ /* verify twice!! */ + if(i == 1){ + if(fexist(child, "w", (off_t *)NULL) != FIOSUC) + strcpy(tmp, "File is write protected! OVERRIDE"); + else + sprintf(tmp, "Delete file \"%.*s\"", NLINE - 20, child); + } + else + strcpy(tmp, "File CANNOT be UNdeleted! Really delete"); + + if((status = mlyesno(tmp, FALSE)) != TRUE){ + emlwrite((status == ABORT) + ? "Delete Cancelled" + : "File Not Deleted", + NULL); + break; + } + } + + if(status == TRUE){ + if(unlink(child) < 0){ + emlwrite("Delete Failed: %s", errstr(errno)); + } + else{ /* fix up pointers and redraw */ + tp = gmp->current; + if(tp->next){ + gmp->current = tp->next; + if(tp->next->prev = tp->prev) + tp->prev->next = tp->next; + } + else if(tp->prev) { + gmp->current = tp->prev; + if(tp->prev->next = tp->next) + tp->next->prev = tp->prev; + } + + if(tp == gmp->head) + gmp->head = tp->next; + + tp->fname = NULL; + tp->next = tp->prev = NULL; + if(tp != gmp->current) + free((char *) tp); + + if((tp = FindCell(gmp, gmp->current->fname)) != NULL){ + gmp->current = tp; + PlaceCell(gmp, gmp->current, &row, &col); + } + + PaintBrowser(gmp, 1, &crow, &ccol); + mlerase(); + } + } + + BrowserKeys(); + break; + + case '?': /* HELP! */ + case (CTRL|'G'): + if(term.t_mrow == 0){ + if(km_popped == 0){ + km_popped = 2; + break; + } + } + + if(Pmaster){ + VARS_TO_SAVE *saved_state; + + saved_state = save_pico_state(); + (*Pmaster->helper)(Pmaster->browse_help, + "Help for Browsing", 1); + if(saved_state){ + restore_pico_state(saved_state); + free_pico_state(saved_state); + } + } + else if(gmode&MDBRONLY) + pico_help(sa_BrowseHelpText, "Browser Help", 1); + else + pico_help(BrowseHelpText, "Help for Browsing", 1); + /* fall thru to repaint everything */ + + case (CTRL|'L'): + PaintBrowser(gmp, 0, &crow, &ccol); + break; + + case 'g': /* jump to a directory */ + case 'G': + + if(!(gmode&MDGOTO)) + goto Default; + + i = 0; + child[0] = '\0'; + + while(!i){ + + status = mlreply("Directory to go to: ", child, NLINE, QNORML, + NULL); + + switch(status){ + case HELPCH: + emlwrite("\007No help yet!", NULL); + /* remove break and sleep after help text is installed */ + sleep(3); + break; + case (CTRL|'L'): + PaintBrowser(gmp, 0, &crow, &ccol); + break; + case ABORT: + emlwrite("Goto cancelled", NULL); + i++; + break; + case FALSE: + case TRUE: + i++; + + if(*child == '\0') + strcpy(child, gethomedir(NULL)); + + if(!compresspath(gmp->dname, child, NLINE)){ + emlwrite("Invalid Directory: %s", child); + break; + } + + if((gmode&MDSCUR) && homeless(child)){ + emlwrite("Restricted mode browsing limited to home directory",NULL); + break; + } + + if((gmode&MDTREE) && !in_oper_tree(child)){ + emlwrite("\007 Can't go outside of %s in restricted mode", + opertree); + break; + } + + if(isdir(child, (long *) NULL, NULL)){ + if((mp = getfcells(child, fb_flags)) == NULL){ + /* getfcells should explain what happened */ + i++; + break; + } + + zotmaster(&gmp); + gmp = mp; + PaintBrowser(gmp, 0, &crow, &ccol); + } + else + emlwrite("\007Not a directory: \"%s\"", child); + + break; + default: + break; + } + } + BrowserKeys(); + break; + + case 'a': /* Add */ + case 'A': + if(gmode&MDSCUR){ /* not allowed! */ + emlwrite("Add not allowed in restricted mode",NULL); + break; + } + + i = 0; + child[0] = '\0'; + /* pass in default filename */ + if(fn && *fn){ + strncpy(child, fn, sizeof(child) - 1); + child[sizeof(child) - 1] = '\0'; + } + + while(!i){ + + switch(status=mlreply("Name of file to add: ", child, NLINE, + QFFILE, NULL)){ + case HELPCH: + emlwrite("\007No help yet!", NULL); +/* remove break and sleep after help text is installed */ + sleep(3); + break; + case (CTRL|'L'): + PaintBrowser(gmp, 0, &crow, &ccol); + break; + case ABORT: + emlwrite("Add File Cancelled", NULL); + i++; + break; + case FALSE: + /* + * Support default filename. A return of 'FALSE' means + * 'No change in filename' which is fine if we have + * provided a default. + * John Berthels + */ + /* FALLTHROUGH */ + case TRUE: + i++; + + if(child[0] == '\0'){ + emlwrite("No file named. Add Cancelled.", NULL); + break; + } + + if(!compresspath(gmp->dname, child, NLINE)){ + emlwrite("Too many ..'s in name", NULL); + break; + } + + if((gmode&MDTREE) && !in_oper_tree(child)){ + emlwrite("\007Restricted mode allows Add in %s only", + opertree); + break; + } + + if((status = fexist(child, "w", (off_t *)NULL)) == FIOSUC){ + sprintf(tmp,"File \"%.*s\" already exists!", + NLINE - 20, child); + emlwrite(tmp, NULL); + break; + } + else if(status != FIOFNF){ + fioperr(status, child); + break; + } + + if(ffwopen(child, FALSE) != FIOSUC){ + /* ffwopen should've complained */ + break; + } + else{ /* highlight new file */ + ffclose(); + emlwrite("Added File \"%s\"", child); + + if((p = strrchr(child, C_FILESEP)) == NULL){ + emlwrite("Problems refiguring browser", NULL); + break; + } + + *p = '\0'; + if(p != child){ + strcpy(tmp, child); + j = 0; + while(child[j++] = *++p) + ; + } + else + strcpy(tmp, S_FILESEP); + + /* + * new file in same dir? if so, refigure files + * and redraw... + */ + if(!strcmp(tmp, gmp->dname)){ + if((mp = getfcells(gmp->dname, fb_flags)) == NULL) + /* getfcells should explain what happened */ + break; + + zotmaster(&gmp); + gmp = mp; + if((tp = FindCell(gmp, child)) != NULL){ + gmp->current = tp; + PlaceCell(gmp, gmp->current, &row, &col); + } + + PaintBrowser(gmp, 1, &crow, &ccol); + } + } + break; + default: + break; + } + } + + BrowserKeys(); + break; + + case 'c': /* copy */ + case 'C': + if(gmp->current->mode == FIODIR){ + emlwrite("\007Can't copy a directory", NULL); + break; + } + + if(gmode&MDSCUR){ /* not allowed! */ + emlwrite("Copy not allowed in restricted mode",NULL); + break; + } + + i = 0; + child[0] = '\0'; + + while(!i){ + + switch(status=mlreply("Name of new copy: ", child, NLINE, + QFFILE, NULL)){ + case HELPCH: + emlwrite("\007No help yet!", NULL); +/* remove break and sleep after help text is installed */ + sleep(3); + break; + case (CTRL|'L'): + PaintBrowser(gmp, 0, &crow, &ccol); + break; + case ABORT: + emlwrite("Make Copy Cancelled", NULL); + i++; + break; + case FALSE: + i++; + mlerase(); + break; + case TRUE: + i++; + + if(child[0] == '\0'){ + emlwrite("No destination, file not copied", NULL); + break; + } + + if(!strcmp(gmp->current->fname, child)){ + emlwrite("\007Can't copy file on to itself!", NULL); + break; + } + + if(!compresspath(gmp->dname, child, NLINE)){ + emlwrite("Too many ..'s in name", NULL); + break; + } + + if((gmode&MDTREE) && !in_oper_tree(child)){ + emlwrite("\007Restricted mode allows Copy in %s only", + opertree); + break; + } + + if((status = fexist(child, "w", (off_t *)NULL)) == FIOSUC){ + sprintf(tmp,"File \"%.*s\" exists! OVERWRITE", + NLINE - 20, child); + if((status = mlyesno(tmp, 0)) != TRUE){ + emlwrite((status == ABORT) + ? "Make copy cancelled" + : "File Not Renamed", + NULL); + break; + } + } + else if(status != FIOFNF){ + fioperr(status, child); + break; + } + + sprintf(tmp, "%s%c%s", gmp->dname, C_FILESEP, + gmp->current->fname); + + if(copy(tmp, child) < 0){ + /* copy() will report any error messages */ + break; + } + else{ /* highlight new file */ + emlwrite("File copied to %s", child); + + if((p = strrchr(child, C_FILESEP)) == NULL){ + emlwrite("Problems refiguring browser", NULL); + break; + } + + *p = '\0'; + strcpy(tmp, (p == child) ? S_FILESEP: child); + + /* + * new file in same dir? if so, refigure files + * and redraw... + */ + if(!strcmp(tmp, gmp->dname)){ + strcpy(child, gmp->current->fname); + if((mp = getfcells(gmp->dname, fb_flags)) == NULL) + /* getfcells should explain what happened */ + break; + + zotmaster(&gmp); + gmp = mp; + if((tp = FindCell(gmp, child)) != NULL){ + gmp->current = tp; + PlaceCell(gmp, gmp->current, &row, &col); + } + + PaintBrowser(gmp, 1, &crow, &ccol); + } + } + break; + default: + break; + } + } + BrowserKeys(); + break; + + case 'r': /* rename */ + case 'R': + i = 0; + + if(!strcmp(gmp->current->fname, "..")){ + emlwrite("\007Can't rename \"..\"", NULL); + break; + } + + if(gmode&MDSCUR){ /* not allowed! */ + emlwrite("Rename not allowed in restricted mode",NULL); + break; + } + + strcpy(child, gmp->current->fname); + + while(!i){ + + switch(status=mlreply("Rename file to: ", child, NLINE, QFFILE, + NULL)){ + case HELPCH: + emlwrite("\007No help yet!", NULL); +/* remove break and sleep after help text is installed */ + sleep(3); + break; + case (CTRL|'L'): + PaintBrowser(gmp, 0, &crow, &ccol); + break; + case ABORT: + emlwrite("Rename cancelled", NULL); + i++; + break; + case FALSE: + case TRUE: + i++; + + if(child[0] == '\0' || status == FALSE){ + mlerase(); + break; + } + + if(!compresspath(gmp->dname, child, NLINE)){ + emlwrite("Too many ..'s in name", NULL); + break; + } + + if((gmode&MDTREE) && !in_oper_tree(child)){ + emlwrite("\007Restricted mode allows Rename in %s only", + opertree); + break; + } + + status = fexist(child, "w", (off_t *)NULL); + if(status == FIOSUC || status == FIOFNF){ + if(status == FIOSUC){ + sprintf(tmp,"File \"%.*s\" exists! OVERWRITE", + NLINE - 20, child); + + if((status = mlyesno(tmp, FALSE)) != TRUE){ + emlwrite((status == ABORT) + ? "Rename cancelled" + : "Not Renamed", + NULL); + break; + } + } + + sprintf(tmp, "%s%c%s", gmp->dname, C_FILESEP, + gmp->current->fname); + + if(rename(tmp, child) < 0){ + emlwrite("Rename Failed: %s", errstr(errno)); + } + else{ + if((p = strrchr(child, C_FILESEP)) == NULL){ + emlwrite("Problems refiguring browser", NULL); + break; + } + + *p = '\0'; + strcpy(tmp, (p == child) ? S_FILESEP: child); + + if((mp = getfcells(tmp, fb_flags)) == NULL) + /* getfcells should explain what happened */ + break; + + zotmaster(&gmp); + gmp = mp; + + if((tp = FindCell(gmp, ++p)) != NULL){ + gmp->current = tp; + PlaceCell(gmp, gmp->current, &row, &col); + } + + PaintBrowser(gmp, 1, &crow, &ccol); + mlerase(); + } + } + else{ + fioperr(status, child); + } + break; + default: + break; + } + } + BrowserKeys(); + break; + + case 'v': /* stand-alone */ + case 'V': /* browser "view" */ + case 's': /* user "select" */ + case 'S': + case (CTRL|'M'): + Selected: + + if((toupper(new_c) == 'S' && (gmode&MDBRONLY)) + || (toupper(new_c) == 'V' && !(gmode&MDBRONLY))) + goto Default; + + if(gmp->current->mode == FIODIR){ + *child = '\0'; + strcpy(tmp, gmp->dname); + p = gmp->current->fname; + if(p[0] == '.' && p[1] == '.' && p[2] == '\0'){ + if((p=strrchr(tmp, C_FILESEP)) != NULL){ + *p = '\0'; + + if((gmode&MDTREE) && !in_oper_tree(tmp)){ + emlwrite( + "\007Can't visit parent in restricted mode", + NULL); + break; + } + + strcpy(child, &p[1]); + if +#if defined(DOS) || defined(OS2) + (p == tmp || (tmp[1] == ':' && tmp[2] == '\0')) +#else + (p == tmp) +#endif + { /* is it root? */ +#if defined(DOS) || defined(OS2) + if(*child) + strcat(tmp, S_FILESEP); +#else + if(*child) + strcpy(tmp, S_FILESEP); +#endif + else{ + emlwrite("\007Can't move up a directory", + NULL); + break; + } + } + } + } + else if((fb_flags&FB_SAVE) && p[0] == '.' && p[1] == '\0'){ + if ((strlen(gmp->dname) < dirlen) && + (strlen(gmp->current->fname) < fnlen)){ + strcpy(dir, gmp->dname); + } + zotmaster(&gmp); + return(0); /* just change the directory, still return no selection */ + } + else{ + if(tmp[1] != '\0') /* were in root? */ + strcat(tmp, S_FILESEP); + strcat(tmp, gmp->current->fname); + } + + if((mp = getfcells(tmp, fb_flags)) == NULL) + /* getfcells should explain what happened */ + break; + + if(gmp->flags & FB_LMODE){ + mp->flags |= FB_LMODE; + mp->lm = gmp->lm; + gmp->lm = NULL; + } + + zotmaster(&gmp); + gmp = mp; + tp = NULL; + + if(*child){ + if((tp = FindCell(gmp, child)) != NULL){ + gmp->current = tp; + PlaceCell(gmp, gmp->current, &row, &col); + } + else + emlwrite("\007Problem finding dir \"%s\"",child); + } + + PaintBrowser(gmp, 0, &crow, &ccol); + if(!*child) + emlwrite("Select/View \".. parent dir\" to return to previous directory.", + NULL); + + break; + } + else if(gmode&MDBRONLY){ + sprintf(child, "%s%c%s", gmp->dname, C_FILESEP, + gmp->current->fname); + + if(LikelyASCII(child)){ + sprintf(tmp, "%s \'%s\'", + (envp = (char *) getenv("PAGER")) + ? envp : BROWSER_PAGER, child); + BrowserRunChild(tmp, gmp->dname); + PaintBrowser(gmp, 0, &crow, &ccol); + } + + break; + } + else{ /* just return */ + if(gmp->flags & FB_LMODEPOS){ + + if(!lmreturn){ + emlwrite("Programming error, called FileBrowse with LMODEPOS but no lmreturn", NULL); + zotmaster(&gmp); + return(-1); + } + + /* user actually used ListMode, the list is finished */ + if(gmp->flags & FB_LMODE){ + *lmreturn = gmp->lm; + gmp->lm = NULL; + } + else{ /* construct an lmreturn for user */ + LMLIST *new; + + if((new=(LMLIST *)malloc(sizeof(*new))) == NULL + || (new->fname=malloc(gmp->current->fname ? strlen(gmp->current->fname)+1 : 1)) == NULL + || (new->dir=malloc(strlen(gmp->dname)+1)) == NULL){ + emlwrite("\007Can't malloc space for filename", NULL); + return(-1); + } + + strcpy(new->fname, + gmp->current->fname ? gmp->current->fname : ""); + strcpy(new->dir, gmp->dname); + strcpy(new->size, gmp->current->size); + new->next = NULL; + *lmreturn = new; + } + + return(1); + } + + if ((strlen(gmp->dname) < dirlen) && + (strlen(gmp->current->fname) < fnlen)){ + strcpy(dir, gmp->dname); + strcpy(fn, gmp->current->fname); + } + else { + zotmaster(&gmp); + return(-1); + } + if(sz != NULL) /* size uninteresting */ + strcpy(sz, gmp->current->size); + + zotmaster (&gmp); + return (1); + } + break; + + case 'w': /* Where is */ + case 'W': + case (CTRL|'W'): + i = 0; + + while(!i){ + + switch(readpattern("File name to find", FALSE)){ + case HELPCH: + emlwrite("\007No help yet!", NULL); +/* remove break and sleep after help text is installed */ + sleep(3); + break; + case (CTRL|'L'): + PaintBrowser(gmp, 0, &crow, &ccol); + break; + case (CTRL|'Y'): /* first first cell */ + for(tp = gmp->top; tp->prev; tp = tp->prev) + ; + + i++; + /* fall thru to repaint */ + case (CTRL|'V'): + if(!i){ + do{ + tp = gmp->top; + if((i = term.t_nrow - term.t_mrow - 2) <= 0) + break; + + while(i-- && tp->next){ + j = 0; + while(++j <= gmp->fpl && tp->next) + tp = tp->next; + } + + if(i < 0) + gmp->top = tp; + } + while(tp->next); + + emlwrite("Searched to end of directory", NULL); + } + else + emlwrite("Searched to start of directory", NULL); + + if(tp){ + PlaceCell(gmp, gmp->current, &row, &col); + PaintCell(row, col, gmp->cpf, gmp->current, 0); + gmp->current = tp; + if(PlaceCell(gmp, gmp->current, &row, &col)){ + PaintBrowser(gmp, 1, &crow, &ccol); + } + else{ + PaintCell(row, col, gmp->cpf, gmp->current, 1); + crow = row; + ccol = col; + } + } + + i++; /* make sure we jump out */ + break; + case ABORT: + emlwrite("Whereis cancelled", NULL); + i++; + break; + case FALSE: + mlerase(); + i++; + break; + case TRUE: + if((tp = FindCell(gmp, pat)) != NULL){ + PlaceCell(gmp, gmp->current, &row, &col); + PaintCell(row, col, gmp->cpf, gmp->current, 0); + gmp->current = tp; + + if(PlaceCell(gmp, tp, &row, &col)){ /* top changed */ + PaintBrowser(gmp, 1, &crow, &ccol); + } + else{ + PaintCell(row, col, gmp->cpf, gmp->current, 1); + crow = row; + ccol = col; + } + mlerase(); + } + else + emlwrite("\"%s\" not found", pat); + + i++; + break; + default: + break; + } + } + + BrowserKeys(); + break; + + case (CTRL|'Z'): + if(gmode&MDSSPD){ + bktoshell(); + PaintBrowser(gmp, 0, &crow, &ccol); + break; + } /* fall thru with error! */ + + default: /* what? */ + Default: + if(c < 0xff) + emlwrite("\007Unknown command: '%c'", (void *) c); + else if(c & CTRL) + emlwrite("\007Unknown command: ^%c", (void *)(c&0xff)); + else + emlwrite("\007Unknown command", NULL); + case NODATA: /* no op */ + break; + } + } +} + + + +/* + * getfcells - make a master browser struct and fill it in + * return NULL if there's a problem. + */ +struct bmaster * +getfcells(dname, fb_flags) + char *dname; + int fb_flags; +{ + int i, /* various return codes */ + flength, + nentries = 0; /* number of dir ents */ + off_t attsz; + char *np, /* names of files in dir */ + *dcp, /* to add file to path */ + *tmpstr, + **filtnames, /* array filtered names */ + errbuf[NLINE]; + struct fcell *ncp, /* new cell pointer */ + *tcp; /* trailing cell ptr */ + struct bmaster *mp; + + errbuf[0] = '\0'; + if((mp=(struct bmaster *)malloc(sizeof(struct bmaster))) == NULL){ + emlwrite("\007Can't malloc space for master filename cell", NULL); + return(NULL); + } + + memset(mp, 0, sizeof(*mp)); + + if(dname[0] == '.' && dname[1] == '\0'){ /* remember this dir */ + if(!getcwd(mp->dname, 256)) + mp->dname[0] = '\0'; + } + else if(dname[0] == '.' && dname[1] == '.' && dname[2] == '\0'){ + if(!getcwd(mp->dname, 256)) + mp->dname[0] = '\0'; + else{ + if((np = (char *)strrchr(mp->dname, C_FILESEP)) != NULL) + if(np != mp->dname) + *np = '\0'; + } + } + else + strcpy(mp->dname, dname); + + mp->head = mp->top = NULL; + mp->cpf = mp->fpl = 0; + mp->longest = 5; /* .. must be labeled! */ + mp->flags = fb_flags; + + emlwrite("Building file list of %s...", mp->dname); + + if((mp->names = getfnames(mp->dname, NULL, &nentries, errbuf)) == NULL){ + free((char *) mp); + if(*errbuf) + emlwrite(errbuf, NULL); + + return(NULL); + } + + /* + * this is the fun part. build an array of pointers to the fnames we're + * interested in (i.e., do any filtering), then pass that off to be + * sorted before building list of cells... + * + * right now default filtering on ".*" except "..", but this could + * easily be made a user option later on... + */ + if((filtnames=(char **)malloc((nentries+1) * sizeof(char *))) == NULL){ + emlwrite("\007Can't malloc space for name array", NULL); + zotmaster(&mp); + return(NULL); + } + + i = 0; /* index of filt'd array */ + np = mp->names; + while(nentries--){ + int ii; + + /* + * Filter dot files? Always filter ".", never filter "..", + * and sometimes fitler ".*"... + */ + if(*np == '.' && (!(*(np+1) == '.' && *(np+2) == '\0') + && !(*(np+1) == '\0' && (fb_flags&FB_SAVE))) + && (*(np+1) == '\0' || !(gmode & MDDOTSOK))){ + np += strlen(np) + 1; + continue; + } + + filtnames[i++] = np; + + if((ii = (int)strlen(np)) > mp->longest) + mp->longest = ii; /* remember longest */ + np += ii + 1; /* advance name pointer */ + + } + nentries = i; /* new # of entries */ + + /* + * sort files case independently + */ + qsort((QSType *)filtnames, (size_t)nentries, sizeof(char *), sstrcasecmp); + + /* + * this is so we use absolute path names for stats. + * remember: be careful using dname as directory name, and fix mp->dname + * when we're done + */ + dcp = (char *)strchr(mp->dname, '\0'); + if(dcp == mp->dname || dcp[-1] != C_FILESEP){ + dcp[0] = C_FILESEP; + dcp[1] = '\0'; + } + else + dcp--; + + i = 0; + while(nentries--){ /* stat filtered files */ + /* get a new cell */ + if((ncp=(struct fcell *)malloc(sizeof(struct fcell))) == NULL){ + emlwrite("\007Can't malloc cells for browser!", NULL); + zotfcells(mp->head); /* clean up cells */ + free((char *) filtnames); + free((char *) mp); + return(NULL); /* bummer. */ + } + ncp->next = ncp->prev = NULL; + + if(mp->head == NULL){ /* tie it onto the list */ + mp->head = mp->top = mp->current = ncp; + } + else{ + tcp->next = ncp; + ncp->prev = tcp; + } + tcp = ncp; + + /* fill in the new cell */ + ncp->fname = filtnames[i++]; + + /* fill in file's mode */ + if ((flength = strlen(ncp->fname) + 1 + strlen(dname)) < NLINE){ + strcpy(&dcp[1], ncp->fname); /* use absolute path! */ + tmpstr = mp->dname; + } + else{ + if((tmpstr = (char *)malloc((flength+1)*sizeof(char))) == NULL){ + emlwrite("\007Can't malloc cells for temp buffer!", NULL); + zotfcells(mp->head); /* clean up cells */ + free((char *) filtnames); + free((char *) mp); + return(NULL); /* bummer. */ + } + strcpy(tmpstr, dname); + tmpstr = strcat(tmpstr, S_FILESEP); + tmpstr = strcat(tmpstr, ncp->fname); + } + switch(fexist(tmpstr, "t", &attsz)){ + case FIODIR : + ncp->mode = FIODIR; + sprintf(ncp->size, "(%sdir)", + (ncp->fname[0] == '.' && ncp->fname[1] == '.' + && ncp->fname[2] == '\0') ? "parent " : + ((fb_flags&FB_SAVE) && ncp->fname[0] == '.' && ncp->fname[1] == '\0' + ? "SELECT " : "")); + break; + case FIOSYM : + ncp->mode = FIOSYM; + strcpy(ncp->size, "--"); + break; + default : + ncp->mode = FIOSUC; /* regular file */ + strcpy(ncp->size, prettysz(attsz)); + break; + } + if (flength >= NLINE) + free((char *) tmpstr); + } + + dcp[(dcp == mp->dname) ? 1 : 0] = '\0'; /* remember to cap dname */ + free((char *) filtnames); /* 'n blast filt'd array*/ + + percdircells(mp); + layoutcells(mp); + if(strlen(mp->dname) < NLINE) + strcpy(browse_dir, mp->dname); + else + browse_dir[0] = '\0'; + return(mp); +} + + + +int +fcell_is_selected(cell, mp) +struct fcell *cell; +struct bmaster *mp; +{ + LMLIST *lm; + + if(cell && cell->fname){ + for(lm = mp ? mp->lm : NULL; lm; lm = lm->next){ + /* directory has to match */ + if(!((mp->dname[0] == '\0' && (!lm->dir || lm->dir[0] =='\0')) + || (mp->dname[0] != '\0' && lm->dir && lm->dir[0] !='\0' + && !strcmp(mp->dname, lm->dir)))) + continue; + + if(lm->fname && !strcmp(cell->fname, lm->fname)) + return(1); + } + } + + return(0); +} + + +/* + * Adds a new name to the head of the lmlist + */ +void +add_cell_to_lmlist(cell, mp) +struct fcell *cell; +struct bmaster *mp; +{ + LMLIST *new; + + if(mp && cell && cell->fname && cell->fname[0]){ + if((new=(LMLIST *)malloc(sizeof(*new))) == NULL || + (new->fname=malloc(sizeof(char)*(strlen(cell->fname)+1))) == NULL || + (new->dir=malloc(sizeof(char)*(strlen(mp->dname)+1))) == NULL){ + emlwrite("\007Can't malloc space for filename", NULL); + return; + } + + strcpy(new->fname, cell->fname); + strcpy(new->dir, mp->dname); + new->size[0] = '\0'; + if(cell->size[0]) + strcpy(new->size, cell->size); + + new->next = mp->lm; + mp->lm = new; + } +} + + +/* + * Deletes a name from the lmlist + */ +void +del_cell_from_lmlist(cell, mp) +struct fcell *cell; +struct bmaster *mp; +{ + LMLIST *lm, *lmprev = NULL; + + if(mp && cell && cell->fname && cell->fname[0]) + for(lm = mp ? mp->lm : NULL; lm; lm = lm->next){ + if(lm->fname && strcmp(cell->fname, lm->fname) == 0){ + free((char *) lm->fname); + if(lm->dir) + free((char *) lm->dir); + + if(lmprev) + lmprev->next = lm->next; + else + mp->lm = lm->next; + + free((char *) lm); + + break; + } + + lmprev = lm; + } +} + + +/* + * PaintCell - print the given cell at the given location on the display + * the format of a printed cell is: + * + * " " + */ +PaintCell(x, y, l, cell, inverted) +struct fcell *cell; +int x, y, l, inverted; +{ + char *p; /* temp str pointer */ + int i = 0, /* current display count */ + j, sl, fl; /* lengths */ + + if(cell == NULL) + return(-1); + + fl = strlen(cell->fname); + sl = strlen(cell->size); + + movecursor(x, y); + + if(gmp && gmp->flags & FB_LMODEPOS && l > 4){ + if(gmp && gmp->flags & FB_LMODE && cell->mode != FIODIR){ + /* + * We have to figure out here if it is selected or not + * and use that to write the X or space. + */ + pputc('[', 0); + if(fcell_is_selected(cell, gmp)) + pputc('X', 0); + else + pputc(' ', 0); + + pputc(']', 0); + pputc(' ', 0); + } + else + pputs(" ", 0); + + l -= 4; + } + + if(inverted) + (*term.t_rev)(1); + + /* room for fname? */ + p = (fl+2 > l) ? &cell->fname[fl-(l-2)] : cell->fname; + while(*p != '\0'){ /* write file name */ + pputc(*p++, 0); + i++; + } + + if(sl+3 <= l-i){ /* room for size? */ + j = (l-i)-(sl+2); /* put space between */ + i += j; + while(j--) /* file name and size */ + pputc(' ', 0); + + p = cell->size; + while(*p != '\0'){ /* write file size */ + pputc(*p++, 0); + i++; + } + } + + if(inverted) + (*term.t_rev)(0); + + while(i++ < l) /* pad ending */ + pputc(' ', 0); + + return(1); +} + + + +/* + * PaintBrowse - with the current data, display the browser. if level == 0 + * paint the whole thing, if level == 1 just paint the cells + * themselves + */ +PaintBrowser(mp, level, row, col) +struct bmaster *mp; +int level; +int *row, *col; +{ + int i, cl; + struct fcell *tp; + + if(!level){ + ClearBrowserScreen(); + BrowserAnchor(mp->dname); + } + + i = 0; + tp = mp->top; + cl = COMPOSER_TOP_LINE; /* current display line */ + while(tp){ + + PaintCell(cl, mp->cpf * i, mp->cpf, tp, tp == mp->current); + + if(tp == mp->current){ + if(row) + *row = cl; + + if(col) + *col = mp->cpf * i; + } + + if(++i >= mp->fpl){ + i = 0; + if(++cl > term.t_nrow-(term.t_mrow+1)) + break; + } + + tp = tp->next; + } + + if(level){ + while(cl <= term.t_nrow - (term.t_mrow+1)){ + if(!i) + movecursor(cl, 0); + peeol(); + movecursor(++cl, 0); + } + } + else{ + BrowserKeys(); + } + + return(1); +} + + +/* + * BrowserKeys - just paints the keyhelp at the bottom of the display + */ +void +BrowserKeys() +{ + menu_browse[QUIT_KEY].name = (gmode&MDBRONLY) ? "Q" : "E"; + menu_browse[QUIT_KEY].label = (gmode&MDBRONLY) ? "Quit" : "Exit Brwsr"; + menu_browse[GOTO_KEY].name = (gmode&MDGOTO) ? "G" : NULL; + menu_browse[GOTO_KEY].label = (gmode&MDGOTO) ? "Goto" : NULL; + if(gmode & MDBRONLY){ + menu_browse[EXEC_KEY].name = "L"; + menu_browse[EXEC_KEY].label = "Launch"; + menu_browse[SELECT_KEY].name = "V"; + menu_browse[SELECT_KEY].label = "[View]"; + menu_browse[PICO_KEY].name = "E"; + menu_browse[PICO_KEY].label = "Edit"; + } + else{ + menu_browse[SELECT_KEY].name = "S"; + menu_browse[SELECT_KEY].label = "[Select]"; + menu_browse[PICO_KEY].name = "A"; + menu_browse[PICO_KEY].label = "Add"; + + if(gmp && gmp->flags & FB_LMODEPOS){ + if(gmp && gmp->flags & FB_LMODE){ /* ListMode is already on */ + menu_browse[EXEC_KEY].name = "X"; + menu_browse[EXEC_KEY].label = "Set/Unset"; + } + else{ /* ListMode is possible */ + menu_browse[EXEC_KEY].name = "L"; + menu_browse[EXEC_KEY].label = "ListMode"; + } + } + else{ /* No ListMode possible */ + menu_browse[EXEC_KEY].name = NULL; + menu_browse[EXEC_KEY].label = NULL; + } + } + + wkeyhelp(menu_browse); +} + + +/* + * layoutcells - figure out max length of cell and how many cells can + * go on a line of the display + */ +void +layoutcells(mp) +struct bmaster *mp; +{ + mp->cpf = mp->longest + 12; /* max chars / file */ + + if(mp->flags & FB_LMODEPOS) + mp->cpf += 4; + + if(gmode & MDONECOL){ + mp->fpl = 1; + } + else{ + int i = 1; + + while(i*mp->cpf < term.t_ncol) /* no force... */ + i++; /* like brute force! */ + + mp->fpl = i - 1; /* files per line */ + } + + if(mp->fpl == 0) + mp->fpl = 1; +} + + +/* + * percdircells - bubble all the directory cells to the top of the + * list. + */ +void +percdircells(mp) +struct bmaster *mp; +{ + struct fcell *dirlp, /* dir cell list pointer */ + *lp, *nlp; /* cell list ptr and next */ + + dirlp = NULL; + for(lp = mp->head; lp; lp = nlp){ + nlp = lp->next; + if(lp->mode == FIODIR){ + if(lp->prev) /* clip from list */ + lp->prev->next = lp->next; + + if(lp->next) + lp->next->prev = lp->prev; + + if(lp->prev = dirlp){ /* tie it into dir portion */ + if(lp->next = dirlp->next) + lp->next->prev = lp; + + dirlp->next = lp; + dirlp = lp; + } + else{ + if((dirlp = lp) != mp->head) + dirlp->next = mp->head; + + if(dirlp->next) + dirlp->next->prev = dirlp; + + mp->head = mp->top = mp->current = dirlp; + } + } + } +} + + +/* + * PlaceCell - given a browser master, return row and col of the display that + * it should go. + * + * return 1 if mp->top has changed, x,y relative to new page + * return 0 if otherwise (same page) + * return -1 on error + */ +PlaceCell(mp, cp, x, y) +struct bmaster *mp; +struct fcell *cp; +int *x, *y; +{ + int cl = COMPOSER_TOP_LINE; /* current line */ + int ci = 0; /* current index on line */ + int rv = 0; + int secondtry = 0; + struct fcell *tp; + + /* will cp fit on screen? */ + tp = mp->top; + while(1){ + if(tp == cp){ /* bingo! */ + *x = cl; + *y = ci * mp->cpf; + break; + } + + if((tp = tp->next) == NULL){ /* above top? */ + if(secondtry++){ + emlwrite("\007Internal error: can't find fname cell", NULL); + return(-1); + } + else{ + tp = mp->top = mp->head; /* try from the top! */ + cl = COMPOSER_TOP_LINE; + ci = 0; + rv = 1; + continue; /* start over! */ + } + } + + if(++ci >= mp->fpl){ /* next line? */ + ci = 0; + if(++cl > term.t_nrow-(term.t_mrow+1)){ /* next page? */ + ci = mp->fpl; /* tp is at bottom right */ + while(ci--) /* find new top */ + tp = tp->prev; + mp->top = tp; + ci = 0; + cl = COMPOSER_TOP_LINE; /* keep checking */ + rv = 1; + } + } + + } + + /* not on display! */ + return(rv); + +} + + +/* + * zotfcells - clean up malloc'd cells of file names + */ +void +zotfcells(hp) +struct fcell *hp; +{ + struct fcell *tp; + + while(hp){ + tp = hp; + hp = hp->next; + tp->next = NULL; + free((char *) tp); + } +} + + +/* + * zotmaster - blast the browser master struct + */ +void +zotmaster(mp) +struct bmaster **mp; +{ + if(mp && *mp){ + zotfcells((*mp)->head); /* free cells */ + zotlmlist((*mp)->lm); /* free lmlist */ + if((*mp)->names) + free((char *)(*mp)->names); /* free file names */ + + free((char *)*mp); /* free master */ + *mp = NULL; /* make double sure */ + } +} + + +/* + * FindCell - starting from the current cell find the first occurance of + * the given string wrapping around if necessary + */ +struct fcell *FindCell(mp, string) +struct bmaster *mp; +char *string; +{ + struct fcell *tp, *fp; + + if(*string == '\0') + return(NULL); + + fp = NULL; + tp = mp->current->next; + + while(tp && !fp){ + if(sisin(tp->fname, string)) + fp = tp; + else + tp = tp->next; + } + + tp = mp->head; + while(tp != mp->current && !fp){ + if(sisin(tp->fname, string)) + fp = tp; + else + tp = tp->next; + } + + return(fp); +} + + +/* + * sisin - case insensitive substring matching function + */ +sisin(s1, s2) +char *s1, *s2; +{ + register int j; + + while(*s1){ + j = 0; + while(toupper((unsigned char)s1[j]) == toupper((unsigned char)s2[j])) + if(s2[++j] == '\0') /* bingo! */ + return(1); + + s1++; + } + return(0); +} + + +/* + * set_browser_title - + */ +void +set_browser_title(s) +char *s; +{ + browser_title = s; +} + + +/* + * BrowserAnchor - draw the browser's anchor line. + */ +void +BrowserAnchor(dir) +char *dir; +{ + register char *p; + register int i, j, l; + char buf[NLINE]; + + movecursor(0, 0); + (*term.t_rev)(1); + + i = 0; + l = strlen(dir); + j = (term.t_ncol-(l+16))/2; + + if(browser_title) + sprintf(buf, " %s", browser_title); + else if(Pmaster) + sprintf(buf, " PINE %s", Pmaster->pine_version); + else + sprintf(buf," UW PICO(tm) %s", (gmode&MDBRONLY) ? "BROWSER" : version); + + p = buf; + while(*p){ + pputc(*p++, 0); + i++; + } + + if(l > term.t_ncol - i - 21){ /* fit dir name on line */ + p = dir; + while((p = strchr(p, C_FILESEP)) && (l-(p-dir)) > term.t_ncol-i-21) + p++; + + if(!p) /* no suitable length! */ + p = &dir[l-(term.t_ncol-i-19)]; + + sprintf(buf, "%s Dir ...%s", (gmode&MDBRONLY) ? "" : " BROWSER ", p); + } + else + sprintf(buf,"%s Dir: %s", (gmode&MDBRONLY) ? "" : " BROWSER ", dir); + + if(i < j) /* keep it centered */ + j = j - i; /* as long as we can */ + else + j = ((term.t_ncol-i)-((int)strlen(p)+15))/2; + + while(j-- && i++) + pputc(' ', 0); + + p = buf; + while(i++ < term.t_ncol && *p) /* show directory */ + pputc(*p++, 0); + + while(i++ < term.t_ncol) + pputc(' ', 0); + + (*term.t_rev)(0); +} + + +/* + * ResizeBrowser - handle a resize event + */ +ResizeBrowser() +{ + if(gmp){ + layoutcells(gmp); + PaintBrowser(gmp, 0, NULL, NULL); + return(1); + } + else + return(0); +} + + +void +ClearBrowserScreen() +{ + int i; + + for(i = 0; i <= term.t_nrow; i++){ /* clear screen */ + movecursor(i, 0); + peeol(); + } +} + + +void +BrowserRunChild(child, dir) + char *child; + char *dir; +{ + int status; + char tmp[NLINE]; + time_t t_in, t_out; + + ClearBrowserScreen(); + movecursor(0, 0); + (*term.t_close)(); + if(!isdir(dir, NULL, &t_in)) + t_in = 0; + + fflush(stdout); + status = system(child); + (*term.t_open)(); + if(t_in && isdir(dir, NULL, &t_out) && t_in < t_out){ + struct bmaster *mp; + + if(mp = getfcells(dir, 0)){ + zotmaster(&gmp); + gmp = mp; + } + /* else getfcells should explain what happened */ + } + + /* complain about non-zero exit status */ + if((status >> 8) & 0xff){ + + movecursor(term.t_nrow - 1, 0); + sprintf(tmp, "[ \"%.30s\" exit with error value: %d ]", + child, (status >> 8) & 0xff); + pputs(tmp, 1); + movecursor(term.t_nrow, 0); + pputs("[ Hit RETURN to continue ]", 1); + fflush(stdout); + + while(GetKey() != (CTRL|'M')){ + (*term.t_beep)(); + fflush(stdout); + } + } +} + +/* + * imitate pc-pine memory for where we last called the file browser. + */ +void +p_chdir(mp) + struct bmaster *mp; +{ + if(mp && mp->dname) + chdir(mp->dname); +} +#endif /* _WINDOWS */ + + +/* + * LikelyASCII - make a rough guess as to the displayability of the + * given file. + */ +int +LikelyASCII(file) + char *file; +{ +#define LA_TEST_BUF 1024 +#define LA_LINE_LIMIT 300 +#if defined(DOS) || defined(OS2) +#define MODE "rb" +#else +#define MODE "r" +#endif + int n, i, line, rv = FALSE; + unsigned char buf[LA_TEST_BUF]; + FILE *fp; + + if(fp = fopen(file, "rb")){ + clearerr(fp); + if((n = fread(buf, sizeof(char), LA_TEST_BUF * sizeof(char), fp)) > 0 + || !ferror(fp)){ + /* + * If we don't hit any newlines in a reasonable number, + * LA_LINE_LIMIT, of characters or the file contains NULLs, + * bag out... + */ + rv = TRUE; + for(i = line = 0; i < n; i++) + if((line = (buf[i] == '\n') ? 0 : line + 1) >= LA_LINE_LIMIT + || !buf[i]){ + rv = FALSE; + emlwrite("Can't display non-text file. Try \"Launch\".", + NULL); + break; + } + } + else + emlwrite("Can't read file: %s", file); + + fclose(fp); + } + else + emlwrite("Can't open file: %s", file); + + return(rv); +} + + +void +zotlmlist(lm) +LMLIST *lm; +{ + LMLIST *tp; + + while(lm){ + if(lm->fname) + free(lm->fname); + + if(lm->dir) + free(lm->dir); + + tp = lm; + lm = lm->next; + tp->next = NULL; + free((char *) tp); + } +} diff --git a/buffer.c b/buffer.c new file mode 100644 index 0000000..0c2295d --- /dev/null +++ b/buffer.c @@ -0,0 +1,367 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: buffer.c 11688 2001-06-21 17:54:43Z hubert $"; +#endif +/* + * Program: Buffer management routines + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2001 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* + * Buffer management. + * Some of the functions are internal, + * and some are actually attached to user + * keys. Like everyone else, they set hints + * for the display system. + */ +#include "headers.h" + +#ifdef ANSI +int sgetline(char **, int *, char *, int); +#else +int sgetline(); +#endif + + +/* + * Look through the list of + * buffers. Return TRUE if there + * are any changed buffers. Buffers + * that hold magic internal stuff are + * not considered; who cares if the + * list of buffer names is hacked. + * Return FALSE if no buffers + * have been changed. + */ +anycb() +{ + register BUFFER *bp; + + bp = bheadp; + while (bp != NULL) { + if ((bp->b_flag&BFTEMP)==0 && (bp->b_flag&BFCHG)!=0) + return (TRUE); + bp = bp->b_bufp; + } + return (FALSE); +} + +/* + * Find a buffer, by name. Return a pointer + * to the BUFFER structure associated with it. If + * the named buffer is found, but is a TEMP buffer (like + * the buffer list) conplain. If the buffer is not found + * and the "cflag" is TRUE, create it. The "bflag" is + * the settings for the flags in in buffer. + */ +BUFFER * +bfind(bname, cflag, bflag) + register char *bname; + int cflag, bflag; +{ + register BUFFER *bp; + register BUFFER *sb; /* buffer to insert after */ + register LINE *lp; + + bp = bheadp; + while (bp != NULL) { + if (strcmp(bname, bp->b_bname) == 0) { + if ((bp->b_flag&BFTEMP) != 0) { + mlwrite("Cannot select builtin buffer", NULL); + return (NULL); + } + return (bp); + } + bp = bp->b_bufp; + } + if (cflag != FALSE) { + if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL) + return (NULL); + if ((lp=lalloc(0)) == NULL) { + free((char *) bp); + return (NULL); + } + /* find the place in the list to insert this buffer */ + if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) { + /* insert at the begining */ + bp->b_bufp = bheadp; + bheadp = bp; + } else { + sb = bheadp; + while (sb->b_bufp != NULL) { + if (strcmp(sb->b_bufp->b_bname, bname) > 0) + break; + sb = sb->b_bufp; + } + + /* and insert it */ + bp->b_bufp = sb->b_bufp; + sb->b_bufp = bp; + } + + /* and set up the other buffer fields */ + bp->b_active = TRUE; + bp->b_dotp = lp; + bp->b_doto = 0; + bp->b_markp = NULL; + bp->b_marko = 0; + bp->b_flag = bflag; + bp->b_mode = gmode; + bp->b_nwnd = 0; + bp->b_linep = lp; + strcpy(bp->b_fname, ""); + strcpy(bp->b_bname, bname); + lp->l_fp = lp; + lp->l_bp = lp; + } + return (bp); +} + +/* + * This routine blows away all of the text + * in a buffer. If the buffer is marked as changed + * then we ask if it is ok to blow it away; this is + * to save the user the grief of losing text. The + * window chain is nearly always wrong if this gets + * called; the caller must arrange for the updates + * that are required. Return TRUE if everything + * looks good. + */ +bclear(bp) +register BUFFER *bp; +{ + register LINE *lp; + register int s = FALSE; + + if(Pmaster){ + if ((bp->b_flag&BFTEMP) == 0 /* Not scratch buffer. */ + && (bp->b_flag&BFCHG) != 0){ /* Something changed */ + emlwrite("buffer lines not freed.", NULL); + return (s); + } + } + else{ + if ((bp->b_flag&BFTEMP) == 0 /* Not scratch buffer. */ + && (bp->b_flag&BFCHG) != 0 /* Something changed */ + && (s=mlyesno("Discard changes", -1)) != TRUE){ + return (s); + } + } + + bp->b_flag &= ~BFCHG; /* Not changed */ + while ((lp=lforw(bp->b_linep)) != bp->b_linep) + lfree(lp); + bp->b_dotp = bp->b_linep; /* Fix "." */ + bp->b_doto = 0; + bp->b_markp = NULL; /* Invalidate "mark" */ + bp->b_marko = 0; + return (TRUE); +} + + +/* + * packbuf - will pack up the main buffer in the buffer provided + * to be returned to the program that called pico. + * if need be, allocate memory for the new message. + * will also free the memory associated with the editor + * buffer, by calling zotedit. + */ +packbuf(buf, blen, lcrlf) +char **buf; +int *blen; +int lcrlf; /* EOLs are local or CRLF */ +{ + register int i = 0; + register LINE *lp; + register int retval = 0; + register char *bufp; + register char *eobuf; + + if(anycb() != FALSE){ + + lp = lforw(curbp->b_linep); + do{ /* how many chars? */ + i += llength(lp); + /* + * add extra for new lines to be inserted later + */ + i += 2; + lp = lforw(lp); + } + while(lp != curbp->b_linep); + + if(i > *blen){ /* new buffer ? */ + /* + * don't forget to add one for the null terminator!!! + */ + if((bufp = (char *)malloc((i+1)*sizeof(char))) == NULL){ + zotedit(); /* bag it! */ + return(COMP_FAILED); + } + free(*buf); + *buf = bufp; + *blen = i; + } + else{ + bufp = *buf; + } + + eobuf = bufp + *blen; + lp = lforw(curbp->b_linep); /* First line. */ + do { + for (i = 0; i < llength(lp); i++){ /* copy into buffer */ + if((bufp+1) < eobuf){ + *bufp++ = (lp->l_text[i].c & 0xFF); + } + else{ + /* + * the idea is to malloc enough space for the new + * buffer... + */ + *bufp = '\0'; + zotedit(); + return(BUF_CHANGED|COMP_FAILED); + } + } + if(lcrlf){ + *bufp++ = '\n'; /* EOLs use local convention */ + } + else{ + *bufp++ = 0x0D; /* EOLs use net standard */ + *bufp++ = 0x0A; + } + lp = lforw(lp); + } + while (lp != curbp->b_linep); + if(lcrlf) + *--bufp = '\0'; + else + *bufp = '\0'; + retval = BUF_CHANGED; + } + + zotedit(); + return(retval); +} + + +/* + * readbuf - reads in a buffer. + */ +void +readbuf(buf) +char **buf; +{ + register LINE *lp1; + register LINE *lp2; + register BUFFER *bp; + register WINDOW *wp; + register int i; + register int s; + char *sptr; /* pointer into buffer string */ + int nbytes; + char line[NLINE]; + CELL ac; + + bp = curbp; + bp->b_flag &= ~(BFTEMP|BFCHG); + sptr = *buf; + ac.a = 0; + + while((s=sgetline(&sptr,&nbytes,line,NLINE)) == FIOSUC || s == FIOLNG){ + + if ((lp1=lalloc(nbytes)) == NULL) { + s = FIOERR; /* Keep message on the */ + break; /* display. */ + } + lp2 = lback(curbp->b_linep); + lp2->l_fp = lp1; + lp1->l_fp = curbp->b_linep; + lp1->l_bp = lp2; + curbp->b_linep->l_bp = lp1; + for (i=0; iw_wndp) { + if (wp->w_bufp == curbp) { + wheadp->w_linep = lforw(curbp->b_linep); + wheadp->w_dotp = lback(curbp->b_linep); + wheadp->w_doto = 0; + wheadp->w_markp = NULL; + wheadp->w_marko = 0; + wheadp->w_flag |= WFHARD; + } + } + + strcpy(bp->b_bname, "main"); + strcpy(bp->b_fname, ""); + + bp->b_dotp = bp->b_linep; + bp->b_doto = 0; +} + + +/* + * sgetline - copy characters from ibuf to obuf, ending at the first + * newline. return with ibuf pointing to first char after + * newline. + */ +sgetline(ibuf, nchars, obuf, blen) +char **ibuf; +int *nchars; +char *obuf; +int blen; +{ + register char *len; + register char *cbuf = *ibuf; + register char *bufp = obuf; + register int retval = FIOSUC; +#define CR '\015' +#define LF '\012' + + *nchars = 0; + if(*cbuf == '\0'){ + retval = FIOEOF; + } + else{ + len = obuf + blen; + while (*cbuf != CR && *cbuf != LF && *cbuf != '\0'){ + if(bufp < len){ + *bufp++ = *cbuf++; + (*nchars)++; + } + else{ + *bufp = '\0'; + retval = FIOLNG; + break; + } + } + } + *bufp = '\0'; /* end retured line */ + *ibuf = (*cbuf == CR) ? ++cbuf : cbuf; + *ibuf = (*cbuf == LF) ? ++cbuf : cbuf; + return(retval); +} diff --git a/cc5.sol b/cc5.sol new file mode 100755 index 0000000..fcb4035 --- /dev/null +++ b/cc5.sol @@ -0,0 +1,74 @@ +#!/sbin/sh +# Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T +# All Rights Reserved + +# THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T +# The copyright notice above does not evidence any +# actual or intended publication of such source code. + +#ident "@(#)cc.sh 1.8 92/05/26 SMI" /* SVr4.0 1.4 */ + +# PROPRIETARY NOTICE (Combined) +# +#This source code is unpublished proprietary information +#constituting, or derived under license from AT&T's UNIX(r) System V. +#In addition, portions of such source code were derived from Berkeley +#4.3 BSD under license from the Regents of the University of +#California. +# +# +# +# Copyright Notice +# +#Notice of copyright on this source code product does not indicate +#publication. +# +# (c) 1986,1987,1988,1989 Sun Microsystems, Inc +# (c) 1983,1984,1985,1986,1987,1988,1989 AT&T. +# All rights reserved. + +# cc command for BSD compatibility package: +# +# BSD compatibility package header files (/usr/ucbinclude) +# are included before SVr4 default (/usr/include) files but +# after any directories specified on the command line via +# the -I option. Thus, the BSD header files are included +# next to last, and SVr4 header files are searched last. +# +# BSD compatibility package libraries (/usr/ucblib) are +# searched next to third to last. SVr4 default libraries +# (/usr/ccs/lib and /usr/lib) are searched next to last +# +# Because the BSD compatibility package C library does not +# contain all the C library routines of /usr/ccs/lib/libc.a, +# the BSD package C library is named /usr/ucblib/libucb.a +# and is passed explicitly to cc. This ensures that libucb.a +# will be searched first for routines and that +# /usr/ccs/lib/libc.a will be searched afterwards for routines +# not found in /usr/ucblib/libucb.a. Also because sockets is +# provided in libc under BSD, /usr/lib/libsocket and /usr/lib/nsl +# are also included as default libraries. +# +# NOTE: the -Y L, and -Y U, options of cc are not valid + +if [ "$CC" ] ; then + $CC "$@" + exit 0 +fi + +if [ -f /usr/ccs/bin/ucbcc ] +then + # get the directory where ucbcc points to and set the LD_LIBRARY_PATH + # to that directory so as to get the necessary libraries. + cclink=`/usr/bin/ls -ln /usr/ccs/bin/ucbcc | awk '{print $11}'` + ccdir=`/usr/bin/dirname $cclink` + + /usr/ccs/bin/ucbcc \ + -YP,:$ccdir:/usr/ccs/lib:/usr/lib "$@" \ + -lsocket -lnsl -lelf -laio + ret=$? + exit $ret +else + echo "/usr/ucb/cc: language optional software package not installed" + exit 1 +fi diff --git a/composer.c b/composer.c new file mode 100644 index 0000000..f700a53 --- /dev/null +++ b/composer.c @@ -0,0 +1,4296 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: composer.c 14001 2005-03-17 19:07:47Z hubert $"; +#endif +/* + * Program: Pine composer routines + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2005 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + * + * NOTES: + * + * - composer.c is the composer for the PINE mail system + * + * - tabled 01/19/90 + * + * Notes: These routines aren't incorporated yet, because the composer as + * a whole still needs development. These are ideas that should + * be implemented in later releases of PINE. See the notes in + * pico.c concerning what needs to be done .... + * + * - untabled 01/30/90 + * + * Notes: Installed header line editing, with wrapping and unwrapping, + * context sensitive help, and other mail header editing features. + * + * - finalish code cleanup 07/15/91 + * + * Notes: Killed/yanked header lines use emacs kill buffer. + * Arbitrarily large headers are handled gracefully. + * All formatting handled by FormatLines. + * + * - Work done to optimize display painting 06/26/92 + * Not as clean as it should be, needs more thought + * + */ +#include "headers.h" + + +int InitEntryText PROTO((char *, struct headerentry *)); +int HeaderOffset PROTO((int)); +int HeaderFocus PROTO((int, int)); +int LineEdit PROTO((int)); +int header_downline PROTO((int, int)); +int header_upline PROTO((int)); +int FormatLines PROTO((struct hdr_line *, char *, int, int, int)); +int FormatSyncAttach PROTO((void)); +char *strqchr PROTO((char *, int, int *, int)); +int ComposerHelp PROTO((int)); +void NewTop PROTO((int)); +void display_delimiter PROTO((int)); +void zotentry PROTO((struct hdr_line *)); +int InvertPrompt PROTO((int, int)); +int partial_entries PROTO((void)); +int physical_line PROTO((struct hdr_line *)); +int strend PROTO((char *, int)); +int KillHeaderLine PROTO((struct hdr_line *, int)); +int SaveHeaderLines PROTO((void)); +char *break_point PROTO((char *, int, int, int *)); +int hldelete PROTO((struct hdr_line *)); +int is_blank PROTO((int, int, int)); +int zotcomma PROTO((char *)); +struct hdr_line *first_hline PROTO((int *)); +struct hdr_line *first_sel_hline PROTO((int *)); +struct hdr_line *next_hline PROTO((int *, struct hdr_line *)); +struct hdr_line *next_sel_hline PROTO((int *, struct hdr_line *)); +struct hdr_line *prev_hline PROTO((int *, struct hdr_line *)); +struct hdr_line *prev_sel_hline PROTO((int *, struct hdr_line *)); +struct hdr_line *first_requested_hline PROTO((int *)); +void fix_mangle_and_err PROTO((int *, char **, char *)); + + +/* + * definition header field array, structures defined in pico.h + */ +struct headerentry *headents; + + +/* + * structure that keeps track of the range of header lines that are + * to be displayed and other fun stuff about the header + */ +struct on_display ods; /* global on_display struct */ + + +/* + * useful macros + */ +#define HALLOC() (struct hdr_line *)malloc(sizeof(struct hdr_line)) +#define LINELEN() (term.t_ncol - headents[ods.cur_e].prlen) +#define BOTTOM() (term.t_nrow - term.t_mrow) +#define FULL_SCR() (BOTTOM() - 3) +#define HALF_SCR() (FULL_SCR()/2) + +#ifdef MOUSE +/* + * Redefine HeaderEditor to install wrapper required for mouse even + * handling... + */ +#define HeaderEditor HeaderEditorWork +#endif /* MOUSE */ + +#if (defined(DOS) && !defined(_WINDOWS)) || defined(OS2) +#define HDR_DELIM "\xCD\xCD\xCD\xCD\xCD Message Text \xCD\xCD\xCD\xCD\xCD" +#else +#define HDR_DELIM "----- Message Text -----" +#endif + +/* + * useful declarations + */ +static short delim_ps = 0; /* previous state */ +static short invert_ps = 0; /* previous state */ + + +static KEYMENU menu_header[] = { + {"^G", "Get Help", KS_SCREENHELP}, {"^X", "Send", KS_SEND}, + {"^R", "Rich Hdr", KS_RICHHDR}, {"^Y", "PrvPg/Top", KS_PREVPAGE}, + {"^K", "Cut Line", KS_CURPOSITION}, {"^O", "Postpone", KS_POSTPONE}, + {"^C", "Cancel", KS_CANCEL}, {"^D", "Del Char", KS_NONE}, + {"^J", "Attach", KS_ATTACH}, {"^V", "NxtPg/End", KS_NEXTPAGE}, + {"^U", "UnDel Line", KS_NONE}, {NULL, NULL} +}; +#define SEND_KEY 1 +#define RICH_KEY 2 +#define CUT_KEY 4 +#define PONE_KEY 5 +#define DEL_KEY 7 +#define ATT_KEY 8 +#define UDEL_KEY 10 +#define TO_KEY 11 + + +/* + * function key mappings for header editor + */ +static int ckm[12][2] = { + { F1, (CTRL|'G')}, + { F2, (CTRL|'C')}, + { F3, (CTRL|'X')}, + { F4, (CTRL|'D')}, + { F5, (CTRL|'R')}, + { F6, (CTRL|'J')}, + { F7, 0 }, + { F8, 0 }, + { F9, (CTRL|'K')}, + { F10, (CTRL|'U')}, + { F11, (CTRL|'O')}, + { F12, (CTRL|'T')} +}; + + +/* + * InitMailHeader - initialize header array, and set beginning editor row + * range. The header entry structure should look just like + * what is written on the screen, the vector + * (entry, line, offset) will describe the current cursor + * position in the header. + * + * Returns: TRUE if special header handling was requested, + * FALSE under standard default behavior. + */ +InitMailHeader(mp) +PICO *mp; +{ + char *addrbuf; + struct headerentry *he; + int rv; + + if(!mp->headents){ + headents = NULL; + return(FALSE); + } + + /* + * initialize some of on_display structure, others below... + */ + ods.p_off = 0; + ods.p_line = COMPOSER_TOP_LINE; + ods.top_l = ods.cur_l = NULL; + + headents = mp->headents; + /*--- initialize the fields in the headerent structure ----*/ + for(he = headents; he->name != NULL; he++){ + he->hd_text = NULL; + he->display_it = he->display_it ? he->display_it : !he->rich_header; + if(he->is_attach) { + /*--- A lot of work to do since attachments are special ---*/ + he->maxlen = 0; + if(mp->attachments != NULL){ + char buf[NLINE]; + int attno = 0; + int l1, ofp, ofp1, ofp2; /* OverFlowProtection */ + size_t addrbuflen = 4 * NLINE; /* malloc()ed size of addrbuf */ + PATMT *ap = mp->attachments; + + ofp = NLINE - 35; + + addrbuf = (char *)malloc(addrbuflen); + addrbuf[0] = '\0'; + buf[0] = '\0'; + while(ap){ + if((l1 = strlen(ap->filename)) <= ofp){ + ofp1 = l1; + ofp2 = ofp - l1; + } + else{ + ofp1 = ofp; + ofp2 = 0; + } + + if(ap->filename){ + sprintf(buf, "%d. %.*s%s %s%s%s\"", + ++attno, + ofp1, + ap->filename, + (l1 > ofp) ? "...]" : "", + ap->size ? "(" : "", + ap->size ? ap->size : "", + ap->size ? ") " : ""); + + /* append description, escaping quotes */ + if(ap->description){ + char *dp = ap->description, *bufp = &buf[strlen(buf)]; + int escaped = 0; + + do + if(*dp == '\"' && !escaped){ + *bufp++ = '\\'; + ofp2--; + } + else if(escaped){ + *bufp++ = '\\'; + escaped = 0; + } + while(--ofp2 > 0 && (*bufp++ = *dp++)); + + *bufp = '\0'; + } + + sprintf(buf + strlen(buf), "\"%s", ap->next ? "," : ""); + + if(strlen(addrbuf) + strlen(buf) >= addrbuflen){ + addrbuflen += NLINE * 4; + if(!(addrbuf = (char *)realloc(addrbuf, addrbuflen))){ + emlwrite("\007Can't realloc addrbuf to %d bytes", + (void *) addrbuflen); + return(ABORT); + } + } + + strcat(addrbuf, buf); + } + ap = ap->next; + } + InitEntryText(addrbuf, he); + free((char *)addrbuf); + } else { + InitEntryText("", he); + } + he->realaddr = NULL; + } else { + if(!he->blank) + addrbuf = *(he->realaddr); + else + addrbuf = ""; + + InitEntryText(addrbuf, he); + } + } + + /* + * finish initialization and then figure out display layout. + * first, look for any field the caller requested we start in, + * and set the offset into that field. + */ + if(ods.cur_l = first_requested_hline(&ods.cur_e)){ + ods.top_e = 0; /* init top_e */ + ods.top_l = first_hline(&ods.top_e); + if(!HeaderFocus(ods.cur_e, Pmaster ? Pmaster->edit_offset : 0)) + HeaderFocus(ods.cur_e, 0); + + rv = TRUE; + } + else{ + ods.top_l = first_hline(&ods.cur_e); + ods.cur_l = first_sel_hline(&ods.cur_e); + ods.top_e = ods.cur_e; + rv = 0; + } + + UpdateHeader(0); + return(rv); +} + + + +/* + * InitEntryText - Add the given header text into the header entry + * line structure. + */ +InitEntryText(address, e) +char *address; +struct headerentry *e; +{ + struct hdr_line *curline; + register int longest; + + /* + * get first chunk of memory, and tie it to structure... + */ + if((curline = HALLOC()) == NULL){ + emlwrite("Unable to make room for full Header.", NULL); + return(FALSE); + } + longest = term.t_ncol - e->prlen - 1; + curline->text[0] = '\0'; + curline->next = NULL; + curline->prev = NULL; + e->hd_text = curline; /* tie it into the list */ + + if(FormatLines(curline, address, longest, e->break_on_comma, 0) == -1) + return(FALSE); + else + return(TRUE); +} + + + +/* + * ResizeHeader - Handle resizing display when SIGWINCH received. + * + * notes: + * works OK, but needs thorough testing + * + */ +ResizeHeader() +{ + register struct headerentry *i; + register int offset; + + if(!headents) + return(TRUE); + + offset = (ComposerEditing) ? HeaderOffset(ods.cur_e) : 0; + + for(i=headents; i->name; i++){ /* format each entry */ + if(FormatLines(i->hd_text, "", (term.t_ncol - i->prlen), + i->break_on_comma, 0) == -1){ + return(-1); + } + } + + if(ComposerEditing) /* restart at the top */ + HeaderFocus(ods.cur_e, offset); /* fix cur_l and p_off */ + else { + struct hdr_line *l; + int e; + + for(i = headents; i->name != NULL; i++); /* Find last line */ + i--; + e = i - headents; + l = headents[e].hd_text; + if(!headents[e].display_it || headents[e].blank) + l = prev_sel_hline(&e, l); /* last selectable line */ + + if(!l){ + e = i - headents; + l = headents[e].hd_text; + } + + HeaderFocus(e, -1); /* put focus on last line */ + } + + if(ComposerTopLine != COMPOSER_TOP_LINE) + UpdateHeader(0); + + PaintBody(0); + + if(ComposerEditing) + movecursor(ods.p_line, ods.p_off+headents[ods.cur_e].prlen); + + (*term.t_flush)(); + return(TRUE); +} + + + +/* + * HeaderOffset - return the character offset into the given header + */ +HeaderOffset(h) +int h; +{ + register struct hdr_line *l; + int i = 0; + + l = headents[h].hd_text; + + while(l != ods.cur_l){ + i += strlen(l->text); + l = l->next; + } + return(i+ods.p_off); +} + + + +/* + * HeaderFocus - put the dot at the given offset into the given header + */ +HeaderFocus(h, offset) +int h, offset; +{ + register struct hdr_line *l; + register int i; + int last = 0; + + if(offset == -1) /* focus on last line */ + last = 1; + + l = headents[h].hd_text; + while(1){ + if(last && l->next == NULL){ + break; + } + else{ + if((i=strlen(l->text)) >= offset) + break; + else + offset -= i; + } + if((l = l->next) == NULL) + return(FALSE); + } + + ods.cur_l = l; + ods.p_len = strlen(l->text); + ods.p_off = (last) ? 0 : offset; + + return(TRUE); +} + + + +/* + * HeaderEditor() - edit the mail header field by field, trapping + * important key sequences, hand the hard work off + * to LineEdit(). + * returns: + * -3 if we drop out bottom *and* want to process mouse event + * -1 if we drop out the bottom + * FALSE if editing is cancelled + * TRUE if editing is finished + */ +HeaderEditor(f, n) +int f, n; +{ + register int i; + register int ch; + register char *bufp; + struct headerentry *h; + int cur_e, mangled, retval = -1, + hdr_only = (gmode & MDHDRONLY) ? 1 : 0; + char *errmss, *err; +#ifdef MOUSE + MOUSEPRESS mp; +#endif + + if(!headents) + return(TRUE); /* nothing to edit! */ + + ComposerEditing = TRUE; + display_delimiter(0); /* provide feedback */ + +#ifdef _WINDOWS + mswin_setscrollrange (0, 0); +#endif /* _WINDOWS */ + + /* + * Decide where to begin editing. if f == TRUE begin editing + * at the bottom. this case results from the cursor backing + * into the editor from the bottom. otherwise, the user explicitly + * requested editing the header, and we begin at the top. + * + * further, if f == 1, we moved into the header by hitting the up arrow + * in the message text, else if f == 2, we moved into the header by + * moving past the left edge of the top line in the message. so, make + * the end of the last line of the last entry the current cursor position + * lastly, if f == 3, we moved into the header by hitting backpage() on + * the top line of the message, so scroll a page back. + */ + if(f){ + if(f == 2){ /* 2 leaves cursor at end */ + struct hdr_line *l = ods.cur_l; + int e = ods.cur_e; + + /*--- make sure on last field ---*/ + while(l = next_sel_hline(&e, l)) + if(headents[ods.cur_e].display_it){ + ods.cur_l = l; + ods.cur_e = e; + } + + ods.p_off = 1000; /* and make sure at EOL */ + } + else{ + /* + * note: assumes that ods.cur_e and ods.cur_l haven't changed + * since we left... + */ + + /* fix postition */ + if(curwp->w_doto < headents[ods.cur_e].prlen) + ods.p_off = 0; + else if(curwp->w_doto < ods.p_off + headents[ods.cur_e].prlen) + ods.p_off = curwp->w_doto - headents[ods.cur_e].prlen; + else + ods.p_off = 1000; + + /* and scroll back if needed */ + if(f == 3) + for(i = 0; header_upline(0) && i <= FULL_SCR(); i++) + ; + } + + ods.p_line = ComposerTopLine - 2; + } + /* else just trust what ods contains */ + + InvertPrompt(ods.cur_e, TRUE); /* highlight header field */ + sgarbk = 1; + + do{ + if(km_popped){ + km_popped--; + if(km_popped == 0) + sgarbk = 1; + } + + if(sgarbk){ + if(km_popped){ /* temporarily change to cause menu to paint */ + term.t_mrow = 2; + curwp->w_ntrows -= 2; + movecursor(term.t_nrow-2, 0); /* clear status line, too */ + peeol(); + } + else if(term.t_mrow == 0) + PaintBody(1); + + ShowPrompt(); /* display correct options */ + sgarbk = 0; + if(km_popped){ + term.t_mrow = 0; + curwp->w_ntrows += 2; + } + } + + ch = LineEdit(!(gmode&MDVIEW)); /* work on the current line */ + + if(km_popped) + switch(ch){ + case NODATA: + case (CTRL|'L'): + km_popped++; + break; + + default: + movecursor(term.t_nrow-2, 0); + peeol(); + movecursor(term.t_nrow-1, 0); + peeol(); + movecursor(term.t_nrow, 0); + peeol(); + break; + } + + switch (ch){ + case (CTRL|'R') : /* Toggle header display */ + if(Pmaster->pine_flags & MDHDRONLY){ + if(Pmaster->expander){ + packheader(); + call_expander(); + PaintBody(0); + break; + } + else + goto bleep; + } + + /*---- Are there any headers to expand above us? ---*/ + for(h = headents; h != &headents[ods.cur_e]; h++) + if(h->rich_header) + break; + if(h->rich_header) + InvertPrompt(ods.cur_e, FALSE); /* Yes, don't leave inverted */ + + mangled = 0; + err = NULL; + if(partial_entries()){ + /*--- Just turned off all rich headers --*/ + if(headents[ods.cur_e].rich_header){ + /*-- current header got turned off too --*/ +#ifdef ATTACHMENTS + if(headents[ods.cur_e].is_attach){ + /* verify the attachments */ + if((i = FormatSyncAttach()) != 0){ + FormatLines(headents[ods.cur_e].hd_text, "", + term.t_ncol - headents[ods.cur_e].prlen, + headents[ods.cur_e].break_on_comma, 0); + } + } +#endif + if(headents[ods.cur_e].builder) /* verify text */ + i = call_builder(&headents[ods.cur_e], &mangled, &err)>0; + /* Check below */ + for(cur_e =ods.cur_e; headents[cur_e].name!=NULL; cur_e++) + if(!headents[cur_e].rich_header) + break; + if(headents[cur_e].name == NULL) { + /* didn't find one, check above */ + for(cur_e =ods.cur_e; headents[cur_e].name!=NULL; + cur_e--) + if(!headents[cur_e].rich_header) + break; + + } + ods.p_off = 0; + ods.cur_e = cur_e; + ods.cur_l = headents[ods.cur_e].hd_text; + } + } + + ods.p_line = 0; /* force update */ + UpdateHeader(0); + PaintHeader(COMPOSER_TOP_LINE, FALSE); + PaintBody(1); + fix_mangle_and_err(&mangled, &err, headents[ods.cur_e].name); + break; + + case (CTRL|'C') : /* bag whole thing ?*/ + if(abort_composer(1, 0) == TRUE) + return(FALSE); + + break; + + case (CTRL|'X') : /* Done. Send it. */ + i = 0; +#ifdef ATTACHMENTS + if(headents[ods.cur_e].is_attach){ + /* verify the attachments, and pretty things up in case + * we come back to the composer due to error... + */ + if((i = FormatSyncAttach()) != 0){ + sleep(2); /* give time for error to absorb */ + FormatLines(headents[ods.cur_e].hd_text, "", + term.t_ncol - headents[ods.cur_e].prlen, + headents[ods.cur_e].break_on_comma, 0); + } + } + else +#endif + mangled = 0; + err = NULL; + if(headents[ods.cur_e].builder) /* verify text? */ + i = call_builder(&headents[ods.cur_e], &mangled, &err); + + if(i < 0){ /* don't leave without a valid addr */ + fix_mangle_and_err(&mangled, &err, headents[ods.cur_e].name); + break; + } + else if(i > 0){ + ods.cur_l = headents[ods.cur_e].hd_text; /* attach cur_l */ + ods.p_off = 0; + ods.p_line = 0; /* force realignment */ + fix_mangle_and_err(&mangled, &err, headents[ods.cur_e].name); + NewTop(0); + } + + fix_mangle_and_err(&mangled, &err, headents[ods.cur_e].name); + + if(wquit(1,0) == TRUE) + return(TRUE); + + if(i > 0){ + /* + * need to be careful here because pointers might be messed up. + * also, could do a better job of finding the right place to + * put the dot back (i.e., the addr/list that was expanded). + */ + UpdateHeader(0); + PaintHeader(COMPOSER_TOP_LINE, FALSE); + PaintBody(1); + } + break; + + case (CTRL|'Z') : /* Suspend compose */ + if(gmode&MDSSPD){ /* is it allowed? */ + bktoshell(); + PaintBody(0); + } + else{ + (*term.t_beep)(); + emlwrite("Unknown Command: ^Z", NULL); + } + break; + + case (CTRL|'O') : /* Suspend message */ + if(Pmaster->pine_flags & MDHDRONLY) + goto bleep; + + i = 0; + mangled = 0; + err = NULL; + if(headents[ods.cur_e].is_attach){ + if(FormatSyncAttach() < 0){ + if(mlyesno("Problem with attachments. Postpone anyway?", + FALSE) != TRUE){ + if(FormatLines(headents[ods.cur_e].hd_text, "", + term.t_ncol - headents[ods.cur_e].prlen, + headents[ods.cur_e].break_on_comma, 0) == -1) + emlwrite("\007Format lines failed!", NULL); + UpdateHeader(0); + PaintHeader(COMPOSER_TOP_LINE, FALSE); + PaintBody(1); + continue; + } + } + } + else if(headents[ods.cur_e].builder) + i = call_builder(&headents[ods.cur_e], &mangled, &err); + + ods.cur_l = headents[ods.cur_e].hd_text; + fix_mangle_and_err(&mangled, &err, headents[ods.cur_e].name); + + if(i < 0) /* don't leave without a valid addr */ + break; + + suspend_composer(1, 0); + return(TRUE); + +#ifdef ATTACHMENTS + case (CTRL|'J') : /* handle attachments */ + if(Pmaster->pine_flags & MDHDRONLY) + goto bleep; + + { char cmt[NLINE]; + LMLIST *lm = NULL, *lmp; + char buf[NLINE], *bfp; + int saved_km_popped; + size_t len; + + /* + * Attachment questions mess with km_popped and assume + * it is zero to start with. If we don't set it to zero + * on entry, the message about mime type will be erased + * by PaintBody. If we don't reset it when we come back, + * the bottom three lines may be messed up. + */ + saved_km_popped = km_popped; + km_popped = 0; + + if(AskAttach(cmt, &lm)){ + + for(lmp = lm; lmp; lmp = lmp->next){ + len = lmp->dir ? strlen(lmp->dir)+1 : 0; + len += lmp->fname ? strlen(lmp->fname) : 0; + + if(len+3 > sizeof(buf)){ + bfp = malloc(len+3); + if((bfp=malloc(len+3)) == NULL){ + emlwrite("\007Can't malloc space for filename", + NULL); + continue; + } + } + else + bfp = buf; + + if(lmp->dir && lmp->dir[0]) + sprintf(bfp, "%s%c%s", lmp->dir, C_FILESEP, + lmp->fname ? lmp->fname : ""); + else + sprintf(bfp, "%s", lmp->fname ? lmp->fname : ""); + + (void) QuoteAttach(bfp); + + (void) AppendAttachment(bfp, lm->size, cmt); + + if(bfp != buf) + free(bfp); + } + + zotlmlist(lm); + } + + km_popped = saved_km_popped; + sgarbk = 1; /* clean up prompt */ + } + break; +#endif + + case (CTRL|'I') : /* tab */ + ods.p_off = 0; /* fall through... */ + + case (CTRL|'N') : + case KEY_DOWN : + header_downline(!hdr_only, hdr_only); + break; + + case (CTRL|'P') : + case KEY_UP : + header_upline(1); + break; + + case (CTRL|'V') : /* down a page */ + case KEY_PGDN : + cur_e = ods.cur_e; + if(!next_sel_hline(&cur_e, ods.cur_l)){ + header_downline(!hdr_only, hdr_only); + if(!(gmode & MDHDRONLY)) + retval = -1; /* tell caller we fell out */ + } + else{ + int move_down, bot_pline; + struct hdr_line *new_cur_l, *line, *next_line, *prev_line; + + move_down = BOTTOM() - 2 - ods.p_line; + if(move_down < 0) + move_down = 0; + + /* + * Count down move_down lines to find the pointer to the line + * that we want to become the current line. + */ + new_cur_l = ods.cur_l; + cur_e = ods.cur_e; + for(i = 0; i < move_down; i++){ + next_line = next_hline(&cur_e, new_cur_l); + if(!next_line) + break; + + new_cur_l = next_line; + } + + if(headents[cur_e].blank){ + next_line = next_sel_hline(&cur_e, new_cur_l); + if(!next_line) + break; + + new_cur_l = next_line; + } + + /* + * Now call header_downline until we get down to the + * new current line, so that the builders all get called. + * New_cur_l will remain valid since we won't be calling + * a builder for it during this loop. + */ + while(ods.cur_l != new_cur_l && header_downline(0, 0)) + ; + + /* + * Count back up, if we're at the bottom, to find the new + * top line. + */ + cur_e = ods.cur_e; + if(next_hline(&cur_e, ods.cur_l) == NULL){ + /* + * Cursor stops at bottom of headers, which is where + * we are right now. Put as much of headers on + * screen as will fit. Count up to figure + * out which line is top_l and which p_line cursor is on. + */ + cur_e = ods.cur_e; + line = ods.cur_l; + /* leave delimiter on screen, too */ + bot_pline = BOTTOM() - 1 - ((gmode & MDHDRONLY) ? 0 : 1); + for(i = COMPOSER_TOP_LINE; i < bot_pline; i++){ + prev_line = prev_hline(&cur_e, line); + if(!prev_line) + break; + + line = prev_line; + } + + ods.top_l = line; + ods.top_e = cur_e; + ods.p_line = i; + + } + else{ + ods.top_l = ods.cur_l; + ods.top_e = ods.cur_e; + /* + * We don't want to scroll down further than the + * delimiter, so check to see if that is the case. + * If it is, we move the p_line down the screen + * until the bottom line is where we want it. + */ + bot_pline = BOTTOM() - 1 - ((gmode & MDHDRONLY) ? 0 : 1); + cur_e = ods.cur_e; + line = ods.cur_l; + for(i = bot_pline; i > COMPOSER_TOP_LINE; i--){ + next_line = next_hline(&cur_e, line); + if(!next_line) + break; + + line = next_line; + } + + /* + * i is the desired value of p_line. + * If it is greater than COMPOSER_TOP_LINE, then + * we need to adjust top_l. + */ + ods.p_line = i; + line = ods.top_l; + cur_e = ods.top_e; + for(; i > COMPOSER_TOP_LINE; i--){ + prev_line = prev_hline(&cur_e, line); + if(!prev_line) + break; + + line = prev_line; + } + + ods.top_l = line; + ods.top_e = cur_e; + + /* + * Special case. If p_line is within one of the bottom, + * move it to the bottom. + */ + if(ods.p_line == bot_pline - 1){ + header_downline(0, 0); + /* but put these back where we want them */ + ods.p_line = bot_pline; + ods.top_l = line; + ods.top_e = cur_e; + } + } + + UpdateHeader(0); + PaintHeader(COMPOSER_TOP_LINE, FALSE); + PaintBody(1); + } + + break; + + case (CTRL|'Y') : /* up a page */ + case KEY_PGUP : + for(i = 0; header_upline(0) && i <= FULL_SCR(); i++) + if(i < 0) + break; + + break; + +#ifdef MOUSE + case KEY_MOUSE: + mouse_get_last (NULL, &mp); + switch(mp.button){ + case M_BUTTON_LEFT : + if (!mp.doubleclick) { + if (mp.row < ods.p_line) { + for (i = ods.p_line - mp.row; + i > 0 && header_upline(0); + --i) + ; + } + else { + for (i = mp.row-ods.p_line; + i > 0 && header_downline(!hdr_only, 0); + --i) + ; + } + + if((ods.p_off = mp.col - headents[ods.cur_e].prlen) <= 0) + ods.p_off = 0; + + /* -3 is returned if we drop out bottom + * *and* want to process a mousepress. The Headereditor + * wrapper should make sense of this return code. + */ + if (ods.p_line >= ComposerTopLine) + retval = -3; + } + + break; + + case M_BUTTON_RIGHT : +#ifdef _WINDOWS + pico_popup(); +#endif + case M_BUTTON_MIDDLE : + default : /* NOOP */ + break; + } + + break; +#endif /* MOUSE */ + + case (CTRL|'T') : /* Call field selector */ + errmss = NULL; + if(headents[ods.cur_e].is_attach) { + /*--- selector for attachments ----*/ + char dir[NLINE], fn[NLINE], sz[NLINE]; + LMLIST *lm = NULL, *lmp; + + strcpy(dir, (gmode & MDCURDIR) + ? (browse_dir[0] ? browse_dir : ".") + : ((gmode & MDTREE) || opertree[0]) + ? opertree + : (browse_dir[0] ? browse_dir + : gethomedir(NULL))); + fn[0] = '\0'; + if(FileBrowse(dir, NLINE, fn, NLINE, sz, + FB_READ | FB_ATTACH | FB_LMODEPOS, &lm) == 1){ + char buf[NLINE], *bfp; + size_t len; + + for(lmp = lm; lmp; lmp = lmp->next){ + len = lmp->dir ? strlen(lmp->dir)+1 : 0; + len += lmp->fname ? strlen(lmp->fname) : 0; + len += 7; + len += strlen(lmp->size); + + if(len+3 > sizeof(buf)){ + bfp = malloc(len+3); + if((bfp=malloc(len+3)) == NULL){ + emlwrite("\007Can't malloc space for filename", + NULL); + continue; + } + } + else + bfp = buf; + + if(lmp->dir && lmp->dir[0]) + sprintf(bfp, "%s%c%s", lmp->dir, C_FILESEP, + lmp->fname ? lmp->fname : ""); + else + sprintf(bfp, "%s", lmp->fname ? lmp->fname : ""); + + (void) QuoteAttach(bfp); + + sprintf(bfp + strlen(bfp), " (%s) \"\"%s", lmp->size, + (!headents[ods.cur_e].hd_text->text[0]) ? "":","); + + if(FormatLines(headents[ods.cur_e].hd_text, bfp, + term.t_ncol - headents[ods.cur_e].prlen, + headents[ods.cur_e].break_on_comma,0)==-1){ + emlwrite("\007Format lines failed!", NULL); + } + + if(bfp != buf) + free(bfp); + + UpdateHeader(0); + } + + zotlmlist(lm); + } /* else, nothing of interest */ + } else if (headents[ods.cur_e].selector != NULL) { + VARS_TO_SAVE *saved_state; + + /*---- General selector for non-attachments -----*/ + + /* + * Since the selector may make a new call back to pico() + * we need to save and restore the pico state here. + */ + if((saved_state = save_pico_state()) != NULL){ + bufp = (*(headents[ods.cur_e].selector))(&errmss); + restore_pico_state(saved_state); + free_pico_state(saved_state); + ttresize(); /* fixup screen bufs */ + picosigs(); /* restore altered signals */ + } + else{ + char *s = "Not enough memory"; + + errmss = (char *)malloc((strlen(s)+1) * sizeof(char)); + strcpy(errmss, s); + bufp = NULL; + } + + if(bufp != NULL) { + mangled = 0; + err = NULL; + if(headents[ods.cur_e].break_on_comma) { + /*--- Must be an address ---*/ + if(ods.cur_l->text[0] != '\0'){ + struct hdr_line *h, *hh; + int q = 0; + + /*--- Check for continuation of previous line ---*/ + for(hh = h = headents[ods.cur_e].hd_text; + h && h->next != ods.cur_l; h = h->next){ + if(strqchr(h->text, ',', &q, -1)){ + hh = h->next; + } + } + if(hh && hh != ods.cur_l){ + /*--- Looks like a continuation ---*/ + ods.cur_l = hh; + ods.p_len = strlen(hh->text); + } + for(i = ++ods.p_len; i; i--) + ods.cur_l->text[i] = ods.cur_l->text[i-1]; + + ods.cur_l->text[0] = ','; + } + + if(FormatLines(ods.cur_l, bufp, + (term.t_ncol-headents[ods.cur_e].prlen), + headents[ods.cur_e].break_on_comma, 0) == -1){ + emlwrite("Problem adding address to header !", + NULL); + (*term.t_beep)(); + break; + } + + /* + * If the "selector" has a "builder" as well, pass + * what was just selected thru the builder... + */ + if(headents[ods.cur_e].builder){ + struct hdr_line *l; + int cur_row, top_too = 0; + + for(l = headents[ods.cur_e].hd_text, cur_row = 0; + l && l != ods.cur_l; + l = l->next, cur_row++) + ; + + top_too = headents[ods.cur_e].hd_text == ods.top_l; + + if(call_builder(&headents[ods.cur_e], &mangled, + &err) < 0){ + fix_mangle_and_err(&mangled, &err, + headents[ods.cur_e].name); + } + + for(ods.cur_l = headents[ods.cur_e].hd_text; + ods.cur_l->next && cur_row; + ods.cur_l = ods.cur_l->next, cur_row--) + ; + + if(top_too) + ods.top_l = headents[ods.cur_e].hd_text; + } + + UpdateHeader(0); + } else { + strcpy(headents[ods.cur_e].hd_text->text, bufp); + } + + free(bufp); + /* mark this entry dirty */ + headents[ods.cur_e].sticky = 1; + headents[ods.cur_e].dirty = 1; + fix_mangle_and_err(&mangled,&err,headents[ods.cur_e].name); + } + } else { + /*----- No selector -----*/ + (*term.t_beep)(); + continue; + } + + PaintBody(0); + if(errmss != NULL) { + (*term.t_beep)(); + emlwrite(errmss, NULL); + free(errmss); + errmss = NULL; + } + continue; + + case (CTRL|'G'): /* HELP */ + if(term.t_mrow == 0){ + if(km_popped == 0){ + km_popped = 2; + sgarbk = 1; /* bring up menu */ + break; + } + } + + if(!ComposerHelp(ods.cur_e)) + break; /* else, fall through... */ + + case (CTRL|'L'): /* redraw requested */ + PaintBody(0); + break; + + case (CTRL|'_'): /* file editor */ + if(headents[ods.cur_e].fileedit != NULL){ + struct headerentry *e; + struct hdr_line *line; + int sz = 0; + char *filename; + VARS_TO_SAVE *saved_state; + + /* + * Since the fileedit will make a new call back to pico() + * we need to save and restore the pico state here. + */ + if((saved_state = save_pico_state()) != NULL){ + e = &headents[ods.cur_e]; + + for(line = e->hd_text; line != NULL; line = line->next) + sz += strlen(line->text); + + filename = (char *)malloc(sz + 1); + filename[0] = '\0'; + + for(line = e->hd_text; line != NULL; line = line->next) + strcat(filename, line->text); + + errmss = (*(headents[ods.cur_e].fileedit))(filename); + + free(filename); + restore_pico_state(saved_state); + free_pico_state(saved_state); + ttresize(); /* fixup screen bufs */ + picosigs(); /* restore altered signals */ + } + else{ + char *s = "Not enough memory"; + + errmss = (char *)malloc((strlen(s)+1) * sizeof(char)); + strcpy(errmss, s); + } + + PaintBody(0); + + if(errmss != NULL) { + (*term.t_beep)(); + emlwrite(errmss, NULL); + free(errmss); + errmss = NULL; + } + + continue; + } + else + goto bleep; + + break; + + default : /* huh? */ +bleep: + if(ch&CTRL) + emlwrite("\007Unknown command: ^%c", (void *)(ch&0xff)); + else + case BADESC: + emlwrite("\007Unknown command", NULL); + + case NODATA: + break; + } + } + while (ods.p_line < ComposerTopLine); + + display_delimiter(1); + curwp->w_flag |= WFMODE; + movecursor(currow, curcol); + ComposerEditing = FALSE; + if (ComposerTopLine == BOTTOM()){ + UpdateHeader(0); + PaintHeader(COMPOSER_TOP_LINE, FALSE); + PaintBody(1); + } + + return(retval); +} + + +/* + * + */ +int +header_downline(beyond, gripe) + int beyond, gripe; +{ + struct hdr_line *new_l, *l; + int new_e, status, fullpaint, len, e, incr = 0; + + /* calculate the next line: physical *and* logical */ + status = 0; + new_e = ods.cur_e; + if((new_l = next_sel_hline(&new_e, ods.cur_l)) == NULL && !beyond){ + + if(gripe){ + char xx[81]; + + strcpy(xx, "Can't move down. Use ^X to "); + strcat(xx, (Pmaster && Pmaster->exit_label) + ? Pmaster->exit_label + : (gmode & MDHDRONLY) + ? "eXit/Save" + : (gmode & MDVIEW) + ? "eXit" + : "Send"); + strcat(xx, "."); + emlwrite(xx, NULL); + } + + return(0); + } + + /* + * Because of blank header lines the cursor may need to move down + * more than one line. Figure out how far. + */ + e = ods.cur_e; + l = ods.cur_l; + while(l != new_l){ + if((l = next_hline(&e, l)) != NULL) + incr++; + else + break; /* can't happen */ + } + + ods.p_line += incr; + fullpaint = ods.p_line >= BOTTOM(); /* force full redraw? */ + + /* expand what needs expanding */ + if(new_e != ods.cur_e || !new_l){ /* new (or last) field ! */ + if(new_l) + InvertPrompt(ods.cur_e, FALSE); /* turn off current entry */ + + if(headents[ods.cur_e].is_attach) { /* verify data ? */ + if(status = FormatSyncAttach()){ /* fixup if 1 or -1 */ + headents[ods.cur_e].rich_header = 0; + if(FormatLines(headents[ods.cur_e].hd_text, "", + term.t_ncol-headents[new_e].prlen, + headents[ods.cur_e].break_on_comma, 0) == -1) + emlwrite("\007Format lines failed!", NULL); + } + } else if(headents[ods.cur_e].builder) { /* expand addresses */ + int mangled = 0; + char *err = NULL; + + if((status = call_builder(&headents[ods.cur_e], &mangled, &err))>0){ + struct hdr_line *l; /* fixup ods.cur_l */ + ods.p_line = 0; /* force top line recalc */ + for(l = headents[ods.cur_e].hd_text; l; l = l->next) + ods.cur_l = l; + + if(new_l) /* if new_l, force validity */ + new_l = headents[new_e].hd_text; + + NewTop(0); /* get new top_l */ + } + else if(status < 0){ /* bad addr? no leave! */ + --ods.p_line; + fix_mangle_and_err(&mangled, &err, headents[ods.cur_e].name); + InvertPrompt(ods.cur_e, TRUE); + return(0); + } + + fix_mangle_and_err(&mangled, &err, headents[ods.cur_e].name); + } + + if(new_l){ /* if one below, turn it on */ + InvertPrompt(new_e, TRUE); + sgarbk = 1; /* paint keymenu too */ + } + } + + if(new_l){ /* fixup new pointers */ + ods.cur_l = (ods.cur_e != new_e) ? headents[new_e].hd_text : new_l; + ods.cur_e = new_e; + if(ods.p_off > (len = strlen(ods.cur_l->text))) + ods.p_off = len; + } + + if(!new_l || status || fullpaint){ /* handle big screen paint */ + UpdateHeader(0); + PaintHeader(COMPOSER_TOP_LINE, FALSE); + PaintBody(1); + + if(!new_l){ /* make sure we're done */ + ods.p_line = ComposerTopLine; + InvertPrompt(ods.cur_e, FALSE); /* turn off current entry */ + } + } + + return(new_l ? 1 : 0); +} + + +/* + * + */ +int +header_upline(gripe) + int gripe; +{ + struct hdr_line *new_l, *l; + int new_e, status, fullpaint, len, e, incr = 0; + + /* calculate the next line: physical *and* logical */ + status = 0; + new_e = ods.cur_e; + if(!(new_l = prev_sel_hline(&new_e, ods.cur_l))){ /* all the way up! */ + ods.p_line = COMPOSER_TOP_LINE; + if(gripe) + emlwrite("Can't move beyond top of %s", + (Pmaster->pine_flags & MDHDRONLY) ? "entry" : "header"); + + return(0); + } + + /* + * Because of blank header lines the cursor may need to move up + * more than one line. Figure out how far. + */ + e = ods.cur_e; + l = ods.cur_l; + while(l != new_l){ + if((l = prev_hline(&e, l)) != NULL) + incr++; + else + break; /* can't happen */ + } + + ods.p_line -= incr; + fullpaint = ods.p_line <= COMPOSER_TOP_LINE; + + if(new_e != ods.cur_e){ /* new field ! */ + InvertPrompt(ods.cur_e, FALSE); + if(headents[ods.cur_e].is_attach){ + if(status = FormatSyncAttach()){ /* non-zero ? reformat field */ + headents[ods.cur_e].rich_header = 0; + if(FormatLines(headents[ods.cur_e].hd_text, "", + term.t_ncol - headents[ods.cur_e].prlen, + headents[ods.cur_e].break_on_comma,0) == -1) + emlwrite("\007Format lines failed!", NULL); + } + } + else if(headents[ods.cur_e].builder){ + int mangled = 0; + char *err = NULL; + + if((status = call_builder(&headents[ods.cur_e], &mangled, + &err)) >= 0){ + /* repair new_l */ + for(new_l = headents[new_e].hd_text; + new_l->next; + new_l=new_l->next) + ; + + /* and cur_l (required in fix_and... */ + ods.cur_l = new_l; + } + else{ + ++ods.p_line; + fix_mangle_and_err(&mangled, &err, headents[ods.cur_e].name); + InvertPrompt(ods.cur_e, TRUE); + return(0); + } + + fix_mangle_and_err(&mangled, &err, headents[ods.cur_e].name); + } + + InvertPrompt(new_e, TRUE); + sgarbk = 1; + } + + ods.cur_e = new_e; /* update pointers */ + ods.cur_l = new_l; + if(ods.p_off > (len = strlen(ods.cur_l->text))) + ods.p_off = len; + + if(status > 0 || fullpaint){ + UpdateHeader(0); + PaintHeader(COMPOSER_TOP_LINE, FALSE); + PaintBody(1); + } + + return(1); +} + + +/* + * + */ +int +AppendAttachment(fn, sz, cmt) + char *fn, *sz, *cmt; +{ + int a_e, status, spaces; + struct hdr_line *lp; + + /*--- Find headerentry that is attachments (only first) --*/ + for(a_e = 0; headents[a_e].name != NULL; a_e++ ) + if(headents[a_e].is_attach){ + /* make sure field stays displayed */ + headents[a_e].rich_header = 0; + headents[a_e].display_it = 1; + break; + } + + /* append new attachment line */ + for(lp = headents[a_e].hd_text; lp->next; lp=lp->next) + ; + + /* build new attachment line */ + if(lp->text[0]){ /* adding a line? */ + strcat(lp->text, ","); /* append delimiter */ + if(lp->next = HALLOC()){ /* allocate new line */ + lp->next->prev = lp; + lp->next->next = NULL; + lp = lp->next; + } + else{ + emlwrite("\007Can't allocate line for new attachment!", NULL); + return(0); + } + } + + + spaces = (*fn == '\"') ? 0 : (strpbrk(fn, "(), \t") != NULL); + sprintf(lp->text, "%s%s%s (%s) \"%.*s\"", + spaces ? "\"" : "", fn, spaces ? "\"" : "", + sz ? sz : "", 80, cmt ? cmt : ""); + + /* validate the new attachment, and reformat if needed */ + if(status = SyncAttach()){ + if(status < 0) + emlwrite("\007Problem attaching: %s", fn); + + if(FormatLines(headents[a_e].hd_text, "", + term.t_ncol - headents[a_e].prlen, + headents[a_e].break_on_comma, 0) == -1){ + emlwrite("\007Format lines failed!", NULL); + return(0); + } + } + + UpdateHeader(0); + PaintHeader(COMPOSER_TOP_LINE, status != 0); + PaintBody(1); + return(status != 0); +} + + + + +/* + * LineEdit - the idea is to manage 7 bit ascii character only input. + * Always use insert mode and handle line wrapping + * + * returns: + * Any characters typed in that aren't printable + * (i.e. commands) + * + * notes: + * Assume we are guaranteed that there is sufficiently + * more buffer space in a line than screen width (just one + * less thing to worry about). If you want to change this, + * then pputc will have to be taught to check the line buffer + * length, and HALLOC() will probably have to become a func. + */ +LineEdit(allowedit) +int allowedit; +{ + register struct hdr_line *lp; /* temporary line pointer */ + register int i; + register int ch = 0; + register int status; /* various func's return val */ + register char *tbufp; /* temporary buffer pointers */ + int skipmove = 0; + char *strng; + int last_key; /* last keystroke */ + + strng = ods.cur_l->text; /* initialize offsets */ + ods.p_len = strlen(strng); + if(ods.p_off < 0) /* offset within range? */ + ods.p_off = 0; + else if(ods.p_off > ods.p_len) + ods.p_off = ods.p_len; + else if(ods.p_off > LINELEN()) /* shouldn't happen, but */ + ods.p_off = LINELEN(); /* you never know... */ + + while(1){ /* edit the line... */ + + if(skipmove) + skipmove = 0; + else + HeaderPaintCursor(); + + last_key = ch; + + (*term.t_flush)(); /* get everything out */ + +#ifdef MOUSE + mouse_in_content(KEY_MOUSE, -1, -1, 0, 0); + register_mfunc(mouse_in_content,2,0,term.t_nrow-(term.t_mrow+1), + term.t_ncol); +#endif +#ifdef _WINDOWS + mswin_setdndcallback (composer_file_drop); + mswin_mousetrackcallback(pico_cursor); +#endif + + ch = GetKey(); + + if (term.t_nrow < 6 && ch != NODATA){ + (*term.t_beep)(); + emlwrite("Please make the screen bigger.", NULL); + continue; + } + +#ifdef MOUSE + clear_mfunc(mouse_in_content); +#endif +#ifdef _WINDOWS + mswin_cleardndcallback (); + mswin_mousetrackcallback(NULL); +#endif + + switch(ch){ + case DEL : + if(gmode & P_DELRUBS) + ch = KEY_DEL; + + default : + (*Pmaster->keybinput)(); + if(!time_to_check()) + break; + + case NODATA : /* new mail ? */ + if((*Pmaster->newmail)(ch == NODATA ? 0 : 2, 1) >= 0){ + int rv; + + if(km_popped){ + term.t_mrow = 2; + curwp->w_ntrows -= 2; + } + + clearcursor(); + mlerase(); + rv = (*Pmaster->showmsg)(ch); + ttresize(); + picosigs(); + if(rv) /* Did showmsg corrupt the display? */ + PaintBody(0); /* Yes, repaint */ + + mpresf = 1; + if(km_popped){ + term.t_mrow = 0; + curwp->w_ntrows += 2; + } + } + + clearcursor(); + movecursor(ods.p_line, ods.p_off+headents[ods.cur_e].prlen); + if(ch == NODATA) /* GetKey timed out */ + continue; + + break; + } + + if(mpresf){ /* blast old messages */ + if(mpresf++ > NMMESSDELAY){ /* every few keystrokes */ + mlerase(); + movecursor(ods.p_line, ods.p_off+headents[ods.cur_e].prlen); + } + } + + if(VALID_KEY(ch)){ /* char input */ + /* + * if we are allowing editing, insert the new char + * end up leaving tbufp pointing to newly + * inserted character in string, and offset to the + * index of the character after the inserted ch ... + */ + if(allowedit){ + if(headents[ods.cur_e].only_file_chars + && !fallowc((unsigned char) ch)){ + /* no garbage in filenames */ + emlwrite("\007Can't have a '%c' in folder name", + (void *) ch); + continue; + } + else if(headents[ods.cur_e].is_attach + && intag(strng,ods.p_off)){ + emlwrite("\007Can't edit attachment number!", NULL); + continue; + } + + if(headents[ods.cur_e].single_space){ + if(ch == ' ' + && (strng[ods.p_off]==' ' || strng[ods.p_off-1]==' ')) + continue; + } + + /* + * go ahead and add the character... + */ + tbufp = &strng[++ods.p_len]; /* find the end */ + do{ + *tbufp = tbufp[-1]; + } while(--tbufp > &strng[ods.p_off]); /* shift right */ + strng[ods.p_off++] = ch; /* add char to str */ + + /* mark this entry dirty */ + headents[ods.cur_e].sticky = 1; + headents[ods.cur_e].dirty = 1; + + /* + * then find out where things fit... + */ + if(ods.p_len < LINELEN()){ + CELL c; + + c.c = ch; + c.a = 0; + if(pinsert(c)){ /* add char to str */ + skipmove++; /* must'a been optimal */ + continue; /* on to the next! */ + } + } + else{ + if((status = FormatLines(ods.cur_l, "", LINELEN(), + headents[ods.cur_e].break_on_comma,0)) == -1){ + (*term.t_beep)(); + continue; + } + else{ + /* + * during the format, the dot may have moved + * down to the next line... + */ + if(ods.p_off >= strlen(strng)){ + ods.p_line++; + ods.p_off -= strlen(strng); + ods.cur_l = ods.cur_l->next; + strng = ods.cur_l->text; + } + ods.p_len = strlen(strng); + } + UpdateHeader(0); + PaintHeader(COMPOSER_TOP_LINE, FALSE); + PaintBody(1); + continue; + } + } + else{ + rdonly(); + continue; + } + } + else { /* interpret ch as a command */ + switch (ch = normalize_cmd(ch, ckm, 2)) { + case (CTRL|'@') : /* word skip */ + while(strng[ods.p_off] + && isalnum((unsigned char)strng[ods.p_off])) + ods.p_off++; /* skip any text we're in */ + + while(strng[ods.p_off] + && !isalnum((unsigned char)strng[ods.p_off])) + ods.p_off++; /* skip any whitespace after it */ + + if(strng[ods.p_off] == '\0'){ + ods.p_off = 0; /* end of line, let caller handle it */ + return(KEY_DOWN); + } + + continue; + + case (CTRL|'K') : /* kill line cursor's on */ + if(!allowedit){ + rdonly(); + continue; + } + + lp = ods.cur_l; + if (!(gmode & MDDTKILL)) + ods.p_off = 0; + + if(KillHeaderLine(lp, (last_key == (CTRL|'K')))){ + if(optimize && + !(ods.cur_l->prev==NULL && ods.cur_l->next==NULL)) + scrollup(wheadp, ods.p_line, 1); + + if(ods.cur_l->next == NULL) + if(zotcomma(ods.cur_l->text)){ + if(ods.p_off > 0) + ods.p_off = strlen(ods.cur_l->text); + } + + i = (ods.p_line == COMPOSER_TOP_LINE); + UpdateHeader(0); + PaintHeader(COMPOSER_TOP_LINE, TRUE); + + if(km_popped){ + km_popped--; + movecursor(term.t_nrow, 0); + peeol(); + } + + PaintBody(1); + + } + strng = ods.cur_l->text; + ods.p_len = strlen(strng); + headents[ods.cur_e].sticky = 0; + headents[ods.cur_e].dirty = 1; + continue; + + case (CTRL|'U') : /* un-delete deleted lines */ + if(!allowedit){ + rdonly(); + continue; + } + + if(SaveHeaderLines()){ + UpdateHeader(0); + PaintHeader(COMPOSER_TOP_LINE, FALSE); + if(km_popped){ + km_popped--; + movecursor(term.t_nrow, 0); + peeol(); + } + + PaintBody(1); + strng = ods.cur_l->text; + ods.p_len = strlen(strng); + headents[ods.cur_e].sticky = 1; + headents[ods.cur_e].dirty = 1; + } + else + emlwrite("Problem Unkilling text", NULL); + continue; + + case (CTRL|'F') : + case KEY_RIGHT: /* move character right */ + if(ods.p_off < ods.p_len){ + pputc(pscr(ods.p_line, + (ods.p_off++)+headents[ods.cur_e].prlen)->c,0); + skipmove++; + continue; + } + else if(gmode & MDHDRONLY) + continue; + + ods.p_off = 0; + return(KEY_DOWN); + + case (CTRL|'B') : + case KEY_LEFT : /* move character left */ + if(ods.p_off > 0){ + ods.p_off--; + continue; + } + if(ods.p_line != COMPOSER_TOP_LINE) + ods.p_off = 1000; /* put cursor at end of line */ + return(KEY_UP); + + case (CTRL|'M') : /* goto next field */ + ods.p_off = 0; + return(KEY_DOWN); + + case KEY_HOME : + case (CTRL|'A') : /* goto beginning of line */ + ods.p_off = 0; + continue; + + case KEY_END : + case (CTRL|'E') : /* goto end of line */ + ods.p_off = ods.p_len; + continue; + + case (CTRL|'D') : /* blast this char */ + case KEY_DEL : + if(!allowedit){ + rdonly(); + continue; + } + else if(ods.p_off >= strlen(strng)) + continue; + + if(headents[ods.cur_e].is_attach && intag(strng, ods.p_off)){ + emlwrite("\007Can't edit attachment number!", NULL); + continue; + } + + pputc(strng[ods.p_off++], 0); /* drop through and rubout */ + + case DEL : /* blast previous char */ + case (CTRL|'H') : + if(!allowedit){ + rdonly(); + continue; + } + + if(headents[ods.cur_e].is_attach && intag(strng, ods.p_off-1)){ + emlwrite("\007Can't edit attachment number!", NULL); + continue; + } + + if(ods.p_off > 0){ /* just shift left one char */ + ods.p_len--; + headents[ods.cur_e].dirty = 1; + if(ods.p_len == 0) + headents[ods.cur_e].sticky = 0; + else + headents[ods.cur_e].sticky = 1; + + tbufp = &strng[--ods.p_off]; + while(*tbufp++ != '\0') + tbufp[-1] = *tbufp; + tbufp = &strng[ods.p_off]; + if(pdel()) /* physical screen delete */ + skipmove++; /* must'a been optimal */ + } + else{ /* may have work to do */ + if(ods.cur_l->prev == NULL){ + (*term.t_beep)(); /* no erase into next field */ + continue; + } + + ods.p_line--; + ods.cur_l = ods.cur_l->prev; + strng = ods.cur_l->text; + if((i=strlen(strng)) > 0){ + strng[i-1] = '\0'; /* erase the character */ + ods.p_off = i-1; + } + else{ + headents[ods.cur_e].sticky = 0; + ods.p_off = 0; + } + + tbufp = &strng[ods.p_off]; + } + + if((status = FormatLines(ods.cur_l, "", LINELEN(), + headents[ods.cur_e].break_on_comma,0))==-1){ + (*term.t_beep)(); + continue; + } + else{ + /* + * beware, the dot may have moved... + */ + while((ods.p_len=strlen(strng)) < ods.p_off){ + ods.p_line++; + ods.p_off -= strlen(strng); + ods.cur_l = ods.cur_l->next; + strng = ods.cur_l->text; + ods.p_len = strlen(strng); + tbufp = &strng[ods.p_off]; + status = TRUE; + } + UpdateHeader(0); + PaintHeader(COMPOSER_TOP_LINE, FALSE); + if(status == TRUE) + PaintBody(1); + } + + movecursor(ods.p_line, ods.p_off+headents[ods.cur_e].prlen); + + if(skipmove) + continue; + + break; + + default : + return(ch); + } + } + + while (*tbufp != '\0') /* synchronizing loop */ + pputc(*tbufp++, 0); + + if(ods.p_len < LINELEN()) + peeol(); + + } +} + + +void +HeaderPaintCursor() +{ + movecursor(ods.p_line, ods.p_off+headents[ods.cur_e].prlen); +} + + + +/* + * FormatLines - Place the given text at the front of the given line->text + * making sure to properly format the line, then check + * all lines below for proper format. + * + * notes: + * Not much optimization at all. Right now, it recursively + * fixes all remaining lines in the entry. Some speed might + * gained if this was built to iteratively scan the lines. + * + * returns: + * -1 on error + * FALSE if only this line is changed + * TRUE if text below the first line is changed + */ +FormatLines(h, instr, maxlen, break_on_comma, quoted) +struct hdr_line *h; /* where to begin formatting */ +char *instr; /* input string */ +int maxlen; /* max chars on a line */ +int break_on_comma; /* break lines on commas */ +int quoted; /* this line inside quotes */ +{ + int retval = FALSE; + register int i, l; + char *ostr; /* pointer to output string */ + register char *breakp; /* pointer to line break */ + register char *bp, *tp; /* temporary pointers */ + char *buf; /* string to add later */ + struct hdr_line *nlp, *lp; + + ostr = h->text; + nlp = h->next; + l = strlen(instr) + strlen(ostr); + if((buf = (char *)malloc(l+10)) == NULL) + return(-1); + + if(l >= maxlen){ /* break then fixup below */ + + if((l=strlen(instr)) < maxlen){ /* room for more */ + + if(break_on_comma && (bp = (char *)strqchr(instr, ',', "ed, -1))){ + bp += (bp[1] == ' ') ? 2 : 1; + for(tp = bp; *tp && *tp == ' '; tp++) + ; + + strcpy(buf, tp); + strcat(buf, ostr); + for(i = 0; &instr[i] < bp; i++) + ostr[i] = instr[i]; + ostr[i] = '\0'; + retval = TRUE; + } + else{ + breakp = break_point(ostr, maxlen-strlen(instr), + break_on_comma ? ',' : ' ', + break_on_comma ? "ed : NULL); + + if(breakp == ostr){ /* no good breakpoint */ + if(break_on_comma && *breakp == ','){ + breakp = ostr + 1; + retval = TRUE; + } + else if(strchr(instr,(break_on_comma && !quoted)?',':' ')){ + strcpy(buf, ostr); + strcpy(ostr, instr); + } + else{ /* instr's broken as we can get it */ + breakp = &ostr[maxlen-strlen(instr)-1]; + retval = TRUE; + } + } + else + retval = TRUE; + + if(retval){ + strcpy(buf, breakp); /* save broken line */ + if(breakp == ostr){ + strcpy(ostr, instr); /* simple if no break */ + } + else{ + *breakp = '\0'; /* more work to break it */ + i = strlen(instr); + /* + * shift ostr i chars + */ + for(bp=breakp; bp >= ostr && i; bp--) + *(bp+i) = *bp; + for(tp=ostr, bp=instr; *bp != '\0'; tp++, bp++) + *tp = *bp; /* then add instr */ + } + } + } + } + /* + * Short-circuit the recursion in this case. + * No time right now to figure out how to do it better. + */ + else if(l > 2*maxlen){ + char *instrp, *saveostr = NULL; + + retval = TRUE; + if(ostr && *ostr){ + saveostr = (char *)malloc(strlen(ostr) + 1); + strcpy(saveostr, ostr); + ostr[0] = '\0'; + } + + instrp = instr; + while(l > 2*maxlen){ + if(break_on_comma || maxlen == 1){ + breakp = (!(bp = strqchr(instrp, ',', "ed, maxlen)) + || bp - instrp >= maxlen || maxlen == 1) + ? &instrp[maxlen] + : bp + ((bp[1] == ' ') ? 2 : 1); + } + else{ + breakp = break_point(instrp, maxlen, ' ', NULL); + + if(breakp == instrp) /* no good break point */ + breakp = &instrp[maxlen - 1]; + } + + for(tp=ostr,bp=instrp; bp < breakp; tp++, bp++) + *tp = *bp; + + *tp = '\0'; + l -= (breakp - instrp); + instrp = breakp; + + if((lp = HALLOC()) == NULL){ + emlwrite("Can't allocate any more lines for header!", NULL); + free(buf); + return(-1); + } + + lp->next = h->next; + if(h->next) + h->next->prev = lp; + + h->next = lp; + lp->prev = h; + lp->text[0] = '\0'; + h = h->next; + ostr = h->text; + } + + /* + * Now l is still > maxlen. Do it the recursive way, + * like the else clause below. Surely we could fix up the + * flow control some here, but this works for now. + */ + + nlp = h->next; + instr = instrp; + if(saveostr){ + strcpy(ostr, saveostr); + free(saveostr); + } + + if(break_on_comma || maxlen == 1){ + breakp = (!(bp = strqchr(instrp, ',', "ed, maxlen)) + || bp - instrp >= maxlen || maxlen == 1) + ? &instrp[maxlen] + : bp + ((bp[1] == ' ') ? 2 : 1); + } + else{ + breakp = break_point(instrp, maxlen, ' ', NULL); + + if(breakp == instrp) /* no good break point */ + breakp = &instrp[maxlen - 1]; + } + + strcpy(buf, breakp); /* save broken line */ + strcat(buf, ostr); /* add line that was there */ + for(tp=ostr,bp=instr; bp < breakp; tp++, bp++) + *tp = *bp; + + *tp = '\0'; + } + else{ /* instr > maxlen ! */ + if(break_on_comma || maxlen == 1){ + breakp = (!(bp = strqchr(instr, ',', "ed, maxlen)) + || bp - instr >= maxlen || maxlen == 1) + ? &instr[maxlen] + : bp + ((bp[1] == ' ') ? 2 : 1); + } + else{ + breakp = break_point(instr, maxlen, ' ', NULL); + + if(breakp == instr) /* no good break point */ + breakp = &instr[maxlen - 1]; + } + + strcpy(buf, breakp); /* save broken line */ + strcat(buf, ostr); /* add line that was there */ + for(tp=ostr,bp=instr; bp < breakp; tp++, bp++) + *tp = *bp; + + *tp = '\0'; + } + + if(nlp == NULL){ /* no place to add below? */ + if((lp = HALLOC()) == NULL){ + emlwrite("Can't allocate any more lines for header!", NULL); + free(buf); + return(-1); + } + + if(optimize && (i = physical_line(h)) != -1) + scrolldown(wheadp, i - 1, 1); + + h->next = lp; /* fix up links */ + lp->prev = h; + lp->next = NULL; + lp->text[0] = '\0'; + nlp = lp; + retval = TRUE; + } + } + else{ /* combined length < max */ + if(*instr){ + strcpy(buf, instr); /* insert instr before ostr */ + strcat(buf, ostr); + strcpy(ostr, buf); + } + + *buf = '\0'; + breakp = NULL; + + if(break_on_comma && (breakp = strqchr(ostr, ',', "ed, -1))){ + breakp += (breakp[1] == ' ') ? 2 : 1; + strcpy(buf, breakp); + *breakp = '\0'; + + if(strlen(buf) && !nlp){ + if((lp = HALLOC()) == NULL){ + emlwrite("Can't allocate any more lines for header!",NULL); + free(buf); + return(-1); + } + + if(optimize && (i = physical_line(h)) != -1) + scrolldown(wheadp, i - 1, 1); + + h->next = lp; /* fix up links */ + lp->prev = h; + lp->next = NULL; + lp->text[0] = '\0'; + nlp = lp; + retval = TRUE; + } + } + + if(nlp){ + if(!strlen(buf) && !breakp){ + if(strlen(ostr) + strlen(nlp->text) >= maxlen){ + breakp = break_point(nlp->text, maxlen-strlen(ostr), + break_on_comma ? ',' : ' ', + break_on_comma ? "ed : NULL); + + if(breakp == nlp->text){ /* commas this line? */ + for(tp=ostr; *tp && *tp != ' '; tp++) + ; + + if(!*tp){ /* no commas, get next best */ + breakp += maxlen - strlen(ostr) - 1; + retval = TRUE; + } + else + retval = FALSE; + } + else + retval = TRUE; + + if(retval){ /* only if something to do */ + for(tp = &ostr[strlen(ostr)],bp=nlp->text; bptext, bp=breakp; *bp != '\0'; tp++, bp++) + *tp = *bp; /* shift next line to left */ + *tp = '\0'; + } + } + else{ + strcat(ostr, nlp->text); + + if(optimize && (i = physical_line(nlp)) != -1) + scrollup(wheadp, i, 1); + + hldelete(nlp); + + if(!(nlp = h->next)){ + free(buf); + return(TRUE); /* can't go further */ + } + else + retval = TRUE; /* more work to do? */ + } + } + } + else{ + free(buf); + return(FALSE); + } + + } + + i = FormatLines(nlp, buf, maxlen, break_on_comma, quoted); + free(buf); + switch(i){ + case -1: /* bubble up worst case */ + return(-1); + case FALSE: + if(retval == FALSE) + return(FALSE); + default: + return(TRUE); + } +} + +/* + * Format the lines before parsing attachments so we + * don't expand a bunch of attachments that we don't + * have the buffer space for. + */ +int +FormatSyncAttach () +{ + FormatLines(headents[ods.cur_e].hd_text, "", + term.t_ncol - headents[ods.cur_e].prlen, + headents[ods.cur_e].break_on_comma, 0); + return(SyncAttach()); +} + + +/* + * PaintHeader - do the work of displaying the header from the given + * physical screen line the end of the header. + * + * 17 July 91 - fixed reshow to deal with arbitrarily large headers. + */ +void +PaintHeader(line, clear) + int line; /* physical line on screen */ + int clear; /* clear before painting */ +{ + register struct hdr_line *lp; + register char *bufp; + register int curline; + register int curoffset; + char buf[NLINE]; + int e; + + if(clear) + pclear(COMPOSER_TOP_LINE, ComposerTopLine); + + curline = COMPOSER_TOP_LINE; + curoffset = 0; + + for(lp = ods.top_l, e = ods.top_e; ; curline++){ + if((curline == line) || ((lp = next_hline(&e, lp)) == NULL)) + break; + } + + while(headents[e].name != NULL){ /* begin to redraw */ + while(lp != NULL){ + buf[0] = '\0'; + if((!lp->prev || curline == COMPOSER_TOP_LINE) && !curoffset){ + if(InvertPrompt(e, (e == ods.cur_e && ComposerEditing)) == -1 + && !is_blank(curline, 0, headents[e].prlen)) + sprintf(buf, "%*s", headents[e].prlen, " "); + } + else if(!is_blank(curline, 0, headents[e].prlen)) + sprintf(buf, "%*s", headents[e].prlen, " "); + + if(*(bufp = buf) != '\0'){ /* need to paint? */ + movecursor(curline, 0); /* paint the line... */ + while(*bufp != '\0') + pputc(*bufp++, 0); + } + + bufp = &(lp->text[curoffset]); /* skip chars already there */ + curoffset += headents[e].prlen; + while(pscr(curline, curoffset) != NULL && + *bufp == pscr(curline, curoffset)->c && *bufp != '\0'){ + bufp++; + if(++curoffset >= term.t_ncol) + break; + } + + if(*bufp != '\0'){ /* need to move? */ + movecursor(curline, curoffset); + while(*bufp != '\0'){ /* display what's not there */ + pputc(*bufp++, 0); + curoffset++; + } + } + + if(curoffset < term.t_ncol + && !is_blank(curline, curoffset, term.t_ncol - curoffset)){ + movecursor(curline, curoffset); + peeol(); + } + curline++; + + curoffset = 0; + if(curline >= BOTTOM()) + break; + + lp = lp->next; + } + + if(curline >= BOTTOM()) + return; /* don't paint delimiter */ + + while(headents[++e].name != NULL) + if(headents[e].display_it){ + lp = headents[e].hd_text; + break; + } + } + + display_delimiter(ComposerEditing ? 0 : 1); +} + + + + +/* + * PaintBody() - generic call to handle repainting everything BUT the + * header + * + * notes: + * The header redrawing in a level 0 body paint gets done + * in update() + */ +void +PaintBody(level) +int level; +{ + curwp->w_flag |= WFHARD; /* make sure framing's right */ + if(level == 0) /* specify what to update */ + sgarbf = TRUE; + + update(); /* display message body */ + + if(level == 0 && ComposerEditing){ + mlerase(); /* clear the error line */ + ShowPrompt(); + } +} + + +/* + * display_for_send - paint the composer from the top line and return. + */ +void +display_for_send() +{ + int i = 0; + struct hdr_line *l; + + /* if first header line isn't displayed, there's work to do */ + if(headents && ((l = first_hline(&i)) != ods.top_l + || ComposerTopLine == COMPOSER_TOP_LINE + || !ods.p_line)){ + struct on_display orig_ods; + int orig_edit = ComposerEditing, + orig_ct_line = ComposerTopLine; + + /* + * fake that the cursor's in the first header line + * and force repaint... + */ + orig_ods = ods; + ods.cur_e = i; + ods.top_l = ods.cur_l = l; + ods.top_e = ods.cur_e; + ods.p_line = COMPOSER_TOP_LINE; + ComposerEditing = TRUE; /* to fool update() */ + setimark(FALSE, 1); /* remember where we were */ + gotobob(FALSE, 1); + + UpdateHeader(0); /* redraw whole enchilada */ + PaintHeader(COMPOSER_TOP_LINE, TRUE); + PaintBody(0); + + ods = orig_ods; /* restore original state */ + ComposerEditing = orig_edit; + ComposerTopLine = curwp->w_toprow = orig_ct_line; + curwp->w_ntrows = BOTTOM() - ComposerTopLine; + swapimark(FALSE, 1); + + /* in case we don't exit, set up restoring the screen */ + sgarbf = TRUE; /* force redraw */ + } +} + + +/* + * ArrangeHeader - set up display parm such that header is reasonably + * displayed + */ +void +ArrangeHeader() +{ + int e; + register struct hdr_line *l; + + ods.p_line = ods.p_off = 0; + e = ods.top_e = 0; + l = ods.top_l = headents[e].hd_text; + while(headents[e+1].name || (l && l->next)) + if(l = next_sel_hline(&e, l)){ + ods.cur_l = l; + ods.cur_e = e; + } + + UpdateHeader(1); +} + + +/* + * ComposerHelp() - display mail help in a context sensitive way + * based on the level passed ... + */ +ComposerHelp(level) +int level; +{ + char buf[80]; + VARS_TO_SAVE *saved_state; + + curwp->w_flag |= WFMODE; + sgarbf = TRUE; + + if(level < 0 || !headents[level].name){ + (*term.t_beep)(); + emlwrite("Sorry, I can't help you with that.", NULL); + sleep(2); + return(FALSE); + } + + sprintf(buf, "Help for %s %.40s Field", + (Pmaster->pine_flags & MDHDRONLY) ? "Address Book" + : "Composer", + headents[level].name); + saved_state = save_pico_state(); + (*Pmaster->helper)(headents[level].help, buf, 1); + if(saved_state){ + restore_pico_state(saved_state); + free_pico_state(saved_state); + } + + ttresize(); + picosigs(); /* restore altered handlers */ + return(TRUE); +} + + + +/* + * ToggleHeader() - set or unset pico values to the full screen size + * painting header if need be. + */ +ToggleHeader(show) +int show; +{ + /* + * check to see if we need to display the header... + */ + if(show){ + UpdateHeader(0); /* figure bounds */ + PaintHeader(COMPOSER_TOP_LINE, FALSE); /* draw it */ + } + else{ + /* + * set bounds for no header display + */ + curwp->w_toprow = ComposerTopLine = COMPOSER_TOP_LINE; + curwp->w_ntrows = BOTTOM() - ComposerTopLine; + } + return(TRUE); +} + + + +/* + * HeaderLen() - return the length in lines of the exposed portion of the + * header + */ +HeaderLen() +{ + register struct hdr_line *lp; + int e; + int i; + + i = 1; + lp = ods.top_l; + e = ods.top_e; + while(lp != NULL){ + lp = next_hline(&e, lp); + i++; + } + return(i); +} + + + +/* + * first_hline() - return a pointer to the first displayable header line + * + * returns: + * 1) pointer to first displayable line in header and header + * entry, via side effect, that the first line is a part of + * 2) NULL if no next line, leaving entry at LASTHDR + */ +struct hdr_line * +first_hline(entry) + int *entry; +{ + /* init *entry so we're sure to start from the top */ + for(*entry = 0; headents[*entry].name; (*entry)++) + if(headents[*entry].display_it) + return(headents[*entry].hd_text); + + *entry = 0; + return(NULL); /* this shouldn't happen */ +} + + +/* + * first_sel_hline() - return a pointer to the first selectable header line + * + * returns: + * 1) pointer to first selectable line in header and header + * entry, via side effect, that the first line is a part of + * 2) NULL if no next line, leaving entry at LASTHDR + */ +struct hdr_line * +first_sel_hline(entry) + int *entry; +{ + /* init *entry so we're sure to start from the top */ + for(*entry = 0; headents[*entry].name; (*entry)++) + if(headents[*entry].display_it && !headents[*entry].blank) + return(headents[*entry].hd_text); + + *entry = 0; + return(NULL); /* this shouldn't happen */ +} + + + +/* + * next_hline() - return a pointer to the next line structure + * + * returns: + * 1) pointer to next displayable line in header and header + * entry, via side effect, that the next line is a part of + * 2) NULL if no next line, leaving entry at LASTHDR + */ +struct hdr_line * +next_hline(entry, line) + int *entry; + struct hdr_line *line; +{ + if(line == NULL) + return(NULL); + + if(line->next == NULL){ + while(headents[++(*entry)].name != NULL){ + if(headents[*entry].display_it) + return(headents[*entry].hd_text); + } + --(*entry); + return(NULL); + } + else + return(line->next); +} + + +/* + * next_sel_hline() - return a pointer to the next selectable line structure + * + * returns: + * 1) pointer to next selectable line in header and header + * entry, via side effect, that the next line is a part of + * 2) NULL if no next line, leaving entry at LASTHDR + */ +struct hdr_line * +next_sel_hline(entry, line) + int *entry; + struct hdr_line *line; +{ + if(line == NULL) + return(NULL); + + if(line->next == NULL){ + while(headents[++(*entry)].name != NULL){ + if(headents[*entry].display_it && !headents[*entry].blank) + return(headents[*entry].hd_text); + } + --(*entry); + return(NULL); + } + else + return(line->next); +} + + + +/* + * prev_hline() - return a pointer to the next line structure back + * + * returns: + * 1) pointer to previous displayable line in header and + * the header entry that the next line is a part of + * via side effect + * 2) NULL if no next line, leaving entry unchanged from + * the value it had on entry. + */ +struct hdr_line * +prev_hline(entry, line) + int *entry; + struct hdr_line *line; +{ + if(line == NULL) + return(NULL); + + if(line->prev == NULL){ + int orig_entry; + + orig_entry = *entry; + while(--(*entry) >= 0){ + if(headents[*entry].display_it){ + line = headents[*entry].hd_text; + while(line->next != NULL) + line = line->next; + return(line); + } + } + + *entry = orig_entry; + return(NULL); + } + else + return(line->prev); +} + + +/* + * prev_sel_hline() - return a pointer to the previous selectable line + * + * returns: + * 1) pointer to previous selectable line in header and + * the header entry that the next line is a part of + * via side effect + * 2) NULL if no next line, leaving entry unchanged from + * the value it had on entry. + */ +struct hdr_line * +prev_sel_hline(entry, line) + int *entry; + struct hdr_line *line; +{ + if(line == NULL) + return(NULL); + + if(line->prev == NULL){ + int orig_entry; + + orig_entry = *entry; + while(--(*entry) >= 0){ + if(headents[*entry].display_it && !headents[*entry].blank){ + line = headents[*entry].hd_text; + while(line->next != NULL) + line = line->next; + return(line); + } + } + + *entry = orig_entry; + return(NULL); + } + else + return(line->prev); +} + + + +/* + * first_requested_hline() - return pointer to first line that pico's caller + * asked that we start on. + */ +struct hdr_line * +first_requested_hline(ent) + int *ent; +{ + int i, reqfield; + struct hdr_line *rv = NULL; + + for(reqfield = -1, i = 0; headents[i].name; i++) + if(headents[i].start_here){ + headents[i].start_here = 0; /* clear old setting */ + if(reqfield < 0){ /* if not already, set up */ + headents[i].display_it = 1; /* make sure it's shown */ + *ent = reqfield = i; + rv = headents[i].hd_text; + } + } + + return(rv); +} + + + +/* + * UpdateHeader() - determines the best range of lines to be displayed + * using the global ods value for the current line and the + * top line, also sets ComposerTopLine and pico limits + * + * showtop -- Attempt to show all header lines if they'll fit. + * + * notes: + * This is pretty ugly because it has to keep the current line + * on the screen in a reasonable location no matter what. + * There are also a couple of rules to follow: + * 1) follow paging conventions of pico (ie, half page + * scroll) + * 2) if more than one page, always display last half when + * pline is toward the end of the header + * + * returns: + * TRUE if anything changed (side effects: new p_line, top_l + * top_e, and pico parms) + * FALSE if nothing changed + * + */ +UpdateHeader(showtop) + int showtop; +{ + register struct hdr_line *lp; + int i, le; + int ret = FALSE; + int old_top = ComposerTopLine; + int old_p = ods.p_line; + + if(ods.p_line < COMPOSER_TOP_LINE || + ((ods.p_line == ComposerTopLine-2) ? 2: 0) + ods.p_line >= BOTTOM()){ + /* NewTop if cur header line is at bottom of screen or two from */ + /* the bottom of the screen if cur line is bottom header line */ + NewTop(showtop); /* get new top_l */ + ret = TRUE; + } + else{ /* make sure p_line's OK */ + i = COMPOSER_TOP_LINE; + lp = ods.top_l; + le = ods.top_e; + while(lp != ods.cur_l){ + /* + * this checks to make sure cur_l is below top_l and that + * cur_l is on the screen... + */ + if((lp = next_hline(&le, lp)) == NULL || ++i >= BOTTOM()){ + NewTop(0); + ret = TRUE; + break; + } + } + } + + ods.p_line = COMPOSER_TOP_LINE; /* find p_line... */ + lp = ods.top_l; + le = ods.top_e; + while(lp && lp != ods.cur_l){ + lp = next_hline(&le, lp); + ods.p_line++; + } + + if(!ret) + ret = !(ods.p_line == old_p); + + ComposerTopLine = ods.p_line; /* figure top composer line */ + while(lp && ComposerTopLine <= BOTTOM()){ + lp = next_hline(&le, lp); + ComposerTopLine += (lp) ? 1 : 2; /* allow for delim at end */ + } + + if(!ret) + ret = !(ComposerTopLine == old_top); + + if(wheadp->w_toprow != ComposerTopLine){ /* update pico params... */ + wheadp->w_toprow = ComposerTopLine; + wheadp->w_ntrows = ((i = BOTTOM() - ComposerTopLine) > 0) ? i : 0; + ret = TRUE; + } + return(ret); +} + + + +/* + * NewTop() - calculate a new top_l based on the cur_l + * + * showtop -- Attempt to show all the header lines if they'll fit + * + * returns: + * with ods.top_l and top_e pointing at a reasonable line + * entry + */ +void +NewTop(showtop) + int showtop; +{ + register struct hdr_line *lp; + register int i; + int e; + + lp = ods.cur_l; + e = ods.cur_e; + i = showtop ? FULL_SCR() : HALF_SCR(); + + while(lp != NULL && --i){ + ods.top_l = lp; + ods.top_e = e; + lp = prev_hline(&e, lp); + } +} + + + +/* + * display_delimiter() - just paint the header/message body delimiter with + * inverse value specified by state. + */ +void +display_delimiter(state) +int state; +{ + register char *bufp; + + if(ComposerTopLine - 1 >= BOTTOM()) /* silently forget it */ + return; + + bufp = (gmode & MDHDRONLY) ? "" : HDR_DELIM; + + if(state == delim_ps){ /* optimize ? */ + for(delim_ps = 0; bufp[delim_ps] && pscr(ComposerTopLine-1,delim_ps) != NULL && pscr(ComposerTopLine-1,delim_ps)->c == bufp[delim_ps];delim_ps++) + ; + + if(bufp[delim_ps] == '\0' && !(gmode & MDHDRONLY)){ + delim_ps = state; + return; /* already displayed! */ + } + } + + delim_ps = state; + + movecursor(ComposerTopLine - 1, 0); + if(state) + (*term.t_rev)(1); + + while(*bufp != '\0') + pputc(*bufp++, state ? 1 : 0); + + if(state) + (*term.t_rev)(0); + + peeol(); +} + + + +/* + * InvertPrompt() - invert the prompt associated with header entry to state + * state (true if invert, false otherwise). + * returns: + * non-zero if nothing done + * 0 if prompt inverted successfully + * + * notes: + * come to think of it, this func and the one above could + * easily be combined + */ +InvertPrompt(entry, state) +int entry, state; +{ + register char *bufp; + register int i; + + bufp = headents[entry].prompt; /* fresh prompt paint */ + if((i = entry_line(entry, FALSE)) == -1) + return(-1); /* silently forget it */ + + if(entry < 16 && (invert_ps&(1<c == bufp[j]; j++) + ; + + if(bufp[j] == '\0'){ + if(state) + invert_ps |= 1< 16, cannot be stored in invert_ps */ + if(state) + invert_ps |= 1<rich_header && h->name != NULL; h++) + ; + + is_on = h->display_it; + for(h = headents; h->name != NULL; h++) + if(h->rich_header) + h->display_it = ! is_on; + + return(is_on); +} + + + +/* + * entry_line() - return the physical line on the screen associated + * with the given header entry field. Note: the field + * may span lines, so if the last char is set, return + * the appropriate value. + * + * returns: + * 1) physical line number of entry + * 2) -1 if entry currently not on display + */ +entry_line(entry, lastchar) +int entry, lastchar; +{ + register int p_line = COMPOSER_TOP_LINE; + int i; + register struct hdr_line *line; + + for(line = ods.top_l, i = ods.top_e; + headents && headents[i].name && i <= entry; + p_line++){ + if(p_line >= BOTTOM()) + break; + if(i == entry){ + if(lastchar){ + if(line->next == NULL) + return(p_line); + } + else if(line->prev == NULL) + return(p_line); + else + return(-1); + } + line = next_hline(&i, line); + } + return(-1); +} + + + +/* + * physical_line() - return the physical line on the screen associated + * with the given header line pointer. + * + * returns: + * 1) physical line number of entry + * 2) -1 if entry currently not on display + */ +physical_line(l) +struct hdr_line *l; +{ + register int p_line = COMPOSER_TOP_LINE; + register struct hdr_line *lp; + int i; + + for(lp=ods.top_l, i=ods.top_e; headents[i].name && lp != NULL; p_line++){ + if(p_line >= BOTTOM()) + break; + + if(lp == l) + return(p_line); + + lp = next_hline(&i, lp); + } + return(-1); +} + + + +/* + * call_builder() - resolve any nicknames in the address book associated + * with the given entry... + * + * NOTES: + * + * BEWARE: this function can cause cur_l and top_l to get lost so BE + * CAREFUL before and after you call this function!!! + * + * There could to be something here to resolve cur_l and top_l + * reasonably into the new linked list for this entry. + * + * The reason this would mostly work without it is resolve_niks gets + * called for the most part in between fields. Since we're moving + * to the beginning or end (i.e. the next/prev pointer in the old + * freed cur_l is NULL) of the next entry, we get a new cur_l + * pointing at a good line. Then since top_l is based on cur_l in + * NewTop() we have pretty much lucked out. + * + * Where we could get burned is in a canceled exit (ctrl|x). Here + * nicknames get resolved into addresses, which invalidates cur_l + * and top_l. Since we don't actually leave, we could begin editing + * again with bad pointers. This would usually results in a nice + * core dump. + * + * NOTE: The mangled argument is a little strange. It's used on both + * input and output. On input, if it is not set, then that tells the + * builder not to do anything that might take a long time, like a + * white pages lookup. On return, it tells the caller that the screen + * and signals may have been mangled so signals should be reset, window + * resized, and screen redrawn. + * + * RETURNS: + * > 0 if any names where resolved, otherwise + * 0 if not, or + * < 0 on error + * -1: move to next line + * -2: don't move off this line + */ +call_builder(entry, mangled, err) +struct headerentry *entry; +int *mangled; +char **err; +{ + register int retval = 0; + register int i; + register struct hdr_line *line; + int quoted = 0; + char *sbuf; + char *s = NULL; + struct headerentry *e; + BUILDER_ARG *nextarg, *arg = NULL, *headarg = NULL; + VARS_TO_SAVE *saved_state; + + if(!entry->builder) + return(0); + + line = entry->hd_text; + i = 0; + while(line != NULL){ + i += term.t_ncol; + line = line->next; + } + + if((sbuf=(char *)malloc((unsigned) i)) == NULL){ + emlwrite("Can't malloc space to expand address", NULL); + return(-1); + } + + *sbuf = '\0'; + /* + * cat the whole entry into one string... + */ + line = entry->hd_text; + while(line != NULL){ + i = strlen(line->text); + /* + * To keep pine address builder happy, addresses should be separated + * by ", ". Add this space if needed, otherwise... + * (This is some ancient requirement that is no longer needed.) + * + * If this line is NOT a continuation of the previous line, add + * white space for pine's address builder if its not already there... + * (This is some ancient requirement that is no longer needed.) + * + * Also if it's not a continuation (i.e., there's already and addr on + * the line), and there's another line below, treat the new line as + * an implied comma. + * (This should only be done for address-type lines, not for regular + * text lines like subjects. Key off of the break_on_comma bit which + * should only be set on those that won't mind a comma being added.) + */ + if(entry->break_on_comma){ + if(i && line->text[i-1] == ',') + strcat(line->text, " "); /* help address builder */ + else if(line->next != NULL && !strend(line->text, ',')){ + if(strqchr(line->text, ',', "ed, -1)) + strcat(line->text, ", "); /* implied comma */ + } + else if(line->prev != NULL && line->next != NULL){ + if(strchr(line->prev->text, ' ') != NULL + && line->text[i-1] != ' ') + strcat(line->text, " "); + } + } + + strcat(sbuf, line->text); + line = line->next; + } + + if(entry->affected_entry){ + /* check if any non-sticky affected entries */ + for(e = entry->affected_entry; e; e = e->next_affected) + if(!e->sticky) + break; + + /* there is at least one non-sticky so make a list to pass */ + if(e){ + for(e = entry->affected_entry; e; e = e->next_affected){ + if(!arg){ + headarg = arg = (BUILDER_ARG *)malloc(sizeof(BUILDER_ARG)); + if(!arg){ + emlwrite("Can't malloc space for fcc", NULL); + return(-1); + } + else{ + arg->next = NULL; + arg->tptr = NULL; + arg->aff = &(e->bldr_private); + arg->me = &(entry->bldr_private); + } + } + else{ + nextarg = (BUILDER_ARG *)malloc(sizeof(BUILDER_ARG)); + if(!nextarg){ + emlwrite("Can't malloc space for fcc", NULL); + return(-1); + } + else{ + nextarg->next = NULL; + nextarg->tptr = NULL; + nextarg->aff = &(e->bldr_private); + nextarg->me = &(entry->bldr_private); + arg->next = nextarg; + arg = arg->next; + } + } + + if(!e->sticky){ + line = e->hd_text; + if(!(arg->tptr=(char *)malloc(strlen(line->text) + 1))){ + emlwrite("Can't malloc space for fcc", NULL); + return(-1); + } + else + strcpy(arg->tptr, line->text); + } + } + } + } + + /* + * Even if there are no affected entries, we still need the arg + * to pass the "me" pointer. + */ + if(!headarg){ + headarg = (BUILDER_ARG *)malloc(sizeof(BUILDER_ARG)); + if(!headarg){ + emlwrite("Can't malloc space", NULL); + return(-1); + } + else{ + headarg->next = NULL; + headarg->tptr = NULL; + headarg->aff = NULL; + headarg->me = &(entry->bldr_private); + } + } + + /* + * The builder may make a new call back to pico() so we save and + * restore the pico state. + */ + saved_state = save_pico_state(); + retval = (*entry->builder)(sbuf, &s, err, headarg, mangled); + if(saved_state){ + restore_pico_state(saved_state); + free_pico_state(saved_state); + } + + if(mangled && *mangled & BUILDER_MESSAGE_DISPLAYED){ + *mangled &= ~ BUILDER_MESSAGE_DISPLAYED; + if(mpresf == FALSE) + mpresf = TRUE; + } + + if(retval >= 0){ + if(strcmp(sbuf, s)){ + line = entry->hd_text; + InitEntryText(s, entry); /* arrange new one */ + zotentry(line); /* blast old list o'entries */ + entry->dirty = 1; /* mark it dirty */ + retval = 1; + } + + for(e = entry->affected_entry, arg = headarg; + e; + e = e->next_affected, arg = arg ? arg->next : NULL){ + if(!e->sticky){ + line = e->hd_text; + if(strcmp(line->text, arg ? arg->tptr : "")){ /* it changed */ + /* make sure they see it if changed */ + e->display_it = 1; + InitEntryText(arg ? arg->tptr : "", e); + if(line == ods.top_l) + ods.top_l = e->hd_text; + + zotentry(line); /* blast old list o'entries */ + e->dirty = 1; /* mark it dirty */ + retval = 1; + } + } + } + } + + if(s) + free(s); + + for(arg = headarg; arg; arg = nextarg){ + /* Don't free xtra or me, they just point to headerentry data */ + nextarg = arg->next; + if(arg->tptr) + free(arg->tptr); + + free(arg); + } + + free(sbuf); + return(retval); +} + + +void +call_expander() +{ + char **s = NULL; + VARS_TO_SAVE *saved_state; + int expret; + + if(!Pmaster->expander) + return; + + /* + * Since expander may make a call back to pico() we need to + * save and restore pico state. + */ + if((saved_state = save_pico_state()) != NULL){ + + expret = (*Pmaster->expander)(headents, &s); + + restore_pico_state(saved_state); + free_pico_state(saved_state); + ttresize(); + picosigs(); + + if(expret > 0 && s){ + char *tbuf; + int i, biggest = 100; + struct headerentry *e; + + /* + * Use tbuf to cat together multiple line entries before comparing. + */ + tbuf = (char *)malloc(biggest + 1); + for(e = headents, i=0; e->name != NULL; e++,i++){ + int sz = 0; + struct hdr_line *line; + + while(e->name && e->blank) + e++; + + if(e->name == NULL) + continue; + + for(line = e->hd_text; line != NULL; line = line->next) + sz += strlen(line->text); + + if(sz > biggest){ + biggest = sz; + free(tbuf); + tbuf = (char *)malloc(biggest + 1); + } + + tbuf[0] = '\0'; + for(line = e->hd_text; line != NULL; line = line->next) + strcat(tbuf, line->text); + + if(strcmp(tbuf, s[i])){ /* it changed */ + struct hdr_line *zline; + + line = zline = e->hd_text; + InitEntryText(s[i], e); + /* + * If any of the lines for this entry are current or + * top, fix that. + */ + for(; line != NULL; line = line->next){ + if(line == ods.top_l) + ods.top_l = e->hd_text; + + if(line == ods.cur_l) + ods.cur_l = e->hd_text; + } + + zotentry(zline); /* blast old list o'entries */ + } + } + + free(tbuf); + } + + if(s){ + char **p; + + for(p = s; *p; p++) + free(*p); + + free(s); + } + } + + return; +} + + +/* + * strend - neglecting white space, returns TRUE if c is at the + * end of the given line. otherwise FALSE. + */ +strend(s, ch) +char *s; +int ch; +{ + register char *b; + register char c; + + c = (char)ch; + + if(s == NULL) + return(FALSE); + + if(*s == '\0') + return(FALSE); + + b = &s[strlen(s)]; + while(isspace((unsigned char)(*--b))){ + if(b == s) + return(FALSE); + } + + return(*b == c); +} + + +/* + * strqchr - returns pointer to first non-quote-enclosed occurance of ch in + * the given string. otherwise NULL. + * s -- the string + * ch -- the character we're looking for + * q -- q tells us if we start out inside quotes on entry and is set + * correctly on exit. + * m -- max characters we'll check for ch (set to -1 for no check) + */ +char * +strqchr(s, ch, q, m) + char *s; + int ch; + int *q; + int m; +{ + int quoted = (q) ? *q : 0; + + for(; s && *s && m != 0; s++, m--){ + if(*s == '"'){ + quoted = !quoted; + if(q) + *q = quoted; + } + + if(!quoted && *s == ch) + return(s); + } + + return(NULL); +} + + +/* + * KillHeaderLine() - kill a line in the header + * + * notes: + * This is pretty simple. Just using the emacs kill buffer + * and its accompanying functions to cut the text from lines. + * + * returns: + * TRUE if hldelete worked + * FALSE otherwise + */ +KillHeaderLine(l, append) +struct hdr_line *l; +int append; +{ + register char *c; + int i = ods.p_off; + int nl = TRUE; + + if(!append) + kdelete(); + + c = l->text; + if (gmode & MDDTKILL){ + if (c[i] == '\0') /* don't insert a new line after this line*/ + nl = FALSE; + /*put to be deleted part into kill buffer */ + for (i=ods.p_off; c[i] != '\0'; i++) + kinsert(c[i]); + }else{ + while(*c != '\0') /* splat out the line */ + kinsert(*c++); + } + + if (nl) + kinsert('\n'); /* helpful to yank in body */ + +#ifdef _WINDOWS + mswin_killbuftoclip (kremove); +#endif + + if (gmode & MDDTKILL){ + if (l->text[0]=='\0'){ + + if(l->next && l->prev) + ods.cur_l = next_hline(&ods.cur_e, l); + else if(l->prev) + ods.cur_l = prev_hline(&ods.cur_e, l); + + if(l == ods.top_l) + ods.top_l = ods.cur_l; + + return(hldelete(l)); + } + else { + l->text[ods.p_off]='\0'; /* delete part of the line from the cursor */ + return(TRUE); + } + }else{ + if(l->next && l->prev) + ods.cur_l = next_hline(&ods.cur_e, l); + else if(l->prev) + ods.cur_l = prev_hline(&ods.cur_e, l); + + if(l == ods.top_l) + ods.top_l = ods.cur_l; + + return(hldelete(l)); /* blast it */ + } +} + + + +/* + * SaveHeaderLines() - insert the saved lines in the list before the + * current line in the header + * + * notes: + * Once again, just using emacs' kill buffer and its + * functions. + * + * returns: + * TRUE if something good happend + * FALSE otherwise + */ +SaveHeaderLines() +{ + char *buf; /* malloc'd copy of buffer */ + register char *bp; /* pointer to above buffer */ + register unsigned i; /* index */ + char *work_buf, *work_buf_begin; + char empty[1]; + int len, buf_len, work_buf_len, tentative_p_off = 0; + struct hdr_line *travel, *tentative_cur_l = NULL; + + if(ksize()){ + if((bp = buf = (char *)malloc(ksize()+5)) == NULL){ + emlwrite("Can't malloc space for saved text", NULL); + return(FALSE); + } + } + else + return(FALSE); + + for(i=0; i < ksize(); i++) + if(kremove(i) != '\n') /* filter out newlines */ + *bp++ = kremove(i); + *bp = '\0'; + + while(--bp >= buf) /* kill trailing white space */ + if(*bp != ' '){ + if(ods.cur_l->text[0] != '\0'){ + if(*bp == '>'){ /* inserting an address */ + *++bp = ','; /* so add separator */ + *++bp = '\0'; + } + } + else{ /* nothing in field yet */ + if(*bp == ','){ /* so blast any extra */ + *bp = '\0'; /* separators */ + } + } + break; + } + + /* insert new text at the dot position */ + buf_len = strlen(buf); + tentative_p_off = ods.p_off + buf_len; + work_buf_len = strlen(ods.cur_l->text) + buf_len; + work_buf = (char *) malloc((work_buf_len + 1) * sizeof(char)); + if (work_buf == NULL) { + emlwrite("Can't malloc space for saved text", NULL); + return(FALSE); + } + + sprintf(work_buf_begin = work_buf, "%.*s%s%s", ods.p_off, + ods.cur_l->text, buf, &ods.cur_l->text[ods.p_off]); + empty[0]='\0'; + ods.p_off = 0; + + /* insert text in 256-byte chuks */ + while(work_buf_len + ods.p_off > 256) { + strncpy(&ods.cur_l->text[ods.p_off], work_buf, 256-ods.p_off); + work_buf += (256 - ods.p_off); + work_buf_len -= (256 - ods.p_off); + + if(FormatLines(ods.cur_l, empty, LINELEN(), + headents[ods.cur_e].break_on_comma, 0) == -1) { + i = FALSE; + break; + } else { + i = TRUE; + len = 0; + travel = ods.cur_l; + while (len < 256){ + len += strlen(travel->text); + if (len >= 256) + break; + + /* + * This comes after the break above because it will + * be accounted for in the while loop below. + */ + if(!tentative_cur_l){ + if(tentative_p_off <= strlen(travel->text)) + tentative_cur_l = travel; + else + tentative_p_off -= strlen(travel->text); + } + + travel = travel->next; + } + + ods.cur_l = travel; + ods.p_off = strlen(travel->text) - len + 256; + } + } + + /* insert the remainder of text */ + if (i != FALSE && work_buf_len > 0) { + strcpy(&ods.cur_l->text[ods.p_off], work_buf); + work_buf = work_buf_begin; + free(work_buf); + + if(FormatLines(ods.cur_l, empty, LINELEN(), + headents[ods.cur_e].break_on_comma, 0) == -1) { + i = FALSE; + } else { + len = 0; + travel = ods.cur_l; + while (len < work_buf_len + ods.p_off){ + if(!tentative_cur_l){ + if(tentative_p_off <= strlen(travel->text)) + tentative_cur_l = travel; + else + tentative_p_off -= strlen(travel->text); + } + + len += strlen(travel->text); + if (len >= work_buf_len + ods.p_off) + break; + + travel = travel->next; + } + + ods.cur_l = travel; + ods.p_off = strlen(travel->text) - len + work_buf_len + ods.p_off; + if(tentative_cur_l + && tentative_p_off >= 0 + && tentative_p_off <= strlen(tentative_cur_l->text)){ + ods.cur_l = tentative_cur_l; + ods.p_off = tentative_p_off; + } + } + } + + free(buf); + return(i); +} + + + + +/* + * break_point - Break the given line s at the most reasonable character c + * within l max characters. + * + * returns: + * Pointer to the best break point in s, or + * Pointer to the beginning of s if no break point found + */ +char * +break_point(s, l, ch, q) + char *s; + int l, ch, *q; +{ + register char *b = s + l; + int quoted = (q) ? *q : 0; + + while(b != s){ + if(ch == ',' && *b == '"') /* don't break on quoted ',' */ + quoted = !quoted; /* toggle quoted state */ + + if(*b == ch){ + if(ch == ' '){ + if(b + 1 < s + l){ + b++; /* leave the ' ' */ + break; + } + } + else{ + /* + * if break char isn't a space, leave a space after + * the break char. + */ + if(!(b+1 >= s+l || (b[1] == ' ' && b+2 == s+l))){ + b += (b[1] == ' ') ? 2 : 1; + break; + } + } + } + b--; + } + + if(q) + *q = quoted; + + return((quoted) ? s : b); +} + + + + +/* + * hldelete() - remove the header line pointed to by l from the linked list + * of lines. + * + * notes: + * the case of first line in field is kind of bogus. since + * the array of headers has a pointer to the first line, and + * i don't want to worry about this too much, i just copied + * the line below and removed it rather than the first one + * from the list. + * + * returns: + * TRUE if it worked + * FALSE otherwise + */ +hldelete(l) +struct hdr_line *l; +{ + register struct hdr_line *lp; + + if(l == NULL) + return(FALSE); + + if(l->next == NULL && l->prev == NULL){ /* only one line in field */ + l->text[0] = '\0'; + return(TRUE); /* no free only line in list */ + } + else if(l->next == NULL){ /* last line in field */ + l->prev->next = NULL; + } + else if(l->prev == NULL){ /* first line in field */ + strcpy(l->text, l->next->text); + lp = l->next; + if((l->next = lp->next) != NULL) + l->next->prev = l; + l = lp; + } + else{ /* some where in field */ + l->prev->next = l->next; + l->next->prev = l->prev; + } + + l->next = NULL; + l->prev = NULL; + free((char *)l); + return(TRUE); +} + + + +/* + * is_blank - returns true if the next n chars from coordinates row, col + * on display are spaces + */ +is_blank(row, col, n) +int row, col, n; +{ + n += col; + for( ;col < n; col++){ + if(pscr(row, col) == NULL || pscr(row, col)->c != ' ') + return(0); + } + return(1); +} + + +/* + * ShowPrompt - display key help corresponding to the current header entry + */ +void +ShowPrompt() +{ + if(headents[ods.cur_e].key_label){ + menu_header[TO_KEY].name = "^T"; + menu_header[TO_KEY].label = headents[ods.cur_e].key_label; + KS_OSDATASET(&menu_header[TO_KEY], KS_OSDATAGET(&headents[ods.cur_e])); + } + else + menu_header[TO_KEY].name = NULL; + + if(Pmaster && Pmaster->exit_label) + menu_header[SEND_KEY].label = Pmaster->exit_label; + else if(gmode & (MDVIEW | MDHDRONLY)) + menu_header[SEND_KEY].label = (gmode & MDHDRONLY) ? "eXit/Save" : "eXit"; + else + menu_header[SEND_KEY].label = "Send"; + + if(gmode & MDVIEW){ + menu_header[CUT_KEY].name = NULL; + menu_header[DEL_KEY].name = NULL; + menu_header[UDEL_KEY].name = NULL; + } + else{ + menu_header[CUT_KEY].name = "^K"; + menu_header[DEL_KEY].name = "^D"; + menu_header[UDEL_KEY].name = "^U"; + } + + if(Pmaster->ctrlr_label){ + menu_header[RICH_KEY].label = Pmaster->ctrlr_label; + menu_header[RICH_KEY].name = "^R"; + } + else if(gmode & MDHDRONLY){ + menu_header[RICH_KEY].name = NULL; + } + else{ + menu_header[RICH_KEY].label = "Rich Hdr"; + menu_header[RICH_KEY].name = "^R"; + } + + if(gmode & MDHDRONLY){ + if(headents[ods.cur_e].fileedit){ + menu_header[PONE_KEY].name = "^_"; + menu_header[PONE_KEY].label = "Edit File"; + } + else + menu_header[PONE_KEY].name = NULL; + + menu_header[ATT_KEY].name = NULL; + } + else{ + menu_header[PONE_KEY].name = "^O"; + menu_header[PONE_KEY].label = "Postpone"; + + menu_header[ATT_KEY].name = "^J"; + } + + wkeyhelp(menu_header); +} + + +/* + * packheader - packup all of the header fields for return to caller. + * NOTE: all of the header info passed in, including address + * of the pointer to each string is contained in the + * header entry array "headents". + */ +packheader() +{ + register int i = 0; /* array index */ + register int count; /* count of chars in a field */ + register int retval = TRUE; /* count of chars in a field */ + register char *bufp; /* */ + register struct hdr_line *line; + + if(!headents) + return(TRUE); + + while(headents[i].name != NULL){ +#ifdef ATTACHMENTS + /* + * attachments are special case, already in struct we pass back + */ + if(headents[i].is_attach){ + i++; + continue; + } +#endif + + if(headents[i].blank){ + i++; + continue; + } + + /* + * count chars to see if we need a new malloc'd space for our + * array. + */ + line = headents[i].hd_text; + count = 0; + while(line != NULL){ + /* + * add one for possible concatination of a ' ' character ... + */ + count += (strlen(line->text) + 1); + line = line->next; + } + + line = headents[i].hd_text; + if(count < headents[i].maxlen){ + *headents[i].realaddr[0] = '\0'; + } + else{ + /* + * don't forget to include space for the null terminator!!!! + */ + if((bufp = (char *)malloc((count+1) * sizeof(char))) != NULL){ + *bufp = '\0'; + + free(*headents[i].realaddr); + *headents[i].realaddr = bufp; + } + else{ + emlwrite("Can't make room to pack header field.", NULL); + retval = FALSE; + } + } + + if(retval != FALSE){ + while(line != NULL){ + /* pass the cursor offset back in Pmaster struct */ + if(headents[i].start_here && ods.cur_l == line && Pmaster) + Pmaster->edit_offset += strlen(*headents[i].realaddr); + + strcat(*headents[i].realaddr, line->text); + if(line->text[0] && line->text[strlen(line->text)-1] == ',') + strcat(*headents[i].realaddr, " "); + + line = line->next; + } + } + + i++; + } + return(retval); +} + + + +/* + * zotheader - free all malloc'd lines associated with the header structs + */ +void +zotheader() +{ + register struct headerentry *i; + + for(i = headents; headents && i->name; i++) + zotentry(i->hd_text); +} + + +/* + * zotentry - free malloc'd space associated with the given linked list + */ +void +zotentry(l) +register struct hdr_line *l; +{ + register struct hdr_line *ld, *lf = l; + + while((ld = lf) != NULL){ + lf = ld->next; + ld->next = ld->prev = NULL; + free((char *) ld); + } +} + + + +/* + * zotcomma - blast any trailing commas and white space from the end + * of the given line + */ +int +zotcomma(s) +char *s; +{ + register char *p; + int retval = FALSE; + + p = &s[strlen(s)]; + while(--p >= s){ + if(*p != ' '){ + if(*p == ','){ + *p = '\0'; + retval = TRUE; + } + + return(retval); + } + } + + return(retval); +} + + +/* + * Save the current state of global variables so that we can restore + * them later. This is so we can call pico again. + * Also have to initialize some variables that normally would be set to + * zero on startup. + */ +VARS_TO_SAVE * +save_pico_state() +{ + VARS_TO_SAVE *ret; + extern int vtrow; + extern int vtcol; + extern int lbound; + extern VIDEO **vscreen; + extern VIDEO **pscreen; + extern int pico_all_done; + extern jmp_buf finstate; + extern char *pico_anchor; + + if((ret = (VARS_TO_SAVE *)malloc(sizeof(VARS_TO_SAVE))) == NULL) + return(ret); + + ret->vtrow = vtrow; + ret->vtcol = vtcol; + ret->lbound = lbound; + ret->vscreen = vscreen; + ret->pscreen = pscreen; + ret->ods = ods; + ret->delim_ps = delim_ps; + ret->invert_ps = invert_ps; + ret->pico_all_done = pico_all_done; + memcpy(ret->finstate, finstate, sizeof(jmp_buf)); + ret->pico_anchor = pico_anchor; + ret->Pmaster = Pmaster; + ret->fillcol = fillcol; + if((ret->pat = (char *)malloc(sizeof(char) * (strlen(pat)+1))) != NULL) + strcpy(ret->pat, pat); + + ret->ComposerTopLine = ComposerTopLine; + ret->ComposerEditing = ComposerEditing; + ret->gmode = gmode; + ret->alt_speller = alt_speller; + ret->quote_str = glo_quote_str; + ret->currow = currow; + ret->curcol = curcol; + ret->thisflag = thisflag; + ret->lastflag = lastflag; + ret->curgoal = curgoal; + ret->opertree = (char *) malloc(sizeof(char) * (strlen(opertree) + 1)); + if(ret->opertree != NULL) + strcpy(ret->opertree, opertree); + + ret->curwp = curwp; + ret->wheadp = wheadp; + ret->curbp = curbp; + ret->bheadp = bheadp; + ret->km_popped = km_popped; + ret->mrow = term.t_mrow; + + /* Initialize for next pico call */ + wheadp = NULL; + curwp = NULL; + bheadp = NULL; + curbp = NULL; + + return(ret); +} + + +void +restore_pico_state(state) +VARS_TO_SAVE *state; +{ + extern int vtrow; + extern int vtcol; + extern int lbound; + extern VIDEO **vscreen; + extern VIDEO **pscreen; + extern int pico_all_done; + extern jmp_buf finstate; + extern char *pico_anchor; + + clearcursor(); + vtrow = state->vtrow; + vtcol = state->vtcol; + lbound = state->lbound; + vscreen = state->vscreen; + pscreen = state->pscreen; + ods = state->ods; + delim_ps = state->delim_ps; + invert_ps = state->invert_ps; + pico_all_done = state->pico_all_done; + memcpy(finstate, state->finstate, sizeof(jmp_buf)); + pico_anchor = state->pico_anchor; + Pmaster = state->Pmaster; + if(Pmaster) + headents = Pmaster->headents; + + fillcol = state->fillcol; + if(state->pat) + strcpy(pat, state->pat); + + ComposerTopLine = state->ComposerTopLine; + ComposerEditing = state->ComposerEditing; + gmode = state->gmode; + alt_speller = state->alt_speller; + glo_quote_str = state->quote_str; + currow = state->currow; + curcol = state->curcol; + thisflag = state->thisflag; + lastflag = state->lastflag; + curgoal = state->curgoal; + if(state->opertree) + strcpy(opertree, state->opertree); + + curwp = state->curwp; + wheadp = state->wheadp; + curbp = state->curbp; + bheadp = state->bheadp; + km_popped = state->km_popped; + term.t_mrow = state->mrow; +} + + +void +free_pico_state(state) +VARS_TO_SAVE *state; +{ + if(state->pat) + free(state->pat); + + if(state->opertree) + free(state->opertree); + + free(state); +} + + +/* + * Ok to call this twice in a row because it won't do anything the second + * time. + */ +void +fix_mangle_and_err(mangled, errmsg, name) + int *mangled; + char **errmsg; + char *name; +{ + if(mangled && *mangled){ + ttresize(); + picosigs(); + PaintBody(0); + *mangled = 0; + } + + if(errmsg && *errmsg){ + if(**errmsg){ + char err[500]; + + sprintf(err, "%s field: %s", name, *errmsg); + (*term.t_beep)(); + emlwrite(err, NULL); + } + else + mlerase(); + + free(*errmsg); + *errmsg = NULL; + } +} + + +#ifdef MOUSE +#undef HeaderEditor + +/* + * Wraper function for the real header editor. + * Does the important tasks of: + * 1) verifying that we _can_ edit the headers. + * 2) acting on the result code from the header editor. + */ +int +HeaderEditor(f, n) + int f, n; +{ + int retval; + + +#ifdef _WINDOWS + /* Sometimes we get here from a scroll callback, which + * is no good at all because mswin is not ready to process input and + * this _headeredit() will never do anything. + * Putting this test here was the most general solution I could think + * of. */ + if (!mswin_caninput()) + return (-1); +#endif + + retval = HeaderEditorWork(f, n); + if (retval == -3) { + retval = mousepress(0,0); + } + return (retval); +} +#endif diff --git a/display.c b/display.c new file mode 100644 index 0000000..ab7f513 --- /dev/null +++ b/display.c @@ -0,0 +1,2572 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: display.c 13654 2004-05-07 21:43:40Z jpf $"; +#endif +/* + * Program: Display functions + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* + * The functions in this file handle redisplay. There are two halves, the + * ones that update the virtual display screen, and the ones that make the + * physical display screen the same as the virtual display screen. These + * functions use hints that are left in the windows by the commands. + * + */ + +#include "headers.h" + + +#ifdef ANSI + void vtmove(int, int); + void vtputc(CELL); + void vtpute(CELL); + void vteeol(void); + void updateline(int, CELL *, CELL *, short *); + void updext(void); + void mlputi(int, int); + void pprints(int, int); + void mlputli(long, int); + void showCompTitle(void); + int nlforw(void); + int dumbroot(int, int); + int dumblroot(long, int); +#else + void vtmove(); + void vtputc(); + void vtpute(); + void vteeol(); + void updateline(); + void updext(); + void mlputi(); + void pprints(); + void mlputli(); + void showCompTitle(); + int nlforw(); + int dumbroot(); + int dumblroot(); +#endif + + +/* + * Standard pico keymenus... + */ +static KEYMENU menu_pico[] = { + {"^G", "Get Help", KS_SCREENHELP}, {"^O", "WriteOut", KS_SAVEFILE}, + {"^R", "Read File", KS_READFILE}, {"^Y", "Prev Pg", KS_PREVPAGE}, + {"^K", "Cut Text", KS_NONE}, {"^C", "Cur Pos", KS_CURPOSITION}, + {"^X", "Exit", KS_EXIT}, {"^J", "Justify", KS_JUSTIFY}, + {"^W", "Where is", KS_WHEREIS}, {"^V", "Next Pg", KS_NEXTPAGE}, + {"^U", NULL, KS_NONE}, +#ifdef SPELLER + {"^T", "To Spell", KS_SPELLCHK} +#else + {"^D", "Del Char", KS_NONE} +#endif +}; +#define UNCUT_KEY 10 + + +static KEYMENU menu_compose[] = { + {"^G", "Get Help", KS_SCREENHELP}, {"^X", NULL, KS_SEND}, + {"^R", "Read File", KS_READFILE}, {"^Y", "Prev Pg", KS_PREVPAGE}, + {"^K", "Cut Text", KS_NONE}, {"^O", "Postpone", KS_POSTPONE}, + {"^C", "Cancel", KS_CANCEL}, {"^J", "Justify", KS_JUSTIFY}, + {NULL, NULL, KS_NONE}, {"^V", "Next Pg", KS_NEXTPAGE}, + {"^U", NULL, KS_NONE}, +#ifdef SPELLER + {"^T", "To Spell", KS_SPELLCHK} +#else + {"^D", "Del Char", KS_NONE} +#endif +}; +#define EXIT_KEY 1 +#define PSTPN_KEY 5 +#define WHERE_KEY 8 + + +/* + * Definition's for pico's modeline + */ +#define PICO_TITLE " UW PICO(tm) %s " +#define PICO_MOD_MSG "Modified " +#define PICO_NEWBUF_MSG " New Buffer " + +#define WFDEBUG 0 /* Window flag debug. */ + +#define VFCHG 0x0001 /* Changed flag */ +#define VFEXT 0x0002 /* extended (beyond column 80) */ +#define VFREV 0x0004 /* reverse video status */ +#define VFREQ 0x0008 /* reverse video request */ + +int vtrow = 0; /* Row location of SW cursor */ +int vtcol = 0; /* Column location of SW cursor */ +int ttrow = FARAWAY; /* Row location of HW cursor */ +int ttcol = FARAWAY; /* Column location of HW cursor */ +int lbound = 0; /* leftmost column of current line + being displayed */ + +VIDEO **vscreen; /* Virtual screen. */ +VIDEO **pscreen; /* Physical screen. */ + +#define ISCONTROL(C) ((C) < 0x20 || (C) == 0x7F \ + || ((gmode & P_HICTRL) && ((C) > 0x7F && (C) < 0xA0))) + + +/* + * Initialize the data structures used by the display code. The edge vectors + * used to access the screens are set up. The operating system's terminal I/O + * channel is set up. All the other things get initialized at compile time. + * The original window has "WFCHG" set, so that it will get completely + * redrawn on the first call to "update". + */ +vtinit() +{ + register int i; + register VIDEO *vp; + + if(Pmaster == NULL) + vtterminalinfo(gmode & MDTCAPWINS); + + (*term.t_open)(); + + (*term.t_rev)(FALSE); + vscreen = (VIDEO **) malloc((term.t_nrow+1)*sizeof(VIDEO *)); + if (vscreen == NULL){ + emlwrite("Allocating memory for virtual display failed.", NULL); + return(FALSE); + } + + + pscreen = (VIDEO **) malloc((term.t_nrow+1)*sizeof(VIDEO *)); + if (pscreen == NULL){ + free((void *)vscreen); + emlwrite("Allocating memory for physical display failed.", NULL); + return(FALSE); + } + + + for (i = 0; i <= term.t_nrow; ++i) { + vp = (VIDEO *) malloc(sizeof(VIDEO)+(term.t_ncol*sizeof(CELL))); + + if (vp == NULL){ + free((void *)vscreen); + free((void *)pscreen); + emlwrite("Allocating memory for virtual display lines failed.", + NULL); + return(FALSE); + } + else + memset(vp, ' ', sizeof(VIDEO)+(term.t_ncol*sizeof(CELL))); + + vp->v_flag = 0; + vscreen[i] = vp; + vp = (VIDEO *) malloc(sizeof(VIDEO)+(term.t_ncol*sizeof(CELL))); + + if (vp == NULL){ + free((void *)vscreen[i]); + while(--i >= 0){ + free((void *)vscreen[i]); + free((void *)pscreen[i]); + } + + free((void *)vscreen); + free((void *)pscreen); + emlwrite("Allocating memory for physical display lines failed.", + NULL); + return(FALSE); + } + else + memset(vp, ' ', sizeof(VIDEO)+(term.t_ncol*sizeof(CELL))); + + vp->v_flag = 0; + pscreen[i] = vp; + } + + return(TRUE); +} + +vtterminalinfo(termcap_wins) + int termcap_wins; +{ + return((term.t_terminalinfo) ? (*term.t_terminalinfo)(termcap_wins) + : (Pmaster ? 0 : TRUE)); +} + + +/* + * Clean up the virtual terminal system, in anticipation for a return to the + * operating system. Move down to the last line and clear it out (the next + * system prompt will be written in the line). Shut down the channel to the + * terminal. + */ +void +vttidy() +{ + movecursor(term.t_nrow-1, 0); + peeol(); + movecursor(term.t_nrow, 0); + peeol(); + (*term.t_close)(); +} + + +/* + * Set the virtual cursor to the specified row and column on the virtual + * screen. There is no checking for nonsense values; this might be a good + * idea during the early stages. + */ +void +vtmove(row, col) +int row, col; +{ + vtrow = row; + vtcol = col; +} + + +/* + * Write a character to the virtual screen. The virtual row and column are + * updated. If the line is too long put a "$" in the last column. This routine + * only puts printing characters into the virtual terminal buffers. Only + * column overflow is checked. + */ +void +vtputc(c) +CELL c; +{ + register VIDEO *vp; + CELL ac; + + vp = vscreen[vtrow]; + ac.c = ' '; + ac.a = c.a; + + if (vtcol >= term.t_ncol) { + vtcol = (vtcol + 0x07) & ~0x07; + ac.c = '$'; + vp->v_text[term.t_ncol - 1] = ac; + } + else if (c.c == '\t') { + do { + vtputc(ac); + } + while ((vtcol&0x07) != 0); + } + else if (ISCONTROL(c.c)){ + ac.c = '^'; + vtputc(ac); + ac.c = ((c.c & 0x7f) | 0x40); + vtputc(ac); + } + else + vp->v_text[vtcol++] = c; +} + + +/* put a character to the virtual screen in an extended line. If we are + * not yet on left edge, don't print it yet. check for overflow on + * the right margin. + */ +void +vtpute(c) +CELL c; +{ + register VIDEO *vp; + CELL ac; + + vp = vscreen[vtrow]; + ac.c = ' '; + ac.a = c.a; + + if (vtcol >= term.t_ncol) { + vtcol = (vtcol + 0x07) & ~0x07; + ac.c = '$'; + vp->v_text[term.t_ncol - 1] = ac; + } + else if (c.c == '\t'){ + do { + vtpute(ac); + } + while (((vtcol + lbound)&0x07) != 0 && vtcol < term.t_ncol); + } + else if (ISCONTROL(c.c)){ + ac.c = '^'; + vtpute(ac); + ac.c = ((c.c & 0x7f) | 0x40); + vtpute(ac); + } + else { + if (vtcol >= 0) + vp->v_text[vtcol] = c; + ++vtcol; + } +} + + +/* + * Erase from the end of the software cursor to the end of the line on which + * the software cursor is located. + */ +void +vteeol() +{ + register VIDEO *vp; + CELL c; + + c.c = ' '; + c.a = 0; + vp = vscreen[vtrow]; + while (vtcol < term.t_ncol) + vp->v_text[vtcol++] = c; +} + + +/* + * Make sure that the display is right. This is a three part process. First, + * scan through all of the windows looking for dirty ones. Check the framing, + * and refresh the screen. Second, make sure that "currow" and "curcol" are + * correct for the current window. Third, make the virtual and physical + * screens the same. + */ +void +update() +{ + register LINE *lp; + register WINDOW *wp; + register VIDEO *vp1; + register VIDEO *vp2; + register int i; + register int j; + register int scroll = 0; + CELL c; + +#if TYPEAH + if (typahead()) + return; +#endif + +#ifdef _WINDOWS + /* This tells our MS Windows module to not bother updating the + * cursor position while a massive screen update is in progress. + */ + mswin_beginupdate (); +#endif + +/* + * BUG: setting and unsetting whole region at a time is dumb. fix this. + */ + if(curwp->w_markp){ + unmarkbuffer(); + markregion(1); + } + + wp = wheadp; + + while (wp != NULL){ + /* Look at any window with update flags set on. */ + + if (wp->w_flag != 0){ + /* If not force reframe, check the framing. */ + + if ((wp->w_flag & WFFORCE) == 0){ + lp = wp->w_linep; + + for (i = 0; i < wp->w_ntrows; ++i){ + if (lp == wp->w_dotp) + goto out; + + if (lp == wp->w_bufp->b_linep) + break; + + lp = lforw(lp); + } + } + + /* Not acceptable, better compute a new value for the line at the + * top of the window. Then set the "WFHARD" flag to force full + * redraw. + */ + i = wp->w_force; + + if (i > 0){ + --i; + + if (i >= wp->w_ntrows) + i = wp->w_ntrows-1; + } + else if (i < 0){ + i += wp->w_ntrows; + + if (i < 0) + i = 0; + } + else if(optimize){ + /* + * find dotp, if its been moved just above or below the + * window, use scrollxxx() to facilitate quick redisplay... + */ + lp = lforw(wp->w_dotp); + if(lp != wp->w_dotp){ + if(lp == wp->w_linep && lp != wp->w_bufp->b_linep){ + scroll = 1; + } + else { + lp = wp->w_linep; + for(j=0;j < wp->w_ntrows; ++j){ + if(lp != wp->w_bufp->b_linep) + lp = lforw(lp); + else + break; + } + if(lp == wp->w_dotp && j == wp->w_ntrows) + scroll = 2; + } + } + j = i = wp->w_ntrows/2; + } + else + i = wp->w_ntrows/2; + + lp = wp->w_dotp; + + while (i != 0 && lback(lp) != wp->w_bufp->b_linep){ + --i; + lp = lback(lp); + } + + /* + * this is supposed to speed things up by using tcap sequences + * to efficiently scroll the terminal screen. the thinking here + * is that its much faster to update pscreen[] than to actually + * write the stuff to the screen... + */ + if(optimize){ + switch(scroll){ + case 1: /* scroll text down */ + j = j-i+1; /* add one for dot line */ + /* + * do we scroll down the header as well? Well, only + * if we're not editing the header, we've backed up + * to the top, and the composer is not being + * displayed... + */ + if(Pmaster && Pmaster->headents && !ComposerEditing + && (lback(lp) == wp->w_bufp->b_linep) + && (ComposerTopLine == COMPOSER_TOP_LINE)) + j += entry_line(1000, TRUE); /* Never > 1000 headers */ + + scrolldown(wp, -1, j); + break; + case 2: /* scroll text up */ + j = wp->w_ntrows - (j-i); /* we chose new top line! */ + if(Pmaster && j){ + /* + * do we scroll down the header as well? Well, only + * if we're not editing the header, we've backed up + * to the top, and the composer is not being + * displayed... + */ + if(!ComposerEditing + && (ComposerTopLine != COMPOSER_TOP_LINE)) + scrollup(wp, COMPOSER_TOP_LINE, + j+entry_line(1000, TRUE)); + else + scrollup(wp, -1, j); + } + else + scrollup(wp, -1, j); + break; + default : + break; + } + } + + wp->w_linep = lp; + wp->w_flag |= WFHARD; /* Force full. */ +out: + /* + * if the line at the top of the page is the top line + * in the body, show the header... + */ + if(Pmaster && Pmaster->headents && !ComposerEditing){ + if(lback(wp->w_linep) == wp->w_bufp->b_linep){ + if(ComposerTopLine == COMPOSER_TOP_LINE){ + i = term.t_nrow - 2 - term.t_mrow - HeaderLen(); + if(i > 0 && nlforw() >= i) { /* room for header ? */ + if((i = nlforw()/2) == 0 && term.t_nrow&1) + i = 1; + while(wp->w_linep != wp->w_bufp->b_linep && i--) + wp->w_linep = lforw(wp->w_linep); + + } + else + ToggleHeader(1); + } + } + else{ + if(ComposerTopLine != COMPOSER_TOP_LINE) + ToggleHeader(0); /* hide it ! */ + } + } + + /* Try to use reduced update. Mode line update has its own special + * flag. The fast update is used if the only thing to do is within + * the line editing. + */ + lp = wp->w_linep; + i = wp->w_toprow; + + if ((wp->w_flag & ~WFMODE) == WFEDIT){ + while (lp != wp->w_dotp){ + ++i; + lp = lforw(lp); + } + + vscreen[i]->v_flag |= VFCHG; + vtmove(i, 0); + + for (j = 0; j < llength(lp); ++j) + vtputc(lgetc(lp, j)); + + vteeol(); + } + else if ((wp->w_flag & (WFEDIT | WFHARD)) != 0){ + while (i < wp->w_toprow+wp->w_ntrows){ + vscreen[i]->v_flag |= VFCHG; + vtmove(i, 0); + + /* if line has been changed */ + if (lp != wp->w_bufp->b_linep){ + for (j = 0; j < llength(lp); ++j) + vtputc(lgetc(lp, j)); + + lp = lforw(lp); + } + + vteeol(); + ++i; + } + } +#if ~WFDEBUG + if ((wp->w_flag&WFMODE) != 0) + modeline(wp); + + wp->w_flag = 0; + wp->w_force = 0; +#endif + } +#if WFDEBUG + modeline(wp); + wp->w_flag = 0; + wp->w_force = 0; +#endif + + /* and onward to the next window */ + wp = wp->w_wndp; + } + + /* Always recompute the row and column number of the hardware cursor. This + * is the only update for simple moves. + */ + lp = curwp->w_linep; + currow = curwp->w_toprow; + + while (lp != curwp->w_dotp){ + ++currow; + lp = lforw(lp); + } + + curcol = 0; + i = 0; + + while (i < curwp->w_doto){ + c = lgetc(lp, i++); + + if (c.c == '\t') + curcol |= 0x07; + else if (ISCONTROL(c.c)) + ++curcol; + + ++curcol; + } + + if (curcol >= term.t_ncol) { /* extended line. */ + /* flag we are extended and changed */ + vscreen[currow]->v_flag |= VFEXT | VFCHG; + updext(); /* and output extended line */ + } else + lbound = 0; /* not extended line */ + + /* make sure no lines need to be de-extended because the cursor is + * no longer on them + */ + + wp = wheadp; + + while (wp != NULL) { + lp = wp->w_linep; + i = wp->w_toprow; + + while (i < wp->w_toprow + wp->w_ntrows) { + if (vscreen[i]->v_flag & VFEXT) { + /* always flag extended lines as changed */ + vscreen[i]->v_flag |= VFCHG; + if ((wp != curwp) || (lp != wp->w_dotp) || + (curcol < term.t_ncol)) { + vtmove(i, 0); + for (j = 0; j < llength(lp); ++j) + vtputc(lgetc(lp, j)); + vteeol(); + + /* this line no longer is extended */ + vscreen[i]->v_flag &= ~VFEXT; + } + } + lp = lforw(lp); + ++i; + } + /* and onward to the next window */ + wp = wp->w_wndp; + } + + /* Special hacking if the screen is garbage. Clear the hardware screen, + * and update your copy to agree with it. Set all the virtual screen + * change bits, to force a full update. + */ + + if (sgarbf != FALSE){ + if(Pmaster){ + int rv; + + showCompTitle(); + + if(ComposerTopLine != COMPOSER_TOP_LINE){ + UpdateHeader(0); /* arrange things */ + PaintHeader(COMPOSER_TOP_LINE, TRUE); + } + + /* + * since we're using only a portion of the screen and only + * one buffer, only clear enough screen for the current window + * which is to say the *only* window. + */ + for(i=wheadp->w_toprow;i<=term.t_nrow; i++){ + movecursor(i, 0); + peeol(); + vscreen[i]->v_flag |= VFCHG; + } + rv = (*Pmaster->showmsg)('X' & 0x1f); /* ctrl-L */ + ttresize(); + picosigs(); /* restore altered handlers */ + if(rv) /* Did showmsg corrupt the display? */ + PaintBody(0); /* Yes, repaint */ + movecursor(wheadp->w_toprow, 0); + } + else{ + for (i = 0; i < term.t_nrow-term.t_mrow; ++i){ + vscreen[i]->v_flag |= VFCHG; + vp1 = pscreen[i]; + c.c = ' '; + c.a = 0; + for (j = 0; j < term.t_ncol; ++j) + vp1->v_text[j] = c; + } + + movecursor(0, 0); /* Erase the screen. */ + (*term.t_eeop)(); + + } + + sgarbf = FALSE; /* Erase-page clears */ + mpresf = FALSE; /* the message area. */ + + if(Pmaster) + modeline(curwp); + else + sgarbk = TRUE; /* fix the keyhelp as well...*/ + } + + /* Make sure that the physical and virtual displays agree. Unlike before, + * the "updateline" code is only called with a line that has been updated + * for sure. + */ + if(Pmaster) + i = curwp->w_toprow; + else + i = 0; + + if (term.t_nrow > term.t_mrow) + c.c = term.t_nrow - term.t_mrow; + else + c.c = 0; + + for (; i < (int)c.c; ++i){ + + vp1 = vscreen[i]; + + /* for each line that needs to be updated, or that needs its + reverse video status changed, call the line updater */ + j = vp1->v_flag; + if (j & VFCHG){ + +#if TYPEAH + if (typahead()){ +#ifdef _WINDOWS + mswin_endupdate (); +#endif + return; + } +#endif + vp2 = pscreen[i]; + + updateline(i, &vp1->v_text[0], &vp2->v_text[0], &vp1->v_flag); + + } + } + + if(Pmaster == NULL){ + + if(sgarbk != FALSE){ + if(term.t_mrow > 0){ + movecursor(term.t_nrow-1, 0); + peeol(); + movecursor(term.t_nrow, 0); + peeol(); + } + + if(lastflag&CFFILL){ + menu_pico[UNCUT_KEY].label = "UnJustify"; + if(!(lastflag&CFFLBF)){ + emlwrite("Can now UnJustify!", NULL); + mpresf = FARAWAY; /* remove this after next keystroke! */ + } + } + else + menu_pico[UNCUT_KEY].label = "UnCut Text"; + + wkeyhelp(menu_pico); + sgarbk = FALSE; + } + } + if(lastflag&CFFLBF){ + emlwrite("Can now UnJustify!", NULL); + mpresf = FARAWAY; /* remove this after next keystroke! */ + } + + /* Finally, update the hardware cursor and flush out buffers. */ + + movecursor(currow, curcol - lbound); +#ifdef _WINDOWS + mswin_endupdate (); + + /* + * Update the scroll bars. This function is where curbp->b_linecnt + * is really managed. See update_scroll. + */ + update_scroll (); +#endif + (*term.t_flush)(); +} + + +/* updext - update the extended line which the cursor is currently + * on at a column greater than the terminal width. The line + * will be scrolled right or left to let the user see where + * the cursor is + */ +void +updext() +{ + register int rcursor; /* real cursor location */ + register LINE *lp; /* pointer to current line */ + register int j; /* index into line */ + + /* calculate what column the real cursor will end up in */ + rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin; + lbound = curcol - rcursor + 1; + + /* scan through the line outputing characters to the virtual screen + * once we reach the left edge + */ + vtmove(currow, -lbound); /* start scanning offscreen */ + lp = curwp->w_dotp; /* line to output */ + for (j=0; jv_text[0].c = '$'; + vscreen[currow]->v_text[0].a = 0; +} + + +/* + * Update a single line. This does not know how to use insert or delete + * character sequences; we are using VT52 functionality. Update the physical + * row and column variables. It does try an exploit erase to end of line. The + * RAINBOW version of this routine uses fast video. + */ +void +updateline(row, vline, pline, flags) +int row; +CELL vline[]; /* what we want it to end up as */ +CELL pline[]; /* what it looks like now */ +short *flags; /* and how we want it that way */ +{ + register CELL *cp1; + register CELL *cp2; + register CELL *cp3; + register CELL *cp4; + register CELL *cp5; + register CELL *cp6; + register CELL *cp7; + register int display = TRUE; + register int nbflag; /* non-blanks to the right flag? */ + + + /* set up pointers to virtual and physical lines */ + cp1 = &vline[0]; + cp2 = &pline[0]; + cp3 = &vline[term.t_ncol]; + + /* advance past any common chars at the left */ + while (cp1 != cp3 && cp1[0].c == cp2[0].c && cp1[0].a == cp2[0].a) { + ++cp1; + ++cp2; + } + +/* This can still happen, even though we only call this routine on changed + * lines. A hard update is always done when a line splits, a massive + * change is done, or a buffer is displayed twice. This optimizes out most + * of the excess updating. A lot of computes are used, but these tend to + * be hard operations that do a lot of update, so I don't really care. + */ + /* if both lines are the same, no update needs to be done */ + if (cp1 == cp3){ + *flags &= ~VFCHG; /* mark it clean */ + return; + } + + /* find out if there is a match on the right */ + nbflag = FALSE; + cp3 = &vline[term.t_ncol]; + cp4 = &pline[term.t_ncol]; + + while (cp3[-1].c == cp4[-1].c && cp3[-1].a == cp4[-1].a) { + --cp3; + --cp4; + if (cp3[0].c != ' ' || cp3[0].a != 0)/* Note if any nonblank */ + nbflag = TRUE; /* in right match. */ + } + + cp5 = cp3; + + if (nbflag == FALSE && eolexist == TRUE) { /* Erase to EOL ? */ + while (cp5 != cp1 && cp5[-1].c == ' ' && cp5[-1].a == 0) + --cp5; + + if (cp3-cp5 <= 3) /* Use only if erase is */ + cp5 = cp3; /* fewer characters. */ + } + + movecursor(row, cp1-&vline[0]); /* Go to start of line. */ + + if (!nbflag) { /* use insert or del char? */ + cp6 = cp3; + cp7 = cp4; + + if(inschar&&(cp7!=cp2 && cp6[0].c==cp7[-1].c && cp6[0].a==cp7[-1].a)){ + while (cp7 != cp2 && cp6[0].c==cp7[-1].c && cp6[0].a==cp7[-1].a){ + --cp7; + --cp6; + } + + if (cp7==cp2 && cp4-cp2 > 3){ + o_insert((int)cp1->c); /* insert the char */ + display = FALSE; /* only do it once!! */ + } + } + else if(delchar && cp3 != cp1 && cp7[0].c == cp6[-1].c + && cp7[0].a == cp6[-1].a){ + while (cp6 != cp1 && cp7[0].c==cp6[-1].c && cp7[0].a==cp6[-1].a){ + --cp7; + --cp6; + } + + if (cp6==cp1 && cp5-cp6 > 3){ + o_delete(); /* insert the char */ + display = FALSE; /* only do it once!! */ + } + } + } + + while (cp1 != cp5) { /* Ordinary. */ + if(display){ + (*term.t_rev)(cp1->a); /* set inverse for this char */ + (*term.t_putchar)(cp1->c); + } + + ++ttcol; + *cp2++ = *cp1++; + } + + (*term.t_rev)(0); /* turn off inverse anyway! */ + + if (cp5 != cp3) { /* Erase. */ + if(display) + peeol(); + while (cp1 != cp3) + *cp2++ = *cp1++; + } + *flags &= ~VFCHG; /* flag this line is changed */ +} + + +/* + * Redisplay the mode line for the window pointed to by the "wp". This is the + * only routine that has any idea of how the modeline is formatted. You can + * change the modeline format by hacking at this routine. Called by "update" + * any time there is a dirty window. + */ +void +modeline(wp) +WINDOW *wp; +{ + if(Pmaster){ + if(ComposerEditing) + ShowPrompt(); + else{ + menu_compose[EXIT_KEY].label = (Pmaster->headents) + ? "Send" :"Exit"; + menu_compose[PSTPN_KEY].name = (Pmaster->headents) + ? "^O" : NULL; + menu_compose[PSTPN_KEY].label = (Pmaster->headents) + ? "Postpone" : NULL; + menu_compose[WHERE_KEY].name = (Pmaster->alt_ed) ? "^_" : "^W"; + menu_compose[WHERE_KEY].label = (Pmaster->alt_ed) ? "Alt Edit" + : "Where is"; + KS_OSDATASET(&menu_compose[WHERE_KEY], + (Pmaster->alt_ed) ? KS_ALTEDITOR : KS_WHEREIS); + menu_compose[UNCUT_KEY].label = (thisflag&CFFILL) ? "UnJustify" + : "UnCut Text"; + wkeyhelp(menu_compose); +#ifdef _WINDOWS + /* When alt editor is available "Where is" is not on the menu + * but the command is still available. This call enables any + * "Where is" menu items. */ + if (Pmaster->alt_ed) + mswin_menuitemadd (MENU|CTRL|'W', "", KS_WHEREIS, 0); +#endif + } + } + else{ + register char *cp; + register int n; /* cursor position count */ + register BUFFER *bp; + register int i; /* loop index */ + register int lchar; /* character to draw line in buffer with */ + char tline[NLINE]; /* buffer for part of mode line */ + CELL c; + + n = 0; + c.a = 1; + vtmove(1, 0); + vteeol(); + vscreen[n]->v_flag |= VFCHG; /* Redraw next time. */ + vtmove(n, 0); /* Seek to right line. */ + +#if REVSTA + if (revexist) + lchar = ' '; + else +#endif + lchar = '-'; + + c.c = lchar; + vtputc(c); + bp = wp->w_bufp; + + n = 1; + + sprintf(cp = tline, PICO_TITLE, version); /* write version */ + + while(c.c = *cp++){ + vtputc(c); + ++n; + } + + if(bp->b_fname[0]){ /* File name? */ + char *p, *endp, *prefix; + + prefix = NULL; /* for abreviation */ + endp = strchr(cp = bp->b_fname, '\0'); /* find eol */ + i = term.t_ncol - n - 22; /* space available */ + while(i > 0 && endp - cp > i){ + if(!prefix){ + prefix = ".../"; /* path won't fit! */ + i -= 4; + } + + if(!(p = strchr(cp, '/'))){ /* neat break? */ + cp = endp - i; /* do best we can */ + break; + } + else + cp = p + 1; + } + + sprintf(tline, "%*.sFile: %s%s", + ((i - (endp - cp)) > 0) ? (i - (endp - cp))/2 : 0, " ", + prefix ? prefix : "", cp); + + for(cp = tline; c.c = *cp; cp++, n++) + vtputc(c); + } + else{ + cp = PICO_NEWBUF_MSG; + if(sizeof(PICO_NEWBUF_MSG) < term.t_ncol){ /* enough room? */ + c.c = lchar; + for(i = (term.t_ncol-sizeof(PICO_NEWBUF_MSG))/2; n < i; n++) + vtputc(c); + } + + while(c.c = *cp++){ + vtputc(c); + ++n; + } + } + +#if WFDEBUG + vtputc(lchar); + vtputc((wp->w_flag&WFMODE)!=0 ? 'M' : lchar); + vtputc((wp->w_flag&WFHARD)!=0 ? 'H' : lchar); + vtputc((wp->w_flag&WFEDIT)!=0 ? 'E' : lchar); + vtputc((wp->w_flag&WFMOVE)!=0 ? 'V' : lchar); + vtputc((wp->w_flag&WFFORCE)!=0 ? 'F' : lchar); + n += 6; +#endif + i = term.t_ncol - n; /* space available */ + cp = NULL; + if(bp->b_flag&BFCHG){ /* "MOD" if changed. */ + cp = PICO_MOD_MSG; + i = (i > sizeof(PICO_MOD_MSG)) ? i - sizeof(PICO_MOD_MSG) : 0; + } + + c.c = lchar; + while(i-- > 0) /* Pad width */ + vtputc(c); + + if(cp) + while(c.c = *cp++) + vtputc(c); + } +} + + + +/* + * Send a command to the terminal to move the hardware cursor to row "row" + * and column "col". The row and column arguments are origin 0. Optimize out + * random calls. Update "ttrow" and "ttcol". + */ +void +movecursor(row, col) +int row, col; +{ + if (row!=ttrow || col!=ttcol) { + ttrow = row; + ttcol = col; + (*term.t_move)(row, col); + } +} + + +/* + * Erase any sense we have of the cursor's HW location... + */ +void +clearcursor() +{ + ttrow = ttcol = FARAWAY; +} + +void +get_cursor(row, col) + int *row, *col; +{ + if(row) + *row = ttrow; + if(col) + *col = ttcol; +} + + +/* + * Erase the message line. This is a special routine because the message line + * is not considered to be part of the virtual screen. It always works + * immediately; the terminal buffer is flushed via a call to the flusher. + */ +void +mlerase() +{ + if (term.t_nrow < term.t_mrow) + return; + + movecursor(term.t_nrow - term.t_mrow, 0); + (*term.t_rev)(0); + if (eolexist == TRUE) + peeol(); + else + while(++ttcol < term.t_ncol) /* track's ttcol */ + (*term.t_putchar)(' '); + + (*term.t_flush)(); + mpresf = FALSE; +} + + +/* + * Ask a yes or no question in the message line. Return either TRUE, FALSE, or + * ABORT. The ABORT status is returned if the user bumps out of the question + * with a ^G. if d >= 0, d is the default answer returned. Otherwise there + * is no default. + */ +mlyesno(prompt, dflt) +char *prompt; +int dflt; +{ + int rv; + char buf[NLINE]; + KEYMENU menu_yesno[12]; + +#ifdef _WINDOWS + if (mswin_usedialog ()) + switch (mswin_yesno (prompt)) { + default: + case 0: return (ABORT); + case 1: return (TRUE); + case 2: return (FALSE); + } +#endif + + for(rv = 0; rv < 12; rv++){ + menu_yesno[rv].name = NULL; + KS_OSDATASET(&menu_yesno[rv], KS_NONE); + } + + menu_yesno[1].name = "Y"; + menu_yesno[1].label = (dflt == TRUE) ? "[Yes]" : "Yes"; + menu_yesno[6].name = "^C"; + menu_yesno[6].label = "Cancel"; + menu_yesno[7].name = "N"; + menu_yesno[7].label = (dflt == FALSE) ? "[No]" : "No"; + wkeyhelp(menu_yesno); /* paint generic menu */ + sgarbk = TRUE; /* mark menu dirty */ + if(Pmaster && curwp) + curwp->w_flag |= WFMODE; + + sprintf(buf, "%s ? ", prompt); + mlwrite(buf, NULL); + (*term.t_rev)(1); + rv = -1; + while(1){ + switch(GetKey()){ + case (CTRL|'M') : /* default */ + if(dflt >= 0){ + pputs((dflt) ? "Yes" : "No", 1); + rv = dflt; + } + else + (*term.t_beep)(); + + break; + + case (CTRL|'C') : /* Bail out! */ + case F2 : + pputs("ABORT", 1); + rv = ABORT; + break; + + case 'y' : + case 'Y' : + case F3 : + pputs("Yes", 1); + rv = TRUE; + break; + + case 'n' : + case 'N' : + case F4 : + pputs("No", 1); + rv = FALSE; + break; + + case (CTRL|'G') : + if(term.t_mrow == 0 && km_popped == 0){ + movecursor(term.t_nrow-2, 0); + peeol(); + term.t_mrow = 2; + (*term.t_rev)(0); + wkeyhelp(menu_yesno); /* paint generic menu */ + mlwrite(buf, NULL); + (*term.t_rev)(1); + sgarbk = TRUE; /* mark menu dirty */ + km_popped++; + break; + } + /* else fall through */ + + default: + (*term.t_beep)(); + case NODATA : + break; + } + + (*term.t_flush)(); + if(rv != -1){ + (*term.t_rev)(0); + if(km_popped){ + term.t_mrow = 0; + movecursor(term.t_nrow, 0); + peeol(); + sgarbf = 1; + km_popped = 0; + } + + return(rv); + } + } +} + + + +/* + * Write a prompt into the message line, then read back a response. Keep + * track of the physical position of the cursor. If we are in a keyboard + * macro throw the prompt away, and return the remembered response. This + * lets macros run at full speed. The reply is always terminated by a carriage + * return. Handle erase, kill, and abort keys. + */ +mlreply(prompt, buf, nbuf, flg, extras) +char *prompt, *buf; +int nbuf, flg; +EXTRAKEYS *extras; +{ + return(mlreplyd(prompt, buf, nbuf, flg|QDEFLT, extras)); +} + + +/* + * function key mappings + */ +static int rfkm[12][2] = { + { F1, (CTRL|'G')}, + { F2, (CTRL|'C')}, + { F3, 0 }, + { F4, 0 }, + { F5, 0 }, + { F6, 0 }, + { F7, 0 }, + { F8, 0 }, + { F9, 0 }, + { F10, 0 }, + { F11, 0 }, + { F12, 0 } +}; + + +/* + * mlreplyd - write the prompt to the message line along with an default + * answer already typed in. Carraige return accepts the + * default. answer returned in buf which also holds the initial + * default, nbuf is it's length, def set means use default value, + * and ff means for-file which checks that all chars are allowed + * in file names. + */ +mlreplyd(prompt, buf, nbuf, flg, extras) +char *prompt; +char *buf; +int nbuf, flg; +EXTRAKEYS *extras; +{ + register int c; /* current char */ + register char *b; /* pointer in buf */ + register int i, j; + register int maxl; + register int plen; + int changed = FALSE; + int return_val = 0; + KEYMENU menu_mlreply[12]; + int extra_v[12]; + +#ifdef _WINDOWS + if (mswin_usedialog ()) { + MDlgButton btn_list[12]; + int i, j; + + memset (&btn_list, 0, sizeof (MDlgButton) * 12); + j = 0; + for (i = 0; extras && extras[i].name != NULL; ++i) { + if (extras[i].label[0] != '\0') { + if ((extras[i].key & CTRL) == CTRL) + btn_list[j].ch = (extras[i].key & ~CTRL) - '@'; + else + btn_list[j].ch = extras[i].key; + btn_list[j].rval = extras[i].key; + btn_list[j].name = extras[i].name; + btn_list[j++].label = extras[i].label; + } + } + btn_list[j].ch = -1; + + return (mswin_dialog (prompt, buf, nbuf, ((flg&QDEFLT) > 0), + FALSE, btn_list, NULL, 0)); + } +#endif + + menu_mlreply[0].name = "^G"; + menu_mlreply[0].label = "Get Help"; + KS_OSDATASET(&menu_mlreply[0], KS_SCREENHELP); + for(j = 0, i = 1; i < 6; i++){ /* insert odd extras */ + menu_mlreply[i].name = NULL; + KS_OSDATASET(&menu_mlreply[i], KS_NONE); + rfkm[2*i][1] = 0; + if(extras){ + for(; extras[j].name && j != 2*(i-1); j++) + ; + + if(extras[j].name){ + rfkm[2*i][1] = extras[j].key; + menu_mlreply[i].name = extras[j].name; + menu_mlreply[i].label = extras[j].label; + KS_OSDATASET(&menu_mlreply[i], KS_OSDATAGET(&extras[j])); + } + } + } + + menu_mlreply[6].name = "^C"; + menu_mlreply[6].label = "Cancel"; + KS_OSDATASET(&menu_mlreply[6], KS_NONE); + for(j = 0, i = 7; i < 12; i++){ /* insert even extras */ + menu_mlreply[i].name = NULL; + rfkm[2*(i-6)+1][1] = 0; + if(extras){ + for(; extras[j].name && j != (2*(i-6)) - 1; j++) + ; + + if(extras[j].name){ + rfkm[2*(i-6)+1][1] = extras[j].key; + menu_mlreply[i].name = extras[j].name; + menu_mlreply[i].label = extras[j].label; + KS_OSDATASET(&menu_mlreply[i], KS_OSDATAGET(&extras[j])); + } + } + } + + /* set up what to watch for and return values */ + memset(extra_v, 0, sizeof(extra_v)); + for(i = 0, j = 0; i < 12 && extras && extras[i].name; i++) + extra_v[j++] = extras[i].key; + + plen = mlwrite(prompt, NULL); /* paint prompt */ + if(!(flg&QDEFLT)) + *buf = '\0'; + + (*term.t_rev)(1); + + maxl = (nbuf-1 < term.t_ncol - plen - 1) ? nbuf-1 : term.t_ncol - plen - 1; + + pputs(buf, 1); + b = &buf[(flg & QBOBUF) ? 0 : strlen(buf)]; + + (*term.t_rev)(0); + wkeyhelp(menu_mlreply); /* paint generic menu */ + sgarbk = 1; /* mark menu dirty */ + (*term.t_rev)(1); + + for (;;) { + movecursor(term.t_nrow - term.t_mrow, plen + b - buf); + (*term.t_flush)(); + +#ifdef MOUSE + mouse_in_content(KEY_MOUSE, -1, -1, 0x5, 0); + register_mfunc(mouse_in_content, + term.t_nrow - term.t_mrow, plen, + term.t_nrow - term.t_mrow, plen + maxl); +#endif +#ifdef _WINDOWS + mswin_allowpaste(MSWIN_PASTE_LINE); +#endif + while((c = GetKey()) == NODATA) + ; + +#ifdef MOUSE + clear_mfunc(mouse_in_content); +#endif +#ifdef _WINDOWS + mswin_allowpaste(MSWIN_PASTE_DISABLE); +#endif + + switch(c = normalize_cmd(c, rfkm, 1)){ + case (CTRL|'A') : /* CTRL-A beginning */ + case KEY_HOME : + b = buf; + continue; + + case (CTRL|'B') : /* CTRL-B back a char */ + if(ttcol > plen) + b--; + continue; + + case (CTRL|'C') : /* CTRL-C abort */ + pputs("ABORT", 1); + ctrlg(FALSE, 0); + (*term.t_rev)(0); + (*term.t_flush)(); + return_val = ABORT; + goto ret; + + case (CTRL|'E') : /* CTRL-E end of line */ + case KEY_END : + b = &buf[strlen(buf)]; + continue; + + case (CTRL|'F') : /* CTRL-F forward a char*/ + if(*b != '\0') + b++; + continue; + + case (CTRL|'G') : /* CTRL-G help */ + if(term.t_mrow == 0 && km_popped == 0){ + movecursor(term.t_nrow-2, 0); + peeol(); + sgarbk = 1; /* mark menu dirty */ + km_popped++; + term.t_mrow = 2; + (*term.t_rev)(0); + wkeyhelp(menu_mlreply); /* paint generic menu */ + plen = mlwrite(prompt, NULL); /* paint prompt */ + (*term.t_rev)(1); + pputs(buf, 1); + break; + } + + pputs("HELP", 1); + (*term.t_rev)(0); + (*term.t_flush)(); + return_val = HELPCH; + goto ret; + + case (CTRL|'H') : /* CTRL-H backspace */ + case 0x7f : /* rubout */ + if (b <= buf) + break; + b--; + ttcol--; /* cheating! no pputc */ + (*term.t_putchar)('\b'); + + case (CTRL|'D') : /* CTRL-D delete char */ + case KEY_DEL : + changed=TRUE; + i = 0; + do /* blat out left char */ + b[i] = b[i+1]; + while(b[i++] != '\0'); + break; + + case (CTRL|'L') : /* CTRL-L redraw */ + (*term.t_rev)(0); + return_val = (CTRL|'L'); + goto ret; + + case (CTRL|'K') : /* CTRL-K kill line */ + changed=TRUE; + buf[0] = '\0'; + b = buf; + movecursor(ttrow, plen); + break; + + case KEY_LEFT: + if(ttcol > plen) + b--; + continue; + + case KEY_RIGHT: + if(*b != '\0') + b++; + continue; + + case F1 : /* sort of same thing */ + (*term.t_rev)(0); + (*term.t_flush)(); + return_val = HELPCH; + goto ret; + + case (CTRL|'M') : /* newline */ + (*term.t_rev)(0); + (*term.t_flush)(); + return_val = changed; + goto ret; + +#ifdef MOUSE + case KEY_MOUSE : + { + MOUSEPRESS mp; + + mouse_get_last (NULL, &mp); + + /* The clicked line have anything special on it? */ + switch(mp.button){ + case M_BUTTON_LEFT : /* position cursor */ + mp.col -= plen; /* normalize column */ + if(mp.col >= 0 && mp.col <= strlen(buf)) + b = buf + mp.col; + + break; + + case M_BUTTON_RIGHT : +#ifdef _WINDOWS + mswin_allowpaste(MSWIN_PASTE_LINE); + mswin_paste_popup(); + mswin_allowpaste(MSWIN_PASTE_DISABLE); + break; +#endif + + case M_BUTTON_MIDDLE : /* NO-OP for now */ + default: /* just ignore */ + break; + } + } + + continue; +#endif + + default : + if(strlen(buf) >= maxl){ /* contain the text */ + (*term.t_beep)(); + continue; + } + + /* look for match in extra_v */ + for(i = 0; i < 12; i++) + if(c && c == extra_v[i]){ + (*term.t_rev)(0); + return_val = c; + goto ret; + } + + changed=TRUE; + + if(c&(~0xff)){ /* bag ctrl/special chars */ + (*term.t_beep)(); + } + else{ + i = strlen(b); + if(flg&QFFILE){ + if(!fallowc(c)){ /* c OK in filename? */ + (*term.t_beep)(); + continue; + } + } + if(flg&QNODQT){ /* reject double quotes? */ + if(c == '"'){ + (*term.t_beep)(); + continue; + } + } + + + do /* blat out left char */ + b[i+1] = b[i]; + while(i-- > 0); + + pputc(*b++ = c, 0); + } + } + + pputs(b, 1); /* show default */ + i = term.t_ncol-1; + while(pscreen[ttrow]->v_text[i].c == ' ' + && pscreen[ttrow]->v_text[i].a == 0) + i--; + + while(ttcol <= i) + pputc(' ', 0); + } + +ret: + if(km_popped){ + term.t_mrow = 0; + movecursor(term.t_nrow, 0); + peeol(); + sgarbf = 1; + km_popped = 0; + } + + return(return_val); +} + + +/* + * emlwrite() - write the message string to the error half of the screen + * center justified. much like mlwrite (which is still used + * to paint the line for prompts and such), except it center + * the text. + */ +void +emlwrite(message, arg) +char *message; +void *arg; +{ + register char *bufp = message; + register char *ap; + register long l; + + mlerase(); + + if((l = strlen(message)) == 0 || term.t_nrow < 2) + return; /* nothing to write or no space to write, bag it */ + + /* + * next, figure out where the to move the cursor so the message + * comes out centered + */ + if((ap=(char *)strchr(message, '%')) != NULL){ + l -= 2; + switch(ap[1]){ + case '%': + case 'c': + l += arg ? 2 : 1; + break; + case 'd': + l += (long)dumbroot((int)arg, 10); + break; + case 'D': + l += (long)dumblroot((long)arg, 10); + break; + case 'o': + l += (long)dumbroot((int)arg, 8); + break; + case 'x': + l += (long)dumbroot((int)arg, 16); + break; + case 's': + l += arg ? strlen((char *)arg) : 2; + break; + } + } + + if(l+4 <= term.t_ncol) + movecursor(term.t_nrow-term.t_mrow, (term.t_ncol - ((int)l + 4))/2); + else + movecursor(term.t_nrow-term.t_mrow, 0); + + (*term.t_rev)(1); + pputs("[ ", 1); + while (*bufp != '\0' && ttcol < term.t_ncol-2){ + if(*bufp == '\007') + (*term.t_beep)(); + else if(*bufp == '%'){ + switch(*++bufp){ + case 'c': + if(arg) + pputc((char)(int)arg, 0); + else { + pputs("%c", 0); + } + break; + case 'd': + mlputi((int)arg, 10); + break; + case 'D': + mlputli((long)arg, 10); + break; + case 'o': + mlputi((int)arg, 16); + break; + case 'x': + mlputi((int)arg, 8); + break; + case 's': + pputs(arg ? (char *)arg : "%s", 0); + break; + case '%': + default: + pputc(*bufp, 0); + break; + } + } + else + pputc(*bufp, 0); + bufp++; + } + + pputs(" ]", 1); + (*term.t_rev)(0); + (*term.t_flush)(); + mpresf = TRUE; +} + + +/* + * Write a message into the message line. Keep track of the physical cursor + * position. A small class of printf like format items is handled. Assumes the + * stack grows down; this assumption is made by the "++" in the argument scan + * loop. Set the "message line" flag TRUE. + */ +mlwrite(fmt, arg) +char *fmt; +void *arg; +{ + register int c; + register char *ap; + + /* + * the idea is to only highlight if there is something to show + */ + mlerase(); + + ttcol = 0; + (*term.t_rev)(1); + ap = (char *) &arg; + while ((c = *fmt++) != 0) { + if (c != '%') { + (*term.t_putchar)(c); + ++ttcol; + } + else { + c = *fmt++; + switch (c) { + case 'd': + mlputi(*(int *)ap, 10); + ap += sizeof(int); + break; + + case 'o': + mlputi(*(int *)ap, 8); + ap += sizeof(int); + break; + + case 'x': + mlputi(*(int *)ap, 16); + ap += sizeof(int); + break; + + case 'D': + mlputli(*(long *)ap, 10); + ap += sizeof(long); + break; + + case 's': + pputs(*(char **)ap, 1); + ap += sizeof(char *); + break; + + default: + (*term.t_putchar)(c); + ++ttcol; + } + } + } + + c = ttcol; + while(ttcol < term.t_ncol) + pputc(' ', 0); + + movecursor(term.t_nrow - term.t_mrow, c); + (*term.t_rev)(0); + (*term.t_flush)(); + mpresf = TRUE; + return(c); +} + + +/* + * Write out an integer, in the specified radix. Update the physical cursor + * position. This will not handle any negative numbers; maybe it should. + */ +void +mlputi(i, r) +int i, r; +{ + register int q; + static char hexdigits[] = "0123456789ABCDEF"; + + if (i < 0){ + i = -i; + pputc('-', 1); + } + + q = i/r; + + if (q != 0) + mlputi(q, r); + + pputc(hexdigits[i%r], 1); +} + + +/* + * do the same except as a long integer. + */ +void +mlputli(l, r) +long l; +int r; +{ + register long q; + + if (l < 0){ + l = -l; + pputc('-', 1); + } + + q = l/r; + + if (q != 0) + mlputli(q, r); + + pputc((int)(l%r)+'0', 1); +} + + +/* + * scrolldown - use stuff to efficiently move blocks of text on the + * display, and update the pscreen array to reflect those + * moves... + * + * wp is the window to move in + * r is the row at which to begin scrolling + * n is the number of lines to scrol + */ +void +scrolldown(wp, r, n) +WINDOW *wp; +int r, n; +{ +#ifdef TERMCAP + register int i; + register int l; + register VIDEO *vp1; + register VIDEO *vp2; + + if(!n) + return; + + if(r < 0){ + r = wp->w_toprow; + l = wp->w_ntrows; + } + else{ + if(r > wp->w_toprow) + vscreen[r-1]->v_flag |= VFCHG; + l = wp->w_toprow+wp->w_ntrows-r; + } + + o_scrolldown(r, n); + + for(i=l-n-1; i >= 0; i--){ + vp1 = pscreen[r+i]; + vp2 = pscreen[r+i+n]; + bcopy(vp1, vp2, term.t_ncol * sizeof(CELL)); + } + pprints(r+n-1, r); + ttrow = FARAWAY; + ttcol = FARAWAY; +#endif /* TERMCAP */ +} + + +/* + * scrollup - use tcap stuff to efficiently move blocks of text on the + * display, and update the pscreen array to reflect those + * moves... + */ +void +scrollup(wp, r, n) +WINDOW *wp; +int r, n; +{ +#ifdef TERMCAP + register int i; + register VIDEO *vp1; + register VIDEO *vp2; + + if(!n) + return; + + if(r < 0) + r = wp->w_toprow; + + o_scrollup(r, n); + + i = 0; + while(1){ + if(Pmaster){ + if(!(r+i+n < wp->w_toprow+wp->w_ntrows)) + break; + } + else{ + if(!((i < wp->w_ntrows-n)&&(r+i+n < wp->w_toprow+wp->w_ntrows))) + break; + } + vp1 = pscreen[r+i+n]; + vp2 = pscreen[r+i]; + bcopy(vp1, vp2, term.t_ncol * sizeof(CELL)); + i++; + } + pprints(wp->w_toprow+wp->w_ntrows-n, wp->w_toprow+wp->w_ntrows-1); + ttrow = FARAWAY; + ttcol = FARAWAY; +#endif /* TERMCAP */ +} + + +/* + * print spaces in the physical screen starting from row abs(n) working in + * either the positive or negative direction (depending on sign of n). + */ +void +pprints(x, y) +int x, y; +{ + register int i; + register int j; + + if(x < y){ + for(i = x;i <= y; ++i){ + for(j = 0; j < term.t_ncol; j++){ + pscreen[i]->v_text[j].c = ' '; + pscreen[i]->v_text[j].a = 0; + } + } + } + else{ + for(i = x;i >= y; --i){ + for(j = 0; j < term.t_ncol; j++){ + pscreen[i]->v_text[j].c = ' '; + pscreen[i]->v_text[j].a = 0; + } + } + } + ttrow = y; + ttcol = 0; +} + + + +/* + * doton - return the physical line number that the dot is on in the + * current window, and by side effect the number of lines remaining + */ +doton(r, chs) +int *r; +unsigned *chs; +{ + register int i = 0; + register LINE *lp = curwp->w_linep; + int l = -1; + + *chs = 0; + while(i++ < curwp->w_ntrows){ + if(lp == curwp->w_dotp) + l = i-1; + lp = lforw(lp); + if(lp == curwp->w_bufp->b_linep){ + i++; + break; + } + if(l >= 0) + (*chs) += llength(lp); + } + *r = i - l - term.t_mrow; + return(l+curwp->w_toprow); +} + + + +/* + * resize_pico - given new window dimensions, allocate new resources + */ +resize_pico(row, col) +int row, col; +{ + int old_nrow, old_ncol; + register int i; + register VIDEO *vp; + + old_nrow = term.t_nrow; + old_ncol = term.t_ncol; + + term.t_nrow = row; + term.t_ncol = col; + + if (old_ncol == term.t_ncol && old_nrow == term.t_nrow) + return(TRUE); + + if(curwp){ + curwp->w_toprow = 2; + curwp->w_ntrows = term.t_nrow - curwp->w_toprow - term.t_mrow; + } + + if(Pmaster){ + fillcol = Pmaster->fillcolumn; + (*Pmaster->resize)(); + } + else if(userfillcol > 0) + fillcol = userfillcol; + else + fillcol = term.t_ncol - 6; /* we control the fill column */ + + /* + * free unused screen space ... + */ + for(i=term.t_nrow+1; i <= old_nrow; ++i){ + free((char *) vscreen[i]); + free((char *) pscreen[i]); + } + + /* + * realloc new space for screen ... + */ + if((vscreen=(VIDEO **)realloc(vscreen,(term.t_nrow+1)*sizeof(VIDEO *))) == NULL){ + if(Pmaster) + return(-1); + else + exit(1); + } + + if((pscreen=(VIDEO **)realloc(pscreen,(term.t_nrow+1)*sizeof(VIDEO *))) == NULL){ + if(Pmaster) + return(-1); + else + exit(1); + } + + for (i = 0; i <= term.t_nrow; ++i) { + if(i <= old_nrow) + vp = (VIDEO *) realloc(vscreen[i], sizeof(VIDEO)+(term.t_ncol*sizeof(CELL))); + else + vp = (VIDEO *) malloc(sizeof(VIDEO)+(term.t_ncol*sizeof(CELL))); + + if (vp == NULL) + exit(1); + vp->v_flag = VFCHG; + vscreen[i] = vp; + if(old_ncol < term.t_ncol){ /* don't let any garbage in */ + vtrow = i; + vtcol = (i < old_nrow) ? old_ncol : 0; + vteeol(); + } + + if(i <= old_nrow) + vp = (VIDEO *) realloc(pscreen[i], sizeof(VIDEO)+(term.t_ncol*sizeof(CELL))); + else + vp = (VIDEO *) malloc(sizeof(VIDEO)+(term.t_ncol*sizeof(CELL))); + + if (vp == NULL) + exit(1); + + vp->v_flag = VFCHG; + pscreen[i] = vp; + } + + if(!ResizeBrowser()){ + if(Pmaster && Pmaster->headents){ + ResizeHeader(); + } + else{ + curwp->w_flag |= (WFHARD | WFMODE); + pico_refresh(0, 1); /* redraw whole enchilada. */ + update(); /* do it */ + } + } + + return(TRUE); +} + +void +redraw_pico_for_callback() +{ + pico_refresh(0, 1); + update(); +} + + +/* + * showCompTitle - display the anchor line passed in from pine + */ +void +showCompTitle() +{ + if(Pmaster){ + register char *bufp; + extern char *pico_anchor; + COLOR_PAIR *lastc = NULL; + + if((bufp = pico_anchor) == NULL) + return; + + movecursor(COMPOSER_TITLE_LINE, 0); + if (Pmaster->colors && Pmaster->colors->tbcp && + pico_is_good_colorpair(Pmaster->colors->tbcp)){ + lastc = pico_get_cur_color(); + (void)pico_set_colorp(Pmaster->colors->tbcp, PSC_NONE); + } + else + (*term.t_rev)(1); + while (ttcol < term.t_ncol) + if(*bufp != '\0') + pputc(*bufp++, 1); + else + pputc(' ', 1); + + if (lastc){ + (void)pico_set_colorp(lastc, PSC_NONE); + free_color_pair(&lastc); + } + else + (*term.t_rev)(0); + movecursor(COMPOSER_TITLE_LINE + 1, 0); + peeol(); + } +} + + + +/* + * zotdisplay - blast malloc'd space created for display maps + */ +void +zotdisplay() +{ + register int i; + + for (i = 0; i <= term.t_nrow; ++i){ /* free screens */ + free((char *) vscreen[i]); + free((char *) pscreen[i]); + } + + free((char *) vscreen); + free((char *) pscreen); +} + + + +/* + * nlforw() - returns the number of lines from the top to the dot + */ +nlforw() +{ + register int i = 0; + register LINE *lp = curwp->w_linep; + + while(lp != curwp->w_dotp){ + lp = lforw(lp); + i++; + } + return(i); +} + + + +/* + * pputc - output the given char, keep track of it on the physical screen + * array, and keep track of the cursor + */ +void +pputc(c, a) +int c; /* char to write */ +int a; /* and its attribute */ +{ + if((ttcol >= 0 && ttcol < term.t_ncol) + && (ttrow >= 0 && ttrow <= term.t_nrow)){ + + /* + * Some terminals scroll when you write in the lower right corner + * of the screen, so don't write there. + */ + if(!(ttrow == term.t_nrow && ttcol == term.t_ncol -1)){ + (*term.t_putchar)(c); /* write it */ + pscreen[ttrow]->v_text[ttcol].c = c; /* keep track of it */ + pscreen[ttrow]->v_text[ttcol].a = a; /* keep track of it */ + } + + ttcol++; + } +} + + +/* + * pputs - print a string and keep track of the cursor + */ +void +pputs(s, a) +register char *s; /* string to write */ +register int a; /* and its attribute */ +{ + while (*s != '\0') + pputc(*s++, a); +} + + +/* + * peeol - physical screen array erase to end of the line. remember to + * track the cursor. + */ +void +peeol() +{ + register int r = ttrow; + register int c = ttcol; + CELL cl; + + cl.c = ' '; + cl.a = 0; + + /* + * Don't clear if we think we are sitting past the last column, + * that erases the last column if we just wrote it. + */ + if(c < term.t_ncol) + (*term.t_eeol)(); + + while(c < term.t_ncol && c >= 0 && r <= term.t_nrow && r >= 0) + pscreen[r]->v_text[c++] = cl; +} + + +/* + * pscr - return the character cell on the physical screen map on the + * given line, l, and offset, o. + */ +CELL * +pscr(l, o) +int l, o; +{ + if((l >= 0 && l <= term.t_nrow) && (o >= 0 && o < term.t_ncol)) + return(&(pscreen[l]->v_text[o])); + else + return(NULL); +} + + +/* + * pclear() - clear the physical screen from row x through row y + */ +void +pclear(x, y) +register int x; +register int y; +{ + register int i; + + for(i=x; i < y; i++){ + movecursor(i, 0); + peeol(); + } +} + + +/* + * dumbroot - just get close + */ +dumbroot(x, b) +int x, b; +{ + if(x < b) + return(1); + else + return(dumbroot(x/b, b) + 1); +} + + +/* + * dumblroot - just get close + */ +dumblroot(x, b) +long x; +int b; +{ + if(x < b) + return(1); + else + return(dumblroot(x/b, b) + 1); +} + + +/* + * pinsertc - use optimized insert, fixing physical screen map. + * returns true if char written, false otherwise + */ +pinsert(c) +CELL c; +{ + register int i; + register CELL *p; + + if(o_insert((int) c.c)){ /* if we've got it, use it! */ + p = pscreen[ttrow]->v_text; /* then clean up physical screen */ + for(i = term.t_ncol-1; i > ttcol; i--) + p[i] = p[i-1]; /* shift right */ + + p[ttcol++] = c; /* insert new char */ + + return(1); + } + + return(0); +} + + +/* + * pdel - use optimized delete to rub out the current char and + * fix the physical screen array. + * returns true if optimized the delete, false otherwise + */ +pdel() +{ + register int i; + register CELL *c; + + if(delchar){ /* if we've got it, use it! */ + (*term.t_putchar)('\b'); /* move left a char */ + --ttcol; + o_delete(); /* and delete it */ + + c = pscreen[ttrow]->v_text; /* then clean up physical screen */ + for(i=ttcol; i < term.t_ncol; i++) + c[i] = c[i+1]; + c[i].c = ' '; + c[i].a = 0; + + return(1); + } + + return(0); +} + + + +/* + * wstripe - write out the given string at the given location, and reverse + * video on flagged characters. Does the same thing as pine's + * stripe. + */ +void +wstripe(line, column, pmt, key) +int line, column; +char *pmt; +int key; +{ + register char *buf; + register int i = 0; + register int j = 0; + register int l; + COLOR_PAIR *lastc = NULL; + COLOR_PAIR *kncp = NULL; + COLOR_PAIR *klcp = NULL; + + if (Pmaster && Pmaster->colors){ + if(pico_is_good_colorpair(Pmaster->colors->klcp)) + klcp = Pmaster->colors->klcp; + + if(klcp && pico_is_good_colorpair(Pmaster->colors->kncp)) + kncp = Pmaster->colors->kncp; + + lastc = pico_get_cur_color(); + } + + l = strlen(pmt); + while(1){ + if(i >= term.t_ncol || j >= l) + return; /* equal strings */ + + if(pmt[j] == key) + j++; + + if (pscr(line, i) == NULL) + return; + + if(pscr(line, i)->c != pmt[j]){ + if(j >= 1 && pmt[j-1] == key) + j--; + break; + } + + j++; + i++; + } + + movecursor(line, column+i); + if(klcp) (void)pico_set_colorp(klcp, PSC_NONE); + buf = &pmt[j]; + do{ + if(*buf == key){ + buf++; + if(kncp) + (void)pico_set_colorp(kncp, PSC_NONE); + else + (void)(*term.t_rev)(1); + + pputc(*buf, 1); + if(kncp) + (void)pico_set_colorp(klcp, PSC_NONE); + else + (void)(*term.t_rev)(0); + } + else{ + pputc(*buf, 0); + } + } + while(*++buf != '\0'); + + peeol(); + if (lastc){ + (void)pico_set_colorp(lastc, PSC_NONE); + free_color_pair(&lastc); + } + (*term.t_flush)(); +} + + + +/* + * wkeyhelp - paint list of possible commands on the bottom + * of the display (yet another pine clone) + * NOTE: function key mode is handled here since all the labels + * are the same... + */ +void +wkeyhelp(keymenu) +KEYMENU *keymenu; +{ + char *obufp, *p, fkey[4]; + char linebuf[2*NLINE]; /* "2" is for space for invert tokens */ + int row, slot, tspace, adjusted_tspace, nspace[6], index, n; +#ifdef MOUSE + char nbuf[NLINE]; +#endif + +#ifdef _WINDOWS + pico_config_menu_items (keymenu); +#endif + + if(term.t_mrow == 0) + return; + + /* + * Calculate amount of space for the names column by column... + */ + for(index = 0; index < 6; index++) + if(!(gmode&MDFKEY)){ + nspace[index] = (keymenu[index].name) + ? strlen(keymenu[index].name) : 0; + if(keymenu[index+6].name + && (n = strlen(keymenu[index+6].name)) > nspace[index]) + nspace[index] = n; + + nspace[index]++; + } + else + nspace[index] = (index < 4) ? 3 : 4; + + tspace = term.t_ncol/6; /* total space for each item */ + /* + * Avoid writing in bottom right corner so we won't scroll screens that + * scroll when you do that. The way this is setup, we won't do that + * unless the number of columns is evenly divisible by 6. + */ + adjusted_tspace = (6 * tspace == term.t_ncol) ? tspace - 1 : tspace; + + index = 0; + for(row = 0; row <= 1; row++){ + linebuf[0] = '\0'; + obufp = &linebuf[0]; + for(slot = 0; slot < 6; slot++){ + if(keymenu[index].name && keymenu[index].label){ + if(gmode&MDFKEY){ + p = fkey; + sprintf(fkey, "F%d", (2 * slot) + row + 1); + } + else + p = keymenu[index].name; +#ifdef MOUSE + sprintf(nbuf, "%.*s %s", nspace[slot], p, + keymenu[index].label); + register_key(index, + (gmode&MDFKEY) ? F1 + (2 * slot) + row: + (keymenu[index].name[0] == '^') + ? (CTRL | keymenu[index].name[1]) + : (keymenu[index].name[0] == 'S' + && !strcmp(keymenu[index].name, "Spc")) + ? ' ' + : keymenu[index].name[0], + nbuf, invert_label, + term.t_nrow - 1 + row, (slot * tspace), + strlen(nbuf), + (Pmaster && Pmaster->colors) + ? Pmaster->colors->kncp: NULL, + (Pmaster && Pmaster->colors) + ? Pmaster->colors->klcp: NULL); +#endif + + n = nspace[slot]; + while(p && *p && n--){ + *obufp++ = '~'; /* insert "invert" token */ + *obufp++ = *p++; + } + + while(n-- > 0) + *obufp++ = ' '; + + p = keymenu[index].label; + n = ((slot == 5 && row == 1) ? adjusted_tspace + : tspace) - nspace[slot]; + while(p && *p && n-- > 0) + *obufp++ = *p++; + + while(n-- > 0) + *obufp++ = ' '; + } + else{ + n = (slot == 5 && row == 1) ? adjusted_tspace : tspace; + while(n--) + *obufp++ = ' '; + +#ifdef MOUSE + register_key(index, NODATA, "", NULL, 0, 0, 0, NULL, NULL); +#endif + } + + *obufp = '\0'; + index++; + } + + wstripe(term.t_nrow - 1 + row, 0, linebuf, '~'); + } +} diff --git a/ebind.h b/ebind.h new file mode 100644 index 0000000..39b764b --- /dev/null +++ b/ebind.h @@ -0,0 +1,165 @@ +/* + * $Id: ebind.h 13654 2004-05-07 21:43:40Z jpf $ + * + * Program: Default key bindings + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + * + * NOTES: + * + * This files describes the key bindings for pico and the pine + * composer. The binds are static, (i.e., no way for the user + * to change them) so as to keep pico/composer as simple to use + * as possible. This, of course, means the number of functions is + * greatly reduced, but, then again, this is seen as very desirable. + * + * There are very limited number of flat ctrl-key bindings left, and + * most of them are slated for yet-to-be implemented functions, like + * invoking an alternate editor in the composer and necessary funcs + * for imlementing attachment handling. We really want to avoid + * going to multiple keystroke functions. -mss + * + */ + +/* EBIND: Initial default key to function bindings for + MicroEMACS 3.2 + + written by Dave G. Conroy + modified by Steve Wilhite, George Jones + greatly modified by Daniel Lawrence +*/ + +#ifndef EBIND_H +#define EBIND_H + + +/* + * Command table. + * This table is *roughly* in ASCII order, left to right across the + * characters of the command. This expains the funny location of the + * control-X commands. + */ +KEYTAB keytab[NBINDS] = { + {KEY_UP, backline}, + {KEY_DOWN, forwline}, + {KEY_RIGHT, forwchar}, + {KEY_LEFT, backchar}, + {KEY_PGUP, backpage}, + {KEY_PGDN, forwpage}, + {KEY_HOME, gotobol}, + {KEY_END, gotoeol}, + {KEY_DEL, forwdel}, +#ifdef MOUSE + {KEY_MOUSE, mousepress}, +#endif + {CTRL|'A', gotobol}, + {CTRL|'B', backchar}, + {CTRL|'C', abort_composer}, + {CTRL|'D', forwdel}, + {CTRL|'E', gotoeol}, + {CTRL|'F', forwchar}, + {CTRL|'G', whelp}, + {CTRL|'H', backdel}, + {CTRL|'I', tab}, + {CTRL|'J', fillpara}, + {CTRL|'K', killregion}, + {CTRL|'L', pico_refresh}, + {CTRL|'M', newline}, + {CTRL|'N', forwline}, + {CTRL|'O', suspend_composer}, + {CTRL|'P', backline}, + {CTRL|'R', insfile}, +#ifdef SPELLER + {CTRL|'T', spell}, +#endif /* SPELLER */ + {CTRL|'U', yank}, + {CTRL|'V', forwpage}, + {CTRL|'W', forwsearch}, + {CTRL|'X', wquit}, + {CTRL|'Y', backpage}, +#ifdef JOB_CONTROL + {CTRL|'Z', bktoshell}, +#endif + {CTRL|'@', forwword}, + {CTRL|'^', setmark}, + {CTRL|'_', alt_editor}, + {0x7F, backdel}, + {0, NULL} +}; + + +/* + * Command table. + * This table is *roughly* in ASCII order, left to right across the + * characters of the command. This expains the funny location of the + * control-X commands. + */ +KEYTAB pkeytab[NBINDS] = { + {KEY_UP, backline}, + {KEY_DOWN, forwline}, + {KEY_RIGHT, forwchar}, + {KEY_LEFT, backchar}, + {KEY_PGUP, backpage}, + {KEY_PGDN, forwpage}, + {KEY_HOME, gotobol}, + {KEY_END, gotoeol}, + {KEY_DEL, forwdel}, +#ifdef MOUSE + {KEY_MOUSE, mousepress}, +#endif + {CTRL|'A', gotobol}, + {CTRL|'B', backchar}, + {CTRL|'C', showcpos}, + {CTRL|'D', forwdel}, + {CTRL|'E', gotoeol}, + {CTRL|'F', forwchar}, + {CTRL|'G', whelp}, + {CTRL|'H', backdel}, + {CTRL|'I', tab}, + {CTRL|'J', fillpara}, + {CTRL|'K', killregion}, + {CTRL|'L', pico_refresh}, + {CTRL|'M', newline}, + {CTRL|'N', forwline}, + {CTRL|'O', filewrite}, + {CTRL|'P', backline}, + {CTRL|'R', insfile}, +#ifdef SPELLER + {CTRL|'T', spell}, +#endif /* SPELLER */ + {CTRL|'U', yank}, + {CTRL|'V', forwpage}, + {CTRL|'W', forwsearch}, + {CTRL|'X', wquit}, + {CTRL|'Y', backpage}, +#ifdef JOB_CONTROL + {CTRL|'Z', bktoshell}, +#endif + {CTRL|'@', forwword}, + {CTRL|'^', setmark}, + {0x7F, backdel}, + {0, NULL} +}; + +#endif /* EBIND_H */ diff --git a/edef.h b/edef.h new file mode 100644 index 0000000..5530ed5 --- /dev/null +++ b/edef.h @@ -0,0 +1,181 @@ +/* + * $Id: edef.h 13816 2004-10-14 01:27:01Z hubert $ + * + * Program: Global definitions and initializations + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* EDEF: Global variable definitions for + MicroEMACS 3.2 + + written by Dave G. Conroy + modified by Steve Wilhite, George Jones + greatly modified by Daniel Lawrence +*/ + +#ifndef EDEF_H +#define EDEF_H + +#ifdef maindef + +/* for MAIN.C */ + +/* initialized global definitions */ + +int fillcol = 72; /* Current fill column */ +int userfillcol = -1; /* Fillcol set from cmd line */ +char pat[NPAT]; /* Search pattern */ +char rpat[NPAT]; /* Replace pattern */ +int eolexist = TRUE; /* does clear to EOL exist */ +int optimize = FALSE; /* optimize flag(cf line speed) */ +int scrollexist = TRUE; /* does insert line exist */ +int inschar = TRUE; /* does insert character exist */ +int delchar = TRUE; /* does delete character exist */ +int sgarbk = TRUE; /* TRUE if keyhelp garbaged */ +int sup_keyhelp = FALSE; /* TRUE if keyhelp is suppressed*/ +int mline_open = FALSE; /* TRUE if message line is open */ +int ComposerTopLine = 2; /* TRUE if message line is open */ +int ComposerEditing = FALSE; /* TRUE if message line is open */ +int revexist = FALSE; /* does reverse video exist? */ +char modecode[] = "WCSEVO"; /* letters to represent modes */ +long gmode = MDWRAP; /* global editor mode */ +int sgarbf = TRUE; /* TRUE if screen is garbage */ +int mpresf = FALSE; /* TRUE if message in last line */ +int clexec = FALSE; /* command line execution flag */ +char *alt_speller = NULL; /* alt spell checking command */ +int preserve_start_stop = FALSE; /* TRUE if pass ^S/^Q to term */ +char *glo_quote_str = NULL; /* points to quote string if set*/ + +/* uninitialized global definitions */ +int currow; /* Cursor row */ +int curcol; /* Cursor column */ +int thisflag; /* Flags, this command */ +int lastflag; /* Flags, last command */ +int curgoal; /* Goal for C-P, C-N */ +char opertree[NLINE+1]; /* operate within this tree */ +char browse_dir[NLINE+1]; /* directory of last browse (cwd) */ +char glo_quote_str_buf[NLINE+1]; /* Indent string (for justify) */ +WINDOW *curwp; /* Current window */ +BUFFER *curbp; /* Current buffer */ +WINDOW *wheadp; /* Head of list of windows */ +BUFFER *bheadp; /* Head of list of buffers */ +BUFFER *blistp; /* Buffer for C-X C-B */ + +BUFFER *bfind PROTO((char *, int, int)); /* Lookup a buffer by name */ +LINE *lalloc PROTO((int)); /* Allocate a line */ +int km_popped; /* menu popped up */ +int panicking; /* we are currently panicking */ +#if defined(USE_TERMCAP) || defined(USE_TERMINFO) || defined(VMS) +KBESC_T *kbesc; /* keyboard esc sequence trie */ +#endif /* USE_TERMCAP/USE_TERMINFO/VMS */ + +#else /* maindef */ + +/* for all the other .C files */ + +/* initialized global external declarations */ + +extern int fillcol; /* Fill column */ +extern int userfillcol; /* Fillcol set from cmd line */ +extern char pat[]; /* Search pattern */ +extern char rpat[]; /* Replace pattern */ +extern int eolexist; /* does clear to EOL exist? */ +extern int optimize; /* optimize flag(cf line speed) */ +extern int scrollexist; /* does insert line exist */ +extern int inschar; /* does insert character exist */ +extern int delchar; /* does delete character exist */ +extern int sgarbk; +extern int sup_keyhelp; +extern int mline_open; /* Message line is open */ +extern int ComposerTopLine; /* TRUE if message line is open */ +extern int ComposerEditing; /* TRUE if message line is open */ +extern int timeo; /* how long we wait in GetKey */ +extern time_t time_of_last_input; /* Last keyboard activity */ +extern int revexist; /* does reverse video exist? */ +extern char modecode[]; /* letters to represent modes */ +extern KEYTAB keytab[]; /* key bind to functions table */ +extern KEYTAB pkeytab[]; /* pico's function table */ +extern long gmode; /* global editor mode */ +extern int sgarbf; /* State of screen unknown */ +extern int mpresf; /* Stuff in message line */ +extern int clexec; /* command line execution flag */ +extern char *alt_speller; /* alt spell checking command */ +extern int preserve_start_stop; /* TRUE if pass ^S/^Q to term */ +extern char *glo_quote_str; /* points to quote string if set*/ +/* initialized global external declarations */ +extern int currow; /* Cursor row */ +extern int curcol; /* Cursor column */ +extern int thisflag; /* Flags, this command */ +extern int lastflag; /* Flags, last command */ +extern int curgoal; /* Goal for C-P, C-N */ +extern char opertree[]; /* operate within this tree */ +extern char browse_dir[]; /* operate within this tree */ +extern char glo_quote_str_buf[]; /* Indent string (for justify) */ +extern WINDOW *curwp; /* Current window */ +extern BUFFER *curbp; /* Current buffer */ +extern WINDOW *wheadp; /* Head of list of windows */ +extern BUFFER *bheadp; /* Head of list of buffers */ +extern BUFFER *blistp; /* Buffer for C-X C-B */ + +extern BUFFER *bfind PROTO((char *, int, int)); /* Lookup a buffer by name */ +extern LINE *lalloc PROTO((int)); /* Allocate a line */ +extern int km_popped; /* menu popped up */ +extern int panicking; /* we are currently panicking */ +/* + * This is a weird one. It has to be defined differently for pico and for + * pine. It seems to need to be defined at startup as opposed to set later. + * It doesn't work to set it later in pico. When pico is used with a + * screen reader it seems to jump to the cursor every time through the + * mswin_charavail() loop in GetKey, and the timeout is this long. So we + * just need to set it higher than we do in pine. If we understood this + * we would probably see that we don't need any timer at all in pico, but + * we don't remember why it is here so we'd better leave it. + * + * This is defined in .../pico/main.c and in .../pine/pine.c. + */ +extern int my_timer_period; /* here so can be set */ +#ifdef MOUSE +extern MENUITEM menuitems[]; /* key labels and functions */ +extern MENUITEM *mfunc; /* single generic function */ +extern mousehandler_t mtrack; /* func used to track the mouse */ +#endif /* MOUSE */ + +#if defined(USE_TERMCAP) || defined(USE_TERMINFO) || defined(VMS) +extern KBESC_T *kbesc; /* keyboard esc sequence trie */ +#endif /* USE_TERMCAP/USE_TERMINFO/VMS */ + +#endif /* maindef */ + +/* terminal table defined only in TERM.C */ + +#ifndef termdef +#if defined(VMS) && !defined(__ALPHA) +globalref +#else +extern +#endif /* VMS */ + TERM term; /* Terminal information. */ +#endif /* termdef */ + +#endif /* EDEF_H */ diff --git a/efunc.h b/efunc.h new file mode 100644 index 0000000..01af99d --- /dev/null +++ b/efunc.h @@ -0,0 +1,342 @@ +/* + * $Id: efunc.h 13711 2004-06-15 22:22:35Z hubert $ + * + * Program: Pine's composer and pico's function declarations + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* EFUNC.H: MicroEMACS function declarations and names + + This file list all the C code functions used by MicroEMACS + and the names to use to bind keys to them. To add functions, + declare it here in both the extern function list and the name + binding table. + + Update History: + + Daniel Lawrence +*/ + +#ifndef EFUNC_H +#define EFUNC_H + + +/* External function declarations */ +/* attach.c */ +extern int AskAttach PROTO((char *, LMLIST **)); +extern int SyncAttach PROTO((void)); +extern int intag PROTO((char *, int)); +extern char *prettysz PROTO((off_t)); +extern int AttachError PROTO((void)); +extern char *QuoteAttach PROTO((char *)); + +/* basic.c */ +extern int gotobol PROTO((int, int)); +extern int backchar PROTO((int, int)); +extern int gotoeol PROTO((int, int)); +extern int forwchar PROTO((int, int)); +extern int gotoline PROTO((int, int)); +extern int gotobob PROTO((int, int)); +extern int gotoeob PROTO((int, int)); +extern int forwline PROTO((int, int)); +extern int backline PROTO((int, int)); +extern int gotobop PROTO((int, int)); +extern int gotoeop PROTO((int, int)); +extern int forwpage PROTO((int, int)); +extern int backpage PROTO((int, int)); +extern int scrollupline PROTO((int, int)); +extern int scrolldownline PROTO((int, int)); +extern int scrollto PROTO((int, int)); +extern int setmark PROTO((int, int)); +extern int swapmark PROTO((int, int)); +extern int setimark PROTO((int, int)); +extern int swapimark PROTO((int, int)); +extern int mousepress PROTO((int, int)); + +/* bind.c */ +extern int whelp PROTO((int, int)); +extern int wscrollw PROTO((int, int, char **, int)); +extern int normal PROTO((int, int (*)[2], int)); +extern void rebindfunc PROTO((int (*)(int, int),int (*)(int, int))); +extern int bindtokey PROTO((int c, int (*) PROTO((int, int)))); + +/* browse.c */ +extern int FileBrowse PROTO((char *, int, char *, int, char *, int, + LMLIST **)); +extern int ResizeBrowser PROTO((void)); +extern void set_browser_title PROTO((char *)); +extern void zotlmlist PROTO((LMLIST *)); + +/* buffer.c */ +extern int anycb PROTO((void)); +extern struct BUFFER *bfind PROTO((char *, int, int)); +extern int bclear PROTO((struct BUFFER *)); +extern int packbuf PROTO((char **, int *, int)); +extern void readbuf PROTO((char **)); + +/* composer.c */ +extern int InitMailHeader PROTO((struct pico_struct *)); +extern int ResizeHeader PROTO((void)); +extern int HeaderEditor PROTO((int, int)); +extern void PaintHeader PROTO((int, int)); +extern void ArrangeHeader PROTO((void)); +extern int ToggleHeader PROTO((int)); +extern int HeaderLen PROTO((void)); +extern int UpdateHeader PROTO((int)); +extern int entry_line PROTO((int, int)); +extern int call_builder PROTO((struct headerentry *, int *, char **)); +extern void call_expander PROTO((void)); +extern void ShowPrompt PROTO((void)); +extern int packheader PROTO((void)); +extern void zotheader PROTO((void)); +extern void display_for_send PROTO((void)); +extern VARS_TO_SAVE *save_pico_state PROTO((void)); +extern void restore_pico_state PROTO((VARS_TO_SAVE *)); +extern void free_pico_state PROTO((VARS_TO_SAVE *)); +extern void HeaderPaintCursor PROTO((void)); +extern void PaintBody PROTO((int)); + +/* display.c */ +extern int vtinit PROTO((void)); +extern int vtterminalinfo PROTO((int)); +extern void vttidy PROTO((void)); +extern void update PROTO((void)); +extern void modeline PROTO((struct WINDOW *)); +extern void movecursor PROTO((int, int)); +extern void clearcursor PROTO((void)); +extern void mlerase PROTO((void)); +extern int mlyesno PROTO((char *, int)); +extern int mlreply PROTO((char *, char *, int, int, EXTRAKEYS *)); +extern int mlreplyd PROTO((char *, char *, int, int, EXTRAKEYS *)); +extern void emlwrite PROTO((char *, void *)); +extern int mlwrite PROTO((char *, void *)); +extern void scrolldown PROTO((struct WINDOW *, int, int)); +extern void scrollup PROTO((struct WINDOW *, int, int)); +extern int doton PROTO((int *, unsigned int *)); +extern int resize_pico PROTO((int, int)); +extern void zotdisplay PROTO((void)); +extern void pputc PROTO((int, int)); +extern void pputs PROTO((char *, int)); +extern void peeol PROTO((void)); +extern CELL *pscr PROTO((int, int)); +extern void pclear PROTO((int, int)); +extern int pinsert PROTO((CELL)); +extern int pdel PROTO((void)); +extern void wstripe PROTO((int, int, char *, int)); +extern void wkeyhelp PROTO((KEYMENU *)); +extern void get_cursor PROTO((int *, int *)); + +/* file.c */ +extern int fileread PROTO((int, int)); +extern int insfile PROTO((int, int)); +extern int readin PROTO((char *, int, int)); +extern int filewrite PROTO((int, int)); +extern int filesave PROTO((int, int)); +extern int writeout PROTO((char *, int)); +extern char *writetmp PROTO((int, char *)); +extern int filename PROTO((int, int)); +extern int in_oper_tree PROTO((char *)); + +/* fileio.c */ +extern int ffropen PROTO((char *)); +extern int ffputline PROTO((CELL *, int)); +extern int ffgetline PROTO((char *, int, int *, int)); + +/* line.c */ +extern struct LINE *lalloc PROTO((int)); +extern void lfree PROTO((struct LINE *)); +extern void lchange PROTO((int)); +extern int linsert PROTO((int, int)); +extern int geninsert PROTO((LINE **, int *, LINE *, int, int, int, long *)); +extern int lnewline PROTO((void)); +extern int ldelete PROTO((long, int (*) PROTO((int)))); +extern int lisblank PROTO((struct LINE *)); +extern void kdelete PROTO((void)); +extern int kinsert PROTO((int)); +extern int kremove PROTO((int)); +extern int ksize PROTO((void)); +extern void fdelete PROTO((void)); +extern int finsert PROTO((int)); +extern int fremove PROTO((int)); + +/* os.c */ +extern int Raw PROTO((int)); +extern void StartInverse PROTO((void)); +extern void EndInverse PROTO((void)); +extern int InverseState PROTO((void)); +extern int StartBold PROTO((void)); +extern void EndBold PROTO((void)); +extern void StartUnderline PROTO((void)); +extern void EndUnderline PROTO((void)); +extern void xonxoff_proc PROTO((int)); +extern void crlf_proc PROTO((int)); +extern void intr_proc PROTO((int)); +extern void flush_input PROTO((void)); +extern void bit_strip_off PROTO((void)); +extern void quit_char_off PROTO((void)); +extern int ttisslow PROTO((void)); +extern int input_ready PROTO((int)); +extern int read_one_char PROTO((void)); +extern SigType (*posix_signal PROTO((int, SigType (*)())))(); +extern int posix_sigunblock PROTO((int)); +extern int ttopen PROTO((void)); +extern void ttresize PROTO((void)); +extern int ttclose PROTO((void)); +extern int ttputc PROTO((int)); +extern int ttflush PROTO((void)); +extern int ttgetc PROTO((int, int (*)(), void (*)())); +extern int simple_ttgetc PROTO((int (*)(), void (*)())); +extern void ttgetwinsz PROTO((int *, int *)); +extern int GetKey PROTO((void)); +extern int alt_editor PROTO((int, int)); +extern void picosigs PROTO((void)); +#ifdef JOB_CONTROL +extern int bktoshell PROTO((void)); +#endif +extern int fallowc PROTO((int)); +extern int fexist PROTO((char *, char *, off_t *)); +extern int isdir PROTO((char *, long *, time_t *)); +extern int can_access PROTO((char *, int)); +extern char *gethomedir PROTO((int *)); +extern int homeless PROTO((char *)); +extern char *errstr PROTO((int)); +extern char *getfnames PROTO((char *, char *, int *, char *)); +extern void fioperr PROTO((int, char *)); +extern void fixpath PROTO((char *, size_t)); +extern char *pfnexpand PROTO((char *, size_t)); +extern int compresspath PROTO((char *, char *, int)); +extern void tmpname PROTO((char *, char *)); +extern char *temp_nam PROTO((char *, char *)); +extern char *temp_nam_ext PROTO((char *, char *, char *)); +extern void makename PROTO((char *, char *)); +extern int copy PROTO((char *, char *)); +extern int ffwopen PROTO((char *, int)); +extern int ffclose PROTO((void)); +extern int ffelbowroom PROTO((void)); +extern FILE *P_open PROTO((char *)); +extern void P_close PROTO((FILE *)); +extern int worthit PROTO((int *)); +extern int o_insert PROTO((int)); +extern int o_delete PROTO((void)); +extern int pico_new_mail PROTO((void)); +extern int time_to_check PROTO((void)); +extern int sstrcasecmp PROTO((const QSType *, const QSType *)); +extern int strucmp PROTO((char *, char *)); +extern int struncmp PROTO((char *, char *, int)); +extern void chkptinit PROTO((char *, int)); +extern void set_collation PROTO((int, int)); +extern int (*pcollator)(); +extern COLOR_PAIR *new_color_pair PROTO((char *, char *)); +extern COLOR_PAIR *pico_get_cur_color PROTO((void)); +extern COLOR_PAIR *pico_get_rev_color PROTO((void)); +extern COLOR_PAIR *pico_get_normal_color PROTO((void)); +extern void free_color_pair PROTO((COLOR_PAIR **)); +extern void pico_nfcolor PROTO((char *)); +extern void pico_nbcolor PROTO((char *)); +extern void pico_rfcolor PROTO((char *)); +extern void pico_rbcolor PROTO((char *)); +extern int pico_set_fg_color PROTO((char *)); +extern int pico_set_bg_color PROTO((char *)); +extern COLOR_PAIR *pico_set_colorp PROTO((COLOR_PAIR *, int)); +extern COLOR_PAIR *pico_set_colors PROTO((char *, char *, int)); +extern int pico_is_good_color PROTO((char *)); +extern int pico_is_good_colorpair PROTO((COLOR_PAIR *)); +extern void pico_set_nfg_color PROTO((void)); +extern void pico_set_nbg_color PROTO((void)); +extern void pico_set_normal_color PROTO((void)); +extern int pico_usingcolor PROTO((void)); +extern char *color_to_asciirgb PROTO((char *)); +extern char *colorx PROTO((int)); +extern char *color_to_canonical_name PROTO((char *)); +extern int pico_count_in_color_table PROTO((void)); +/* these color functions aren't needed for Windows */ +extern int pico_hascolor PROTO((void)); +extern void pico_toggle_color PROTO((int)); +extern unsigned pico_get_color_options PROTO((void)); +extern void pico_set_color_options PROTO((unsigned)); +extern void pico_endcolor PROTO((void)); +extern char *pico_get_last_fg_color PROTO((void)); +extern char *pico_get_last_bg_color PROTO((void)); +#ifdef MOUSE +extern unsigned long pico_mouse PROTO((unsigned, int, int)); +#endif + +/* pico.c */ +extern int pico PROTO((struct pico_struct *)); +extern void edinit PROTO((char *)); +extern int execute PROTO((int, int, int)); +extern int quickexit PROTO((int, int)); +extern int abort_composer PROTO((int, int)); +extern int suspend_composer PROTO((int, int)); +extern int wquit PROTO((int, int)); +extern int ctrlg PROTO((int, int)); +extern int rdonly PROTO((void)); +extern int pico_help PROTO((char **, char *, int)); +extern void zotedit PROTO((void)); +#ifdef _WINDOWS +int composer_file_drop PROTO((int, int, char *)); +int pico_cursor PROTO((int, long)); +#endif + +/* random.c */ +extern int showcpos PROTO((int, int)); +extern int tab PROTO((int, int)); +extern int newline PROTO((int, int)); +extern int forwdel PROTO((int, int)); +extern int backdel PROTO((int, int)); +extern int killtext PROTO((int, int)); +extern int yank PROTO((int, int)); +extern COLOR_PAIR *pico_apply_rev_color PROTO((COLOR_PAIR *, int)); + +/* region.c */ +extern int killregion PROTO((int, int)); +extern int deleteregion PROTO((int, int)); +extern int markregion PROTO((int)); +extern void unmarkbuffer PROTO((void)); + +/* search.c */ +extern int forwsearch PROTO((int, int)); +extern int readpattern PROTO((char *, int)); +extern int forscan PROTO((int *, char *, LINE *, int, int)); +extern void chword PROTO((char *, char *)); + +/* spell.c */ +#ifdef SPELLER +extern int spell PROTO((int, int)); +#endif + +/* window.c */ +extern int pico_refresh PROTO((int, int)); +extern void redraw_pico_for_callback(); + +/* word.c */ +extern int wrapword PROTO((void)); +extern int backword PROTO((int, int)); +extern int forwword PROTO((int, int)); +extern int fillpara PROTO((int, int)); +extern int fillbuf PROTO((int, int)); +extern int inword PROTO((void)); +extern int quote_match PROTO((char *, LINE *, char *, int)); + +#endif /* EFUNC_H */ diff --git a/estruct.h b/estruct.h new file mode 100644 index 0000000..c7a04f6 --- /dev/null +++ b/estruct.h @@ -0,0 +1,439 @@ +/* + * $Id: estruct.h 13888 2004-12-01 00:37:37Z hubert $ + * + * Program: Struct and preprocessor definitions + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* ESTRUCT: Structure and preprocesser defined for + MicroEMACS 3.6 + + written by Dave G. Conroy + modified by Steve Wilhite, George Jones + greatly modified by Daniel Lawrence +*/ + +#ifndef ESTRUCT_H +#define ESTRUCT_H + +/* Configuration options */ + +#define CVMVAS 1 /* arguments to page forward/back in pages */ +#define NFWORD 1 /* forward word jumps to begining of word */ +#define TYPEAH 0 /* type ahead causes update to be skipped */ +#define REVSTA 1 /* Status line appears in reverse video */ + + +/* internal constants */ + +#define NBINDS 50 /* max # of bound keys */ +#ifdef MAXPATHLEN +#define NFILEN MAXPATHLEN /* # of bytes, file name */ +#else +#define NFILEN 80 /* # of bytes, file name */ +#endif +#define NBUFN 16 /* # of bytes, buffer name */ +#define NLINE 256 /* # of bytes, line */ +#define NSTRING 256 /* # of bytes, string buffers */ +#define NPAT 80 /* # of bytes, pattern */ +#define FARAWAY 1000 /* Huge number */ +#define NLOCKS 100 /* max # of file locks active */ + +#define AGRAVE 0x60 /* M- prefix, Grave (LK201) */ +#define METACH 0x1B /* M- prefix, Control-[, ESC */ +#define CTMECH 0x1C /* C-M- prefix, Control-\ */ +#define EXITCH 0x1D /* Exit level, Control-] */ +#define CTRLCH 0x1E /* C- prefix, Control-^ */ +#define HELPCH 0x1F /* Help key, Control-_ */ + +#undef CTRL +#define CTRL 0x0100 /* Control flag, or'ed in */ +#define META 0x0200 /* Meta flag, or'ed in */ +#define CTLX 0x0400 /* ^X flag, or'ed in */ +#define SPEC 0x0800 /* special key (arrow's, etc) */ +#define FUNC 0x1000 /* special key (function keys) */ +#if defined(DOS) || defined(OS2) +#define MENU 0x2000 /* Menu command */ +#define ALTD 0x4000 /* ALT key... */ +#endif + +#define QNORML 0x0000 /* Flag meaning no flag ;) */ +#define QFFILE 0x0001 /* Flag buffer for file neme */ +#define QDEFLT 0x0002 /* Flag to use default answer */ +#define QBOBUF 0x0004 /* Start with cursor at BOL */ +#define QNODQT 0x0008 /* Don't accept double quotes */ + +#undef FALSE +#define FALSE 0 /* False, no, bad, etc. */ +#undef TRUE +#define TRUE 1 /* True, yes, good, etc. */ +#define ABORT 2 /* Death, ^G, abort, etc. */ + +#define FIOSUC 0 /* File I/O, success. */ +#define FIOFNF 1 /* File I/O, file not found. */ +#define FIOEOF 2 /* File I/O, end of file. */ +#define FIOERR 3 /* File I/O, error. */ +#define FIOLNG 4 /*line longer than allowed len */ +#define FIODIR 5 /* File is a directory */ +#define FIONWT 6 /* File lacks write permission */ +#define FIONRD 7 /* File lacks read permission */ +#define FIONEX 8 /* File lacks exec permission */ +#define FIOSYM 9 /* File is a symbolic link */ +#define FIOPER 10 /* Generic permission denied */ + + +/* for can_access (access) function */ +#define EXECUTE_ACCESS 01 /* These five are */ +#define WRITE_ACCESS 02 /* for the calls */ +#define READ_ACCESS 04 /* to access() */ +#define ACCESS_EXISTS 00 /* */ +#define EDIT_ACCESS 06 /* (this is r+w access) */ +#define OWNER_ONLY 010 /* open with mode 0600 */ + + +#define CFCPCN 0x0001 /* Last command was C-P, C-N */ +#define CFKILL 0x0002 /* Last command was a kill */ +#define CFFILL 0x0004 /* Last command was a kill */ +#define CFSRCH 0x0008 /* Last command was WhereIs */ +#define CFFLBF 0x0010 /* Last cmd was full buf fill */ + +#define BACKSPACE '\b' /* backspace character */ +#define TAB '\t' /* tab character */ +#define RETURN '\r' /* carriage return char */ +#define LINE_FEED '\n' /* line feed character */ +#define FORMFEED '\f' /* form feed (^L) char */ +#define COMMA ',' /* comma character */ +#define SPACE ' ' /* space character */ +#define ESCAPE '\033' /* the escape */ +#define BELL '\007' /* the bell */ +#define LPAREN '(' /* left parenthesis */ +#define RPAREN ')' /* right parenthesis */ +#define BSLASH '\\' /* back slash */ +#define QUOTE '"' /* double quote char */ +#define DEL '\177' /* delete */ + + +/* + * macros to help filter character input + */ +#define LOBIT_CHAR(C) ((C) > 0x1f && (C) < 0x7f) +#define HIBIT_CHAR(C) ((C) > 0x7f && (C) <= 0xff) +#define HIBIT_OK(C) (!(gmode & MDHBTIGN)) +#define VALID_KEY(C) (LOBIT_CHAR(C) || (HIBIT_OK(C) && HIBIT_CHAR(C))) +#define ctrl(c) ((c) & 0x1f) /* control character mapping */ + +#define STDIN_FD 0 +#define STDOUT_FD 1 +#define STDERR_FD 2 + + +/* + * Placeholders for keymenu tags used in some ports (well, only in the + * windows port for now) to turn on commands in the Menu Bar. + */ +#ifndef KS_OSDATAVAR +#define KS_OSDATAVAR +#define KS_OSDATAGET(X) +#define KS_OSDATASET(X, Y) + +#define KS_NONE +#define KS_VIEW +#define KS_EXPUNGE +#define KS_ZOOM +#define KS_SORT +#define KS_HDRMODE +#define KS_MAINMENU +#define KS_FLDRLIST +#define KS_FLDRINDEX +#define KS_COMPOSER +#define KS_PREVPAGE +#define KS_PREVMSG +#define KS_NEXTMSG +#define KS_ADDRBOOK +#define KS_WHEREIS +#define KS_PRINT +#define KS_REPLY +#define KS_FORWARD +#define KS_BOUNCE +#define KS_DELETE +#define KS_UNDELETE +#define KS_FLAG +#define KS_SAVE +#define KS_EXPORT +#define KS_TAKEADDR +#define KS_SELECT +#define KS_APPLY +#define KS_POSTPONE +#define KS_SEND +#define KS_CANCEL +#define KS_ATTACH +#define KS_TOADDRBOOK +#define KS_READFILE +#define KS_JUSTIFY +#define KS_ALTEDITOR +#define KS_GENERALHELP +#define KS_SCREENHELP +#define KS_EXIT +#define KS_NEXTPAGE +#define KS_SAVEFILE +#define KS_CURPOSITION +#define KS_GOTOFLDR +#define KS_JUMPTOMSG +#define KS_RICHHDR +#define KS_EXITMODE +#define KS_REVIEW +#define KS_KEYMENU +#define KS_SELECTCUR +#define KS_UNDO +#define KS_SPELLCHK +#endif + + +/* + * There is a window structure allocated for every active display window. The + * windows are kept in a big list, in top to bottom screen order, with the + * listhead at "wheadp". Each window contains its own values of dot and mark. + * The flag field contains some bits that are set by commands to guide + * redisplay; although this is a bit of a compromise in terms of decoupling, + * the full blown redisplay is just too expensive to run for every input + * character. + */ +typedef struct WINDOW { + struct WINDOW *w_wndp; /* Next window */ + struct BUFFER *w_bufp; /* Buffer displayed in window */ + struct LINE *w_linep; /* Top line in the window */ + struct LINE *w_dotp; /* Line containing "." */ + int w_doto; /* Byte offset for "." */ + struct LINE *w_markp; /* Line containing "mark" */ + int w_marko; /* Byte offset for "mark" */ + struct LINE *w_imarkp; /* INTERNAL Line with "mark" */ + int w_imarko; /* INTERNAL "mark" byte offset */ + signed char w_toprow; /* Origin 0 top row of window */ + signed char w_ntrows; /* # of rows of text in window */ + char w_force; /* If NZ, forcing row. */ + char w_flag; /* Flags. */ +} WINDOW; + +#define WFFORCE 0x01 /* Window needs forced reframe */ +#define WFMOVE 0x02 /* Movement from line to line */ +#define WFEDIT 0x04 /* Editing within a line */ +#define WFHARD 0x08 /* Better to a full display */ +#define WFMODE 0x10 /* Update mode line. */ + +/* + * Text is kept in buffers. A buffer header, described below, exists for every + * buffer in the system. The buffers are kept in a big list, so that commands + * that search for a buffer by name can find the buffer header. There is a + * safe store for the dot and mark in the header, but this is only valid if + * the buffer is not being displayed (that is, if "b_nwnd" is 0). The text for + * the buffer is kept in a circularly linked list of lines, with a pointer to + * the header line in "b_linep". + * Buffers may be "Inactive" which means the files accosiated with them + * have not been read in yet. These get read in at "use buffer" time. + */ +typedef struct BUFFER { + struct BUFFER *b_bufp; /* Link to next BUFFER */ + struct LINE *b_dotp; /* Link to "." LINE structure */ + int b_doto; /* Offset of "." in above LINE */ + struct LINE *b_markp; /* The same as the above two, */ + int b_marko; /* but for the "mark" */ + struct LINE *b_linep; /* Link to the header LINE */ + long b_linecnt; /* Lines in buffer (mswin only) */ + long b_mode; /* editor mode of this buffer */ + char b_active; /* window activated flag */ + char b_nwnd; /* Count of windows on buffer */ + char b_flag; /* Flags */ + char b_fname[NFILEN]; /* File name */ + char b_bname[NBUFN]; /* Buffer name */ +} BUFFER; + +#define BFTEMP 0x01 /* Internal temporary buffer */ +#define BFCHG 0x02 /* Changed since last write */ +#define BFWRAPOPEN 0x04 /* Wordwrap should open new line */ + + +/* + * The starting position of a region, and the size of the region in + * characters, is kept in a region structure. Used by the region commands. + */ +typedef struct { + struct LINE *r_linep; /* Origin LINE address. */ + int r_offset; /* Origin LINE offset. */ + long r_size; /* Length in characters. */ +} REGION; + + +/* + * character and attribute pair. The basic building block + * of the editor. The bitfields may have to be changed to a char + * and short if there are problems... + */ +typedef struct CELL { + unsigned int c : 8; /* Character value in cell */ + unsigned int a : 8; /* Its attributes */ +} CELL; + +#define RGBLEN 11 +#define MAXCOLORLEN 11 /* longest string a color can be */ + +typedef struct COLOR_PAIR { + char fg[MAXCOLORLEN+1]; + char bg[MAXCOLORLEN+1]; +} COLOR_PAIR; + +#define COL_BLACK 0 +#define COL_RED 1 +#define COL_GREEN 2 +#define COL_YELLOW 3 +#define COL_BLUE 4 +#define COL_MAGENTA 5 +#define COL_CYAN 6 +#define COL_WHITE 7 + +#define DEFAULT_NORM_FORE COL_BLACK +#define DEFAULT_NORM_BACK COL_CYAN + +/* flags for pico_set_color() */ +#define PSC_NONE 0x0 +#define PSC_NORM 0x1 +#define PSC_REV 0x2 +#define PSC_RET 0x4 /* return an allocated copy of previous color */ + +/* flags for color_options */ +#define COLOR_ANSI8_OPT 0x01 +#define COLOR_ANSI16_OPT 0x02 + +/* styles for pico_apply_rev_color() */ +#define IND_COL_FLIP 0 +#define IND_COL_REV 1 +#define IND_COL_FG 2 +#define IND_COL_FG_NOAMBIG 3 +#define IND_COL_BG 4 +#define IND_COL_BG_NOAMBIG 5 + + +/* + * All text is kept in circularly linked lists of "LINE" structures. These + * begin at the header line (which is the blank line beyond the end of the + * buffer). This line is pointed to by the "BUFFER". Each line contains a the + * number of bytes in the line (the "used" size), the size of the text array, + * and the text. The end of line is not stored as a byte; it's implied. Future + * additions will include update hints, and a list of marks into the line. + */ +typedef struct LINE { + struct LINE *l_fp; /* Link to the next line */ + struct LINE *l_bp; /* Link to the previous line */ + int l_size; /* Allocated size */ + int l_used; /* Used size */ + CELL l_text[1]; /* A bunch of characters. */ +} LINE; + +#define lforw(lp) ((lp)->l_fp) +#define lback(lp) ((lp)->l_bp) +#define lgetc(lp, n) ((lp)->l_text[(n)]) +#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c)) +#define llength(lp) ((lp)->l_used) + +/* + * The editor communicates with the display using a high level interface. A + * "TERM" structure holds useful variables, and indirect pointers to routines + * that do useful operations. The low level get and put routines are here too. + * This lets a terminal, in addition to having non standard commands, have + * funny get and put character code too. The calls might get changed to + * "termp->t_field" style in the future, to make it possible to run more than + * one terminal type. + */ +typedef struct { + short t_nrow; /* Number of rows - 1. */ + short t_ncol; /* Number of columns. */ + short t_margin; /* min margin for extended lines*/ + short t_scrsiz; /* size of scroll region " */ + short t_mrow; /* Number of rows in menu */ + int (*t_open)(); /* Open terminal at the start. */ + int (*t_terminalinfo)(); /* Set up terminal info */ + int (*t_close)(); /* Close terminal at end. */ + int (*t_getchar)(); /* Get character from keyboard. */ + int (*t_putchar)(); /* Put character to display. */ + int (*t_flush)(); /* Flush output buffers. */ + int (*t_move)(); /* Move the cursor, origin 0. */ + int (*t_eeol)(); /* Erase to end of line. */ + int (*t_eeop)(); /* Erase to end of page. */ + int (*t_beep)(); /* Beep. */ + int (*t_rev)(); /* set reverse video state */ +} TERM; + +/* structure for the table of initial key bindings */ + +typedef struct { + short k_code; /* Key code */ + int (*k_fp)(); /* Routine to handle it */ +} KEYTAB; + +/* sturcture used for key menu painting */ + +typedef struct { + char *name; /* key to display */ + char *label; /* function name key envokes */ + KS_OSDATAVAR /* port-specific data */ +} KEYMENU; + +typedef struct { + char *name; /* key to display */ + char *label; /* function name key envokes */ + int key; /* what to watch for and return */ + KS_OSDATAVAR /* port-specific data */ +} EXTRAKEYS; + +typedef struct lmlist { + char *dir; + char *fname; + char size[32]; + struct lmlist *next; +} LMLIST; + + +typedef struct VIDEO { + short v_flag; /* Flags */ + CELL v_text[1]; /* Screen data. */ +} VIDEO; + +typedef struct _file_io_data { + FILE *fp; /* stdio stream into file */ + long flags; /* state flags */ + char *name; /* pointer to file name */ +} FIOINFO; + +#define FIOINFO_READ 0x01 +#define FIOINFO_WRITE 0x02 + +#ifdef MOUSE + +/* Test if mouse position (R, C) is in menu item (X) */ +#define M_ACTIVE(R, C, X) (((unsigned)(R)) >= (X)->tl.r \ + && ((unsigned)(R)) <= (X)->br.r \ + && ((unsigned)(C)) >= (X)->tl.c \ + && ((unsigned)(C)) < (X)->br.c) +#endif /* MOUSE */ + +#endif /* ESTRUCT_H */ diff --git a/file.c b/file.c new file mode 100644 index 0000000..313be69 --- /dev/null +++ b/file.c @@ -0,0 +1,1011 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: file.c 13703 2004-06-11 21:49:40Z hubert $"; +#endif +/* + * Program: High level file input and output routines + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* + * The routines in this file + * handle the reading and writing of + * disk files. All of details about the + * reading and writing of the disk are + * in "fileio.c". + */ +#include "headers.h" + + +#ifdef ANSI + int ifile(char *); + int insmsgchar(int); +#else + int ifile(); + int insmsgchar(); +#endif +char *file_split(char *, int *, char *, int); + +/* + * Read a file into the current + * buffer. This is really easy; all you do it + * find the name of the file, and call the standard + * "read a file into the current buffer" code. + * Bound to "C-X C-R". + */ +fileread(f, n) +int f, n; +{ + register int s; + char fname[NFILEN]; + + if ((s=mlreply("Read file: ", fname, NFILEN, QNORML, NULL)) != TRUE) + return(s); + + if(gmode&MDSCUR){ + emlwrite("File reading disabled in secure mode",NULL); + return(0); + } + + if (strlen(fname) == 0) { + emlwrite("No file name entered",NULL); + return(0); + } + + if((gmode & MDTREE) && !in_oper_tree(fname)){ + emlwrite("Can't read file from outside of %s", opertree); + return(0); + } + + return(readin(fname, TRUE, TRUE)); +} + + + + +static char *inshelptext[] = { + "Insert File Help Text", + " ", + "\tType in a file name to have it inserted into your editing", + "\tbuffer between the line that the cursor is currently on", + "\tand the line directly below it. You may abort this by ", + "~\ttyping the ~F~2 (~^~C) key after exiting help.", + " ", + "End of Insert File Help", + " ", + NULL +}; + +static char *writehelp[] = { + "Write File Help Text", + " ", + "\tType in a file name to have it written out, thus saving", + "\tyour buffer, to a file. You can abort this by typing ", + "~\tthe ~F~2 (~^~C) key after exiting help.", + " ", + "End of Write File Help", + " ", + " ", + NULL +}; + + +/* + * Insert a file into the current + * buffer. This is really easy; all you do it + * find the name of the file, and call the standard + * "insert a file into the current buffer" code. + * Bound to "C-X C-I". + */ +insfile(f, n) +int f, n; +{ + register int s; + char fname[NLINE], dir[NLINE]; + int retval, bye = 0, msg = 0; + char prompt[64], *infile; + EXTRAKEYS menu_ins[5]; + + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + + fname[0] = '\0'; + while(!bye){ + /* set up keymenu stuff */ + if(!msg){ + int last_menu = 0; + + menu_ins[last_menu].name = "^T"; + menu_ins[last_menu].key = (CTRL|'T'); + menu_ins[last_menu].label = "To Files"; + KS_OSDATASET(&menu_ins[last_menu], KS_NONE); + + if(Pmaster && Pmaster->msgntext){ + menu_ins[++last_menu].name = "^W"; + menu_ins[last_menu].key = (CTRL|'W'); + menu_ins[last_menu].label = msg ? "InsertFile" : "InsertMsg"; + KS_OSDATASET(&menu_ins[last_menu], KS_NONE); + } + +#if !defined(DOS) && !defined(MAC) + if(Pmaster && Pmaster->upload){ + menu_ins[++last_menu].name = "^Y"; + menu_ins[last_menu].key = (CTRL|'Y'); + menu_ins[last_menu].label = "RcvUpload"; + KS_OSDATASET(&menu_ins[last_menu], KS_NONE); + } +#endif /* !(DOS || MAC) */ + + if(gmode & MDCMPLT){ + menu_ins[++last_menu].name = msg ? "" : "TAB"; + menu_ins[last_menu].key = (CTRL|'I'); + menu_ins[last_menu].label = msg ? "" : "Complete"; + KS_OSDATASET(&menu_ins[last_menu], KS_NONE); + } + + menu_ins[++last_menu].name = NULL; + } + + sprintf(prompt, "%s to insert from %s %s: ", + msg ? "Number of message" : "File", + (msg || (gmode&MDCURDIR)) + ? "current" + : ((gmode & MDTREE) || opertree[0]) ? opertree : "home", + msg ? "folder" : "directory"); + s = mlreplyd(prompt, fname, NLINE, QDEFLT, msg ? NULL : menu_ins); + /* something to read and it was edited or the default accepted */ + if(fname[0] && (s == TRUE || s == FALSE)){ + bye++; + if(msg){ + if((*Pmaster->msgntext)(atol(fname), insmsgchar)) + emlwrite("Message %s included", fname); + } + else{ + bye++; + if(gmode&MDSCUR){ + emlwrite("Can't insert file in restricted mode",NULL); + } + else{ + if((gmode & MDTREE) + && !compresspath(opertree, fname, NLINE)){ + emlwrite( + "Can't insert file from outside of %s: too many ..'s", + opertree); + } + else{ + fixpath(fname, NLINE); + + if((gmode & MDTREE) && !in_oper_tree(fname)) + emlwrite("Can't insert file from outside of %s", + opertree); + else + retval = ifile(fname); + } + } + } + } + else{ + switch(s){ + case (CTRL|'I') : + { + char *fn, *p; + int dirlen, l = NLINE; + + dir[0] = '\0'; + fn = file_split(dir, &l, fname, 0); + + if(!pico_fncomplete(dir, fn, l - 1)) + (*term.t_beep)(); + } + + break; + case (CTRL|'W'): + msg = !msg; /* toggle what to insert */ + break; + case (CTRL|'T'): + if(msg){ + emlwrite("Can't select messages yet!", NULL); + } + else{ + char *fn; + int len = NLINE; + + fn = file_split(dir, &len, fname, 1); + if(!isdir(dir, NULL, NULL)) + strcpy(dir, (gmode&MDCURDIR) + ? (browse_dir[0] ? browse_dir : ".") + : ((gmode & MDTREE) || opertree[0]) + ? opertree + : (browse_dir[0] ? browse_dir + :gethomedir(NULL))); + else{ + if(*fn){ + int dirlen; + + dirlen = strlen(dir); + if(dirlen && dir[dirlen - 1] != C_FILESEP) + strcat(dir, S_FILESEP); + strcat(dir, fn); + if(!isdir(dir, NULL, NULL)) + dir[dirlen] = '\0'; + } + } + + fname[0] = '\0'; + if((s = FileBrowse(dir, NLINE, fname, NLINE, + NULL, FB_READ, NULL)) == 1){ + if(gmode&MDSCUR){ + emlwrite("Can't insert in restricted mode", + NULL); + sleep(2); + } + else{ + if (infile = (char *)malloc((strlen(dir)+ + strlen(S_FILESEP)+ + strlen(fname)+1)*sizeof(char))){ + strcpy(infile, dir); + strcat(infile, S_FILESEP); + strcat(infile, fname); + retval = ifile(infile); + free((char *) infile); + } + else { + emlwrite("Trouble allocating space for insert!" + ,NULL); + sleep(3); + } + } + bye++; + } + else + fname[0] = '\0'; + + pico_refresh(FALSE, 1); + if(s != 1){ + update(); /* redraw on return */ + continue; + } + } + + break; + +#if !defined(DOS) && !defined(MAC) + case (CTRL|'Y') : + if(Pmaster && Pmaster->upload){ + char tfname[NLINE]; + + if(gmode&MDSCUR){ + emlwrite( + "\007Restricted mode disallows uploaded command", + NULL); + return(0); + } + + tfname[0] = '\0'; + retval = (*Pmaster->upload)(tfname, NULL); + + pico_refresh(FALSE, 1); + update(); + + if(retval){ + retval = ifile(tfname); + bye++; + } + else + sleep(3); /* problem, show error! */ + + if(tfname[0]) /* clean up temp file */ + unlink(tfname); + } + else + (*term.t_beep)(); /* what? */ + + break; +#endif /* !(DOS || MAC) */ + case HELPCH: + if(Pmaster){ + VARS_TO_SAVE *saved_state; + + saved_state = save_pico_state(); + (*Pmaster->helper)(msg ? Pmaster->ins_m_help + : Pmaster->ins_help, + "Help for Insert File", 1); + if(saved_state){ + restore_pico_state(saved_state); + free_pico_state(saved_state); + } + } + else + pico_help(inshelptext, "Help for Insert File", 1); + case (CTRL|'L'): + pico_refresh(FALSE, 1); + update(); + continue; + default: + ctrlg(FALSE, 0); + retval = s; + bye++; + } + } + } + curwp->w_flag |= WFMODE|WFHARD; + + return(retval); +} + +/* + * split out the file name from the path. + * Copy path into dirbuf, return filename, + * which is a pointer into orig_fname. + * lenp is the length of dirbuf. + * is_for_browse - use browse dir if possible + * don't want to use it for TAB-completion + */ +char * +file_split(dirbuf, lenp, orig_fname, is_for_browse) + char *dirbuf; + int *lenp; + char *orig_fname; + int is_for_browse; +{ + char *p, *fn; + int dirlen; + + if(*orig_fname && (p = strrchr(orig_fname, C_FILESEP))){ + fn = p + 1; + (*lenp) -= fn - orig_fname; + dirlen = p - orig_fname; + if(p == orig_fname) + strcpy(dirbuf, S_FILESEP); +#ifdef DOS + else if(orig_fname[0] == C_FILESEP + || (isalpha((unsigned char)orig_fname[0]) + && orig_fname[1] == ':')){ + if(orig_fname[1] == ':' && p == orig_fname+2) + dirlen = fn - orig_fname; + strncpy(dirbuf, orig_fname, dirlen); + dirbuf[dirlen] = '\0'; + } +#else + else if (orig_fname[0] == C_FILESEP + || orig_fname[0] == '~') { + strncpy(dirbuf, orig_fname, dirlen); + dirbuf[dirlen] = '\0'; + } +#endif + else + sprintf(dirbuf, "%s%c%.*s", + (gmode & MDCURDIR) + ? ((is_for_browse && browse_dir[0]) ? browse_dir : ".") + : ((gmode & MDTREE) || opertree[0]) + ? opertree + : ((is_for_browse && browse_dir[0]) + ? browse_dir : gethomedir(NULL)), + C_FILESEP, p - orig_fname, orig_fname); + } + else{ + fn = orig_fname; + strcpy(dirbuf, (gmode & MDCURDIR) + ? ((is_for_browse && browse_dir[0]) ? browse_dir : ".") + : ((gmode & MDTREE) || opertree[0]) + ? opertree + : ((is_for_browse && browse_dir[0]) + ? browse_dir : gethomedir(NULL))); + } + return fn; +} + +insmsgchar(c) + int c; +{ + if(c == '\n'){ + char *p; + + lnewline(); + for(p = (glo_quote_str ? glo_quote_str + : (Pmaster ? Pmaster->quote_str : NULL)); + p && *p; p++) + if(!linsert(1, *p)) + return(0); + } + else if(c != '\r') /* ignore CR (likely CR of CRLF) */ + return(linsert(1, c)); + + return(1); +} + + + +/* + * Read file "fname" into the current + * buffer, blowing away any text found there. Called + * by both the read and find commands. Return the final + * status of the read. Also called by the mainline, + * to read in a file specified on the command line as + * an argument. + */ +readin(fname, lockfl, rename) +char fname[]; /* name of file to read */ +int lockfl; /* check for file locks? */ +int rename; /* don't rename if reading from, say, alt speller */ +{ + char line[NLINE], *linep; + long nline; + int s, done, newline; + + curbp->b_linecnt = -1; /* Must be recalculated */ + if ((s = bclear(curbp)) != TRUE) /* Might be old. */ + return (s); + + if(rename) + strcpy(curbp->b_fname, fname); + if ((s=ffropen(fname)) != FIOSUC){ /* Hard file open. */ + if(s == FIOFNF) /* File not found. */ + emlwrite("New file", NULL); + else + fioperr(s, fname); + } + else{ + int charsread = 0; + + emlwrite("Reading file", NULL); + nline = 0L; + done = newline = 0; + while(!done) + if((s = ffgetline(line, NLINE, &charsread, 1)) == FIOEOF){ + curbp->b_flag &= ~(BFTEMP|BFCHG); + gotobob(FALSE, 1); + sprintf(line,"Read %d line%s", + nline, (nline > 1) ? "s" : ""); + emlwrite(line, NULL); + break; + } + else{ + if(newline){ + lnewline(); + newline = 0; + } + + switch(s){ + case FIOSUC : + nline++; + newline = 1; + + case FIOLNG : + for(linep = line; charsread-- > 0; linep++) + linsert(1, (unsigned char) *linep); + + break; + + default : + done++; + break; + } + } + + ffclose(); /* Ignore errors. */ + } + + return(s != FIOERR && s != FIOFNF); /* true if success */ +} + + +/* + * Ask for a file name, and write the + * contents of the current buffer to that file. + * Update the remembered file name and clear the + * buffer changed flag. This handling of file names + * is different from the earlier versions, and + * is more compatable with Gosling EMACS than + * with ITS EMACS. Bound to "C-X C-W". + */ +filewrite(f, n) +int f, n; +{ + register WINDOW *wp; + register int s; + char fname[NFILEN]; + char shows[NLINE], origshows[NLINE], *bufp; + EXTRAKEYS menu_write[3]; + + if(curbp->b_fname[0] != 0) + strcpy(fname, curbp->b_fname); + else + fname[0] = '\0'; + + menu_write[0].name = "^T"; + menu_write[0].label = "To Files"; + menu_write[0].key = (CTRL|'T'); + menu_write[1].name = "TAB"; + menu_write[1].label = "Complete"; + menu_write[1].key = (CTRL|'I'); + menu_write[2].name = NULL; + for(;!(gmode & MDTOOL);){ + s = mlreplyd("File Name to write : ", fname, NFILEN, + QDEFLT|QFFILE, menu_write); + + switch(s){ + case FALSE: + if(!fname[0]){ /* no file name to write to */ + ctrlg(FALSE, 0); + return(s); + } + case TRUE: + if((gmode & MDTREE) && !compresspath(opertree, fname, NFILEN)){ + emlwrite("Can't write outside of %s: too many ..'s", + opertree); + sleep(2); + continue; + } + else{ + fixpath(fname, NFILEN); /* fixup ~ in file name */ + if((gmode & MDTREE) && !in_oper_tree(fname)){ + emlwrite("Can't write outside of %s", opertree); + sleep(2); + continue; + } + } + + break; + + case (CTRL|'I'): + { + char *fn, *p, dir[NFILEN]; + int l = NFILEN; + + dir[0] = '\0'; + if(*fname && (p = strrchr(fname, C_FILESEP))){ + fn = p + 1; + l -= fn - fname; + if(p == fname) + strcpy(dir, S_FILESEP); +#ifdef DOS + else if(fname[0] == C_FILESEP + || (isalpha((unsigned char)fname[0]) + && fname[1] == ':')){ +#else + else if (fname[0] == C_FILESEP || fname[0] == '~') { +#endif + strncpy(dir, fname, p - fname); + dir[p-fname] = '\0'; + } + else + sprintf(dir, "%s%c%.*s", + (gmode & MDCURDIR) + ? "." + : ((gmode & MDTREE) || opertree[0]) + ? opertree : gethomedir(NULL), + C_FILESEP, p - fname, fname); + } + else{ + fn = fname; + strcpy(dir, (gmode & MDCURDIR) + ? "." + : ((gmode & MDTREE) || opertree[0]) + ? opertree : gethomedir(NULL)); + } + + if(!pico_fncomplete(dir, fn, l - 1)) + (*term.t_beep)(); + } + + continue; + case (CTRL|'T'): + /* If we have a file name, break up into path and file name.*/ + *shows = 0; + if(*fname) { + if (isdir (fname, NULL, NULL)) { + /* fname is a directory. */ + strcpy (shows, fname); + *fname = '\0'; + } + else { + /* Find right most seperator. */ + bufp = strrchr (fname, C_FILESEP); + if (bufp != NULL) { + /* Copy directory part to 'shows', and file + * name part to front of 'fname'. */ + *bufp = '\0'; + strcpy (shows, fname); + memcpy (fname, bufp+1, strlen (bufp+1) + 1); + } + } + } + + /* If we did not end up with a valid directory, use home. */ + if (!*shows || !isdir (shows, NULL, NULL)) + strcpy(shows, ((gmode & MDTREE) || opertree[0]) + ? opertree + : (browse_dir[0] ? browse_dir + : gethomedir(NULL))); + + strcpy(origshows, shows); + if ((s = FileBrowse(shows, NLINE, fname, NFILEN, NULL, + FB_SAVE, NULL)) == 1) { + if (strlen(shows)+strlen(S_FILESEP)+strlen(fname) < NLINE){ + strcat(shows, S_FILESEP); + strcat(shows, fname); + strcpy(fname, shows); + } + else { + emlwrite("Cannot write. File name too long!!",NULL); + sleep(3); + } + } + else if (s == 0 && strcmp(shows, origshows)){ + strcat(shows, S_FILESEP); + strcat(shows, fname); + strcpy(fname, shows); + } + else if (s == -1){ + emlwrite("Cannot write. File name too long!!",NULL); + sleep(3); + } + pico_refresh(FALSE, 1); + update(); + if(s == 1) + break; + else + continue; + case HELPCH: + pico_help(writehelp, "", 1); + case (CTRL|'L'): + pico_refresh(FALSE, 1); + update(); + continue; + default: + return(s); + break; + } + + if(strcmp(fname, curbp->b_fname) == 0) + break; + + if((s=fexist(fname, "w", (off_t *)NULL)) == FIOSUC){ + /*exists overwrite? */ + + sprintf(shows, "File \"%s\" exists, OVERWRITE", fname); + if((s=mlyesno(shows, FALSE)) == TRUE) + break; + } + else if(s == FIOFNF){ + break; /* go write it */ + } + else{ /* some error, can't write */ + fioperr(s, fname); + return(ABORT); + } + } + emlwrite("Writing...", NULL); + + if ((s=writeout(fname, 0)) != -1) { + if(!(gmode&MDTOOL)){ + strcpy(curbp->b_fname, fname); + curbp->b_flag &= ~BFCHG; + + wp = wheadp; /* Update mode lines. */ + while (wp != NULL) { + if (wp->w_bufp == curbp) + if((Pmaster && s == TRUE) || Pmaster == NULL) + wp->w_flag |= WFMODE; + wp = wp->w_wndp; + } + } + + if(s > 1) + emlwrite("Wrote %d lines", (void *)s); + else + emlwrite("Wrote 1 line", NULL); + } + return ((s == -1) ? FALSE : TRUE); +} + + + +/* + * Save the contents of the current + * buffer in its associatd file. No nothing + * if nothing has changed (this may be a bug, not a + * feature). Error if there is no remembered file + * name for the buffer. Bound to "C-X C-S". May + * get called by "C-Z". + */ +filesave(f, n) +int f, n; +{ + register WINDOW *wp; + register int s; + + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + if ((curbp->b_flag&BFCHG) == 0) /* Return, no changes. */ + return (TRUE); + if (curbp->b_fname[0] == 0) { /* Must have a name. */ + emlwrite("No file name", NULL); + sleep(2); + return (FALSE); + } + + emlwrite("Writing...", NULL); + if ((s=writeout(curbp->b_fname, 0)) != -1) { + curbp->b_flag &= ~BFCHG; + wp = wheadp; /* Update mode lines. */ + while (wp != NULL) { + if (wp->w_bufp == curbp) + if(Pmaster == NULL) + wp->w_flag |= WFMODE; + wp = wp->w_wndp; + } + if(s > 1){ + emlwrite("Wrote %d lines", (void *)s); + } + else + emlwrite("Wrote 1 line", NULL); + } + return (s); +} + +/* + * This function performs the details of file + * writing. Uses the file management routines in the + * "fileio.c" package. The number of lines written is + * displayed. Sadly, it looks inside a LINE; provide + * a macro for this. Most of the grief is error + * checking of some sort. + * + * If the argument readonly is set, the file is created with user read + * and write permission only if it doesn't already exist. Note that the + * word readonly is misleading. It is user r/w permission only. + * + * CHANGES: 1 Aug 91: returns number of lines written or -1 on error, MSS + */ +writeout(fn, readonly) +char *fn; +int readonly; +{ + register int s; + register int t; + register LINE *lp; + register int nline; + + if (!((s = ffwopen(fn, readonly)) == FIOSUC && ffelbowroom())) + return (-1); /* Open writes message. */ + + lp = lforw(curbp->b_linep); /* First line. */ + nline = 0; /* Number of lines. */ + while (lp != curbp->b_linep) { + if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC) + break; + ++nline; + lp = lforw(lp); + } + + t = ffclose(); /* ffclose complains if error */ + + if(s == FIOSUC) + s = t; /* report worst case */ + + return ((s == FIOSUC) ? nline : -1); +} + + +/* + * writetmp - write a temporary file for message text, mindful of + * access restrictions and included text. If n is true, include + * lines that indicated included message text, otw forget them + * If dir is non-null, put the temp file in that directory. + */ +char *writetmp(n, dir) +int n; +char *dir; +{ + static char fn[NFILEN]; + register int s; + register int t; + register LINE *lp; + register int nline; + + tmpname(dir, fn); + + /* Open writes message */ + if (!fn[0] || (s=ffwopen(fn, TRUE)) != FIOSUC){ + if(fn[0]) + (void)unlink(fn); + + return(NULL); + } + + lp = lforw(curbp->b_linep); /* First line. */ + nline = 0; /* Number of lines. */ + while (lp != curbp->b_linep) { + if(n || (!n && lp->l_text[0].c != '>')) + if ((s=ffputline(&lp->l_text[0], llength(lp))) != FIOSUC) + break; + + ++nline; + lp = lforw(lp); + } + + t = ffclose(); /* ffclose complains if error */ + + if(s == FIOSUC) + s = t; /* remember worst case */ + + if (s != FIOSUC){ /* Some sort of error. */ + (void)unlink(fn); + return(NULL); + } + + return(fn); +} + + +/* + * Insert file "fname" into the current + * buffer, Called by insert file command. Return the final + * status of the read. + */ +ifile(fname) +char fname[]; +{ + char line[NLINE], *linep; + long nline; + int s, done, newline, charsread = 0; + + if ((s=ffropen(fname)) != FIOSUC){ /* Hard file open. */ + fioperr(s, fname); + return(FALSE); + } + + gotobol(FALSE, 1); + + curbp->b_flag |= BFCHG; /* we have changed */ + curbp->b_flag &= ~BFTEMP; /* and are not temporary*/ + curbp->b_linecnt = -1; /* must be recalculated */ + + emlwrite("Inserting %s.", fname); + done = newline = 0; + nline = 0L; + while(!done) + if((s = ffgetline(line, NLINE, &charsread, 1)) == FIOEOF){ + if(llength(curwp->w_dotp) > curwp->w_doto) + lnewline(); + else + forwchar(FALSE, 1); + + sprintf(line,"Inserted %d line%s", nline, (nline>1) ? "s" : ""); + emlwrite(line, NULL); + break; + } + else{ + if(newline){ + lnewline(); + newline = 0; + } + + switch(s){ + case FIOSUC : /* copy line into buf */ + nline++; + newline = 1; + + case FIOLNG : + for(linep = line; charsread-- > 0; linep++) + linsert(1, (unsigned char) *linep); + + break; + + default : + done++; + } + } + + ffclose(); /* Ignore errors. */ + + return(s != FIOERR); +} + + + +/* + * pico_fncomplete - pico's function to complete the given file name + */ +int pico_fncomplete(dir, fn, len) +char *dir, *fn; +int len; +{ + char *p, *dlist, tmp[NLINE], dtmp[NLINE]; + int n, i, match = -1; +#ifdef DOS +#define FILECMP(x, y) (toupper((unsigned char)(x))\ + == toupper((unsigned char)(y))) +#else +#define FILECMP(x, y) ((x) == (y)) +#endif + + strcpy(dtmp, dir); + pfnexpand(dir = dtmp, NLINE); + if(*fn && (dlist = p = getfnames(dir, fn, &n, NULL))){ + memset(tmp, 0, sizeof(tmp)); + while(n--){ /* any names in it */ + for(i = 0; fn[i] && FILECMP(p[i], fn[i]); i++) + ; + + if(!fn[i]){ /* match or more? */ + if(tmp[0]){ + for(; p[i] && FILECMP(p[i], tmp[i]); i++) + ; + + match = !p[i] && !tmp[i]; + tmp[i] = '\0'; /* longest common string */ + } + else{ + match = 1; /* may be it!?! */ + strcpy(tmp, p); + } + } + + p += strlen(p) + 1; + } + + free(dlist); + } + + if(match >= 0){ + strncpy(fn, tmp, len); + fn[len] = '\0'; + if(match == 1){ + if ((strlen(dir)+strlen(S_FILESEP)+strlen(fn)) < len){ + strcat(dir, S_FILESEP); + strcat(dir, fn); + if(isdir(dir, NULL, NULL)) + strcat(fn, S_FILESEP); + } + else{ + emlwrite("File name too BIG!!",0); + sleep(3); + *fn = '\0'; + } + + } + } + + return(match == 1); + +} + + +/* + * in_oper_tree - returns true if file "f" does reside in opertree + */ +in_oper_tree(f) +char *f; +{ + int end = strlen(opertree); + + return(!strncmp(opertree, f, end) + && (opertree[end-1] == '/' + || opertree[end-1] == '\\' + || f[end] == '\0' + || f[end] == '/' + || f[end] == '\\')); +} diff --git a/fileio.c b/fileio.c new file mode 100644 index 0000000..c90bf40 --- /dev/null +++ b/fileio.c @@ -0,0 +1,159 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: fileio.c 12094 2002-02-12 22:53:53Z hubert $"; +#endif +/* + * Program: ASCII file reading routines + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2002 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* + * The routines in this file read and write ASCII files from the disk. All of + * the knowledge about files are here. A better message writing scheme should + * be used. + */ +#include "headers.h" + + +#if defined(bsd) || defined(lnx) +extern int errno; +#endif + + +FIOINFO g_pico_fio; + +/* + * Open a file for reading. + */ +ffropen(fn) + char *fn; +{ + int status; + + if ((status = fexist(g_pico_fio.name = fn, "r", (off_t *)NULL)) == FIOSUC){ + g_pico_fio.flags = FIOINFO_READ; + if((g_pico_fio.fp = fopen(g_pico_fio.name, "r")) == NULL) + status = FIOFNF; + } + + return (status); +} + + +/* + * Write a line to the already opened file. The "buf" points to the buffer, + * and the "nbuf" is its length, less the free newline. Return the status. + * Check only at the newline. + */ +ffputline(buf, nbuf) + CELL buf[]; + int nbuf; +{ + register int i; + + for (i = 0; i < nbuf; ++i) + if(fputc(buf[i].c&0xFF, g_pico_fio.fp) == EOF) + break; + + if(i == nbuf) + fputc('\n', g_pico_fio.fp); + + if (ferror(g_pico_fio.fp)) { + emlwrite("\007Write error: %s", errstr(errno)); + sleep(5); + return (FIOERR); + } + + return (FIOSUC); +} + + + +/* + * Read a line from a file, and store the bytes in the supplied buffer. The + * "nbuf" is the length of the buffer. Complain about long lines and lines + * at the end of the file that don't have a newline present. Check for I/O + * errors too. Return status. + */ +ffgetline(buf, nbuf, charsreturned, msg) + register char buf[]; + int nbuf; + int *charsreturned; + int msg; +{ + register int c; + register int i; + + if(charsreturned) + *charsreturned = 0; + + i = 0; + + while ((c = fgetc(g_pico_fio.fp)) != EOF && c != '\n') { + /* + * Don't blat the CR should the newline be CRLF and we're + * running on a unix system. NOTE: this takes care of itself + * under DOS since the non-binary open turns newlines into '\n'. + */ + if(c == '\r'){ + if((c = fgetc(g_pico_fio.fp)) == EOF || c == '\n') + break; + + if (i < nbuf-2) /* Bare CR. Insert it and go on... */ + buf[i++] = '\r'; /* else, we're up a creek */ + } + + if (i >= nbuf-2) { + buf[nbuf - 2] = c; /* store last char read */ + buf[nbuf - 1] = 0; /* and terminate it */ + if(charsreturned) + *charsreturned = nbuf - 1; + if (msg) + emlwrite("File has long line", NULL); + return (FIOLNG); + } + buf[i++] = c; + } + + if (c == EOF) { + if (ferror(g_pico_fio.fp)) { + emlwrite("File read error", NULL); + if(charsreturned) + *charsreturned = i; + return (FIOERR); + } + + if (i != 0) + emlwrite("File doesn't end with newline. Adding one.", NULL); + else{ + if(charsreturned) + *charsreturned = i; + return (FIOEOF); + } + } + + buf[i] = 0; + if(charsreturned) + *charsreturned = i; + return (FIOSUC); +} diff --git a/headers.h b/headers.h new file mode 100644 index 0000000..503612e --- /dev/null +++ b/headers.h @@ -0,0 +1,80 @@ +/*====================================================================== + $Id: headers.h 9714 1999-01-27 22:14:21Z hubert $ + + headers.h + + The include file to always include that includes a few other things + - includes the most general system files and other pine include files + - declares the global variables + + ====*/ + + +#ifndef _PICO_HEADERS_INCLUDED +#define _PICO_HEADERS_INCLUDED + +/*---------------------------------------------------------------------- + Include files + + System specific includes and defines are in os.h, the source for which +is os-xxx.h. (Don't edit os.h; edit os-xxx.h instead.) + ----*/ + +#ifdef TERMCAP_WINS + Do not use TERMCAP WINS anymore. This is now set at runtime with + pico -q, pilot -q, or the pine feature called termdef-takes-precedence. + You do not need to do anything special while compiling. +#endif /* TERMCAP_WINS */ + +#include + +#include "os.h" + +/* + * [Re]Define signal functions as needed... + */ +#ifdef POSIX_SIGNALS +/* + * Redefine signal call to our wrapper of POSIX sigaction + */ +#define signal(SIG,ACT) posix_signal(SIG,ACT) +#define our_sigunblock(SIG) posix_sigunblock(SIG) +#else /* !POSIX_SIGNALS */ +#ifdef SYSV_SIGNALS +/* + * Redefine signal calls to SYSV style call. + */ +#define signal(SIG,ACT) sigset(SIG,ACT) +#define our_sigunblock(SIG) sigrelse(SIG) +#else /* !SYSV_SIGNALS */ +#ifdef WIN32 +#define signal(SIG,ACT) mswin_signal(SIG,ACT) +#define our_sigunblock(SIG) +#else /* !WIN32 */ +/* + * Good ol' BSD signals. + */ +#define our_sigunblock(SIG) +#endif /* !WIN32 */ +#endif /* !SYSV_SIGNALS */ +#endif /* !POSIX_SIGNALS */ + + +/* These includes are all ANSI, and OK with all other compilers (so far) */ +#include +#include +#include + + +#ifdef ANSI +#define PROTO(args) args +#else +#define PROTO(args) () +#endif + +#include "estruct.h" +#include "pico.h" +#include "edef.h" +#include "efunc.h" + +#endif /* _PICO_HEADERS_INCLUDED */ diff --git a/line.c b/line.c new file mode 100644 index 0000000..63bb711 --- /dev/null +++ b/line.c @@ -0,0 +1,783 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: line.c 13654 2004-05-07 21:43:40Z jpf $"; +#endif +/* + * Program: Line management routines + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* + * The functions in this file are a general set of line management utilities. + * They are the only routines that touch the text. They also touch the buffer + * and window structures, to make sure that the necessary updating gets done. + * There are routines in this file that handle the kill buffer too. It isn't + * here for any good reason. + * + * Note that this code only updates the dot and mark values in the window list. + * Since all the code acts on the current window, the buffer that we are + * editing must be being displayed, which means that "b_nwnd" is non zero, + * which means that the dot and mark values in the buffer headers are nonsense. + */ + +#include "headers.h" + +#define NBLOCK 16 /* Line block chunk size */ +#define KBLOCK 1024 /* Kill buffer block size */ + + +/* + * Struct to manage the kill and justify buffers + */ +struct pkchunk { + short used; /* # of bytes used in this buffer*/ + char bufp[KBLOCK]; /* buffer containing text */ + struct pkchunk *next; /* pointer to next chunk */ +}; + +static struct pkbuf { + long total; /* # of bytes used in buffer */ + struct pkchunk *first; /* first one of these in the chain */ + struct pkchunk *last; /* last one of these in the chain */ +} *kbufp, *fbufp; + + +#ifdef ANSI + void insspace(int, int); + int ldelnewline(void); + void pkbufdel(struct pkbuf **); + void pkchunkdel(struct pkchunk **); + int pkbufinsert(int, struct pkbuf **); + int pkbufremove(int, struct pkbuf *); +#else + void insspace(); + int ldelnewline(); + void pkbufdel(); + void pkchunkdel(); + int pkbufinsert(); + int pkbufremove(); +#endif + + +/* + * This routine allocates a block of memory large enough to hold a LINE + * containing "used" characters. The block is always rounded up a bit. Return + * a pointer to the new block, or NULL if there isn't any memory left. Print a + * message in the message line if no space. + */ +LINE * +lalloc(used) +register int used; +{ + register LINE *lp; + register int size; + + if((size = (used+NBLOCK-1) & ~(NBLOCK-1)) > NLINE) + size *= 2; + + if (size == 0) /* Assume that an empty */ + size = NBLOCK; /* line is for type-in. */ + + if ((lp = (LINE *) malloc(sizeof(LINE)+(size*sizeof(CELL)))) == NULL) { + emlwrite("Cannot allocate %d bytes", (void *)size); + return (NULL); + } + + lp->l_size = size; + lp->l_used = used; + return (lp); +} + +/* + * Delete line "lp". Fix all of the links that might point at it (they are + * moved to offset 0 of the next line. Unlink the line from whatever buffer it + * might be in. Release the memory. The buffers are updated too; the magic + * conditions described in the above comments don't hold here. + */ +void +lfree(lp) +register LINE *lp; +{ + register BUFFER *bp; + register WINDOW *wp; + + wp = wheadp; + while (wp != NULL) { + if (wp->w_linep == lp) + wp->w_linep = lp->l_fp; + + if (wp->w_dotp == lp) { + wp->w_dotp = lp->l_fp; + wp->w_doto = 0; + } + + if (wp->w_markp == lp) { + wp->w_markp = lp->l_fp; + wp->w_marko = 0; + } + + if (wp->w_imarkp == lp) { + wp->w_imarkp = lp->l_fp; + wp->w_imarko = 0; + } + + wp = wp->w_wndp; + } + + bp = bheadp; + while (bp != NULL) { + if (bp->b_nwnd == 0) { + if (bp->b_dotp == lp) { + bp->b_dotp = lp->l_fp; + bp->b_doto = 0; + } + + if (bp->b_markp == lp) { + bp->b_markp = lp->l_fp; + bp->b_marko = 0; + } + } + + bp = bp->b_bufp; + } + + lp->l_bp->l_fp = lp->l_fp; + lp->l_fp->l_bp = lp->l_bp; + free((char *) lp); +} + + +/* + * This routine gets called when a character is changed in place in the current + * buffer. It updates all of the required flags in the buffer and window + * system. The flag used is passed as an argument; if the buffer is being + * displayed in more than 1 window we change EDIT t HARD. Set MODE if the + * mode line needs to be updated (the "*" has to be set). + */ +void +lchange(flag) +register int flag; +{ + register WINDOW *wp; + + if (curbp->b_nwnd != 1) /* Ensure hard. */ + flag = WFHARD; + + if ((curbp->b_flag&BFCHG) == 0) { /* First change, so */ + if(Pmaster == NULL) + flag |= WFMODE; /* update mode lines. */ + curbp->b_flag |= BFCHG; + } + + wp = wheadp; + while (wp != NULL) { + if (wp->w_bufp == curbp) + wp->w_flag |= flag; + wp = wp->w_wndp; + } +} + + +/* + * insert spaces forward into text + * default flag and numeric argument + */ +void +insspace(f, n) +int f, n; +{ + linsert(n, ' '); + backchar(f, n); +} + +/* + * Insert "n" copies of the character "c" at the current location of dot. In + * the easy case all that happens is the text is stored in the line. In the + * hard case, the line has to be reallocated. When the window list is updated, + * take special care; I screwed it up once. You always update dot in the + * current window. You update mark, and a dot in another window, if it is + * greater than the place where you did the insert. Return TRUE if all is + * well, and FALSE on errors. + */ +linsert(n, c) +int n, c; +{ + register LINE *dotp; + register int doto; + register WINDOW *wp; + + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + + dotp = curwp->w_dotp; + doto = curwp->w_doto; + lchange(WFEDIT); + + if(!geninsert(&(curwp->w_dotp), &(curwp->w_doto), curbp->b_linep, + c, (curwp->w_markp) ? 1 : 0, n, &curbp->b_linecnt)) + return(FALSE); + + wp = wheadp; /* Update windows */ + while (wp != NULL) { + if (wp->w_linep == dotp) + wp->w_linep = wp->w_dotp; + + if (wp->w_imarkp == dotp) { /* added for internal mark */ + wp->w_imarkp = wp->w_dotp; + if (wp->w_imarko > doto) + wp->w_imarko += n; + } + + if (wp->w_markp == dotp) { + wp->w_markp = dotp; + if (wp->w_marko > doto) + wp->w_marko += n; + } + wp = wp->w_wndp; + } + + return (TRUE); +} + + +/* + * geninsert - do the actual work of inserting a character into + * the list of lines. + */ +int +geninsert(dotp, doto, linep, c, attb, n, lines) +LINE **dotp, *linep; +int *doto; +int c, attb, n; +long *lines; +{ + register LINE *lp1; + register LINE *lp2; + register CELL *cp1; + register CELL *cp2; + CELL ac; + + ac.a = attb; + if (*dotp == linep) { /* At the end: special */ + if (*doto != 0) { + emlwrite("Programmer botch: geninsert", NULL); + return (FALSE); + } + + if ((lp1=lalloc(n)) == NULL) /* Allocate new line */ + return (FALSE); + + lp2 = (*dotp)->l_bp; /* Previous line */ + lp2->l_fp = lp1; /* Link in */ + lp1->l_fp = *dotp; + (*dotp)->l_bp = lp1; + lp1->l_bp = lp2; + *doto = n; + *dotp = lp1; + ac.c = ((char)c & 0xff); + cp1 = &(*dotp)->l_text[0]; + while(n--) + *cp1++ = ac; + + if(lines) + (*lines)++; + + return (TRUE); + } + + if ((*dotp)->l_used+n > (*dotp)->l_size) { /* Hard: reallocate */ + if ((lp1=lalloc((*dotp)->l_used+n)) == NULL) + return (FALSE); + + cp1 = &(*dotp)->l_text[0]; + cp2 = &lp1->l_text[0]; + while (cp1 != &(*dotp)->l_text[*doto]) + *cp2++ = *cp1++; + + cp2 += n; + while (cp1 != &(*dotp)->l_text[(*dotp)->l_used]) + *cp2++ = *cp1++; + + (*dotp)->l_bp->l_fp = lp1; + lp1->l_fp = (*dotp)->l_fp; + (*dotp)->l_fp->l_bp = lp1; + lp1->l_bp = (*dotp)->l_bp; + + /* global may be keeping track of mark/imark */ + if(wheadp){ + if (wheadp->w_imarkp == *dotp) + wheadp->w_imarkp = lp1; + + if (wheadp->w_markp == *dotp) + wheadp->w_markp = lp1; + } + + free((char *) (*dotp)); + *dotp = lp1; + } else { /* Easy: in place */ + (*dotp)->l_used += n; + cp2 = &(*dotp)->l_text[(*dotp)->l_used]; + cp1 = cp2-n; + while (cp1 != &(*dotp)->l_text[*doto]) + *--cp2 = *--cp1; + } + + ac.c = ((char)c & 0xff); + while(n--) /* add the chars */ + (*dotp)->l_text[(*doto)++] = ac; + + return(TRUE); +} + + +/* + * Insert a newline into the buffer at the current location of dot in the + * current window. The funny ass-backwards way it does things is not a botch; + * it just makes the last line in the file not a special case. Return TRUE if + * everything works out and FALSE on error (memory allocation failure). The + * update of dot and mark is a bit easier than in the above case, because the + * split forces more updating. + */ +lnewline() +{ + register CELL *cp1; + register CELL *cp2; + register LINE *lp1; + register LINE *lp2; + register int doto; + register WINDOW *wp; + + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + + lchange(WFHARD); + lp1 = curwp->w_dotp; /* Get the address and */ + doto = curwp->w_doto; /* offset of "." */ + if ((lp2=lalloc(doto)) == NULL) /* New first half line */ + return (FALSE); + + cp1 = &lp1->l_text[0]; /* Shuffle text around */ + cp2 = &lp2->l_text[0]; + while (cp1 != &lp1->l_text[doto]) + *cp2++ = *cp1++; + + cp2 = &lp1->l_text[0]; + while (cp1 != &lp1->l_text[lp1->l_used]) + *cp2++ = *cp1++; + + lp1->l_used -= doto; + lp2->l_bp = lp1->l_bp; + lp1->l_bp = lp2; + lp2->l_bp->l_fp = lp2; + lp2->l_fp = lp1; + wp = wheadp; /* Windows */ + while (wp != NULL) { + if (wp->w_linep == lp1) + wp->w_linep = lp2; + + if (wp->w_dotp == lp1) { + if (wp->w_doto < doto) + wp->w_dotp = lp2; + else + wp->w_doto -= doto; + } + + if (wp->w_imarkp == lp1) { /* ADDED for internal mark */ + if (wp->w_imarko < doto) + wp->w_imarkp = lp2; + else + wp->w_imarko -= doto; + } + + if (wp->w_markp == lp1) { + if (wp->w_marko < doto) + wp->w_markp = lp2; + else + wp->w_marko -= doto; + } + wp = wp->w_wndp; + } + + /* + * Keep track of the number of lines in the buffer. + */ + ++curbp->b_linecnt; + return (TRUE); +} + + +/* + * This function deletes "n" bytes, starting at dot. It understands how do deal + * with end of lines, etc. It returns TRUE if all of the characters were + * deleted, and FALSE if they were not (because dot ran into the end of the + * buffer. The "preserve" function is used to save what was deleted. + */ +ldelete(n, preserve) +long n; +int (*preserve) PROTO((int)); +{ + register CELL *cp1; + register CELL *cp2; + register LINE *dotp; + register int doto; + register int chunk; + register WINDOW *wp; + + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + + while (n != 0) { + dotp = curwp->w_dotp; + doto = curwp->w_doto; + if (dotp == curbp->b_linep) /* Hit end of buffer. */ + return (FALSE); + chunk = dotp->l_used-doto; /* Size of chunk. */ + if (chunk > n) + chunk = n; + if (chunk == 0) { /* End of line, merge. */ + lchange(WFHARD); + if (ldelnewline() == FALSE + || (preserve ? (*preserve)('\n') == FALSE : 0)) + return (FALSE); + --n; + continue; + } + + lchange(WFEDIT); + cp1 = &dotp->l_text[doto]; /* Scrunch text. */ + cp2 = cp1 + chunk; + if (preserve) { /* Kill? */ + while (cp1 != cp2) { + if ((*preserve)(cp1->c) == FALSE) + return (FALSE); + ++cp1; + } + cp1 = &dotp->l_text[doto]; + } + + while (cp2 != &dotp->l_text[dotp->l_used]) + *cp1++ = *cp2++; + + dotp->l_used -= chunk; + wp = wheadp; /* Fix windows */ + while (wp != NULL) { + if (wp->w_dotp==dotp && wp->w_doto>=doto) { + wp->w_doto -= chunk; + if (wp->w_doto < doto) + wp->w_doto = doto; + } + + if (wp->w_markp==dotp && wp->w_marko>=doto) { + wp->w_marko -= chunk; + if (wp->w_marko < doto) + wp->w_marko = doto; + } + + if (wp->w_imarkp==dotp && wp->w_imarko>=doto) { + wp->w_imarko -= chunk; + if (wp->w_imarko < doto) + wp->w_imarko = doto; + } + + wp = wp->w_wndp; + } + n -= chunk; + } + +#ifdef _WINDOWS + if (preserve == kinsert && ksize() > 0) + mswin_killbuftoclip (kremove); +#endif + + return (TRUE); +} + +/* + * Delete a newline. Join the current line with the next line. If the next line + * is the magic header line always return TRUE; merging the last line with the + * header line can be thought of as always being a successful operation, even + * if nothing is done, and this makes the kill buffer work "right". Easy cases + * can be done by shuffling data around. Hard cases require that lines be moved + * about in memory. Return FALSE on error and TRUE if all looks ok. Called by + * "ldelete" only. + */ +ldelnewline() +{ + register CELL *cp1; + register CELL *cp2; + register LINE *lp1; + register LINE *lp2; + register LINE *lp3; + register WINDOW *wp; + + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + + lp1 = curwp->w_dotp; + lp2 = lp1->l_fp; + if (lp2 == curbp->b_linep) { /* At the buffer end. */ + if (lp1->l_used == 0) { /* Blank line. */ + lfree(lp1); + --curbp->b_linecnt; + } + + return (TRUE); + } + + if (lp2->l_used <= lp1->l_size-lp1->l_used) { + cp1 = &lp1->l_text[lp1->l_used]; + cp2 = &lp2->l_text[0]; + while (cp2 != &lp2->l_text[lp2->l_used]) + *cp1++ = *cp2++; + + wp = wheadp; + while (wp != NULL) { + if (wp->w_linep == lp2) + wp->w_linep = lp1; + if (wp->w_dotp == lp2) { + wp->w_dotp = lp1; + wp->w_doto += lp1->l_used; + } + if (wp->w_markp == lp2) { + wp->w_markp = lp1; + wp->w_marko += lp1->l_used; + } + if (wp->w_imarkp == lp2) { + wp->w_imarkp = lp1; + wp->w_imarko += lp1->l_used; + } + wp = wp->w_wndp; + } + lp1->l_used += lp2->l_used; + lp1->l_fp = lp2->l_fp; + lp2->l_fp->l_bp = lp1; + free((char *) lp2); + --curbp->b_linecnt; + return (TRUE); + } + + if ((lp3=lalloc(lp1->l_used+lp2->l_used)) == NULL) + return (FALSE); + + cp1 = &lp1->l_text[0]; + cp2 = &lp3->l_text[0]; + while (cp1 != &lp1->l_text[lp1->l_used]) + *cp2++ = *cp1++; + + cp1 = &lp2->l_text[0]; + while (cp1 != &lp2->l_text[lp2->l_used]) + *cp2++ = *cp1++; + + lp1->l_bp->l_fp = lp3; + lp3->l_fp = lp2->l_fp; + lp2->l_fp->l_bp = lp3; + lp3->l_bp = lp1->l_bp; + wp = wheadp; + while (wp != NULL) { + if (wp->w_linep==lp1 || wp->w_linep==lp2) + wp->w_linep = lp3; + if (wp->w_dotp == lp1) + wp->w_dotp = lp3; + else if (wp->w_dotp == lp2) { + wp->w_dotp = lp3; + wp->w_doto += lp1->l_used; + } + if (wp->w_markp == lp1) + wp->w_markp = lp3; + else if (wp->w_markp == lp2) { + wp->w_markp = lp3; + wp->w_marko += lp1->l_used; + } + if (wp->w_imarkp == lp1) + wp->w_imarkp = lp3; + else if (wp->w_imarkp == lp2) { + wp->w_imarkp = lp3; + wp->w_imarko += lp1->l_used; + } + wp = wp->w_wndp; + } + + free((char *) lp1); + free((char *) lp2); + --curbp->b_linecnt; + return (TRUE); +} + + +/* + * Tell the caller if the given line is blank or not. + */ +lisblank(line) + LINE *line; +{ + int n = 0; + char qstr[NLINE]; + + n = ((glo_quote_str || (Pmaster && Pmaster->quote_str)) + && quote_match(glo_quote_str ? glo_quote_str : Pmaster->quote_str, + line, qstr, NLINE)) + ? strlen(qstr) : 0; + + for(; n < llength(line); n++) + if(!isspace((unsigned char) lgetc(line, n).c)) + return(FALSE); + + return(TRUE); +} + + +/* + * Delete all of the text saved in the kill buffer. Called by commands when a + * new kill context is being created. The kill buffer array is released, just + * in case the buffer has grown to immense size. No errors. + */ +void +kdelete() +{ + pkbufdel(&kbufp); +} + +void +fdelete() +{ + pkbufdel(&fbufp); +} + +void +pkbufdel(buf) + struct pkbuf **buf; +{ + if (*buf) { + pkchunkdel(&(*buf)->first); + free((char *) *buf); + *buf = NULL; + } +} + + +void +pkchunkdel(chunk) + struct pkchunk **chunk; +{ + if(chunk){ + if((*chunk)->next) + pkchunkdel(&(*chunk)->next); + + free((char *) *chunk); + *chunk = NULL; + } +} + + +/* + * Insert a character to the kill buffer, enlarging the buffer if there isn't + * any room. Always grow the buffer in chunks, on the assumption that if you + * put something in the kill buffer you are going to put more stuff there too + * later. Return TRUE if all is well, and FALSE on errors. + */ +kinsert(c) + int c; +{ + return(pkbufinsert(c, &kbufp)); +} + +finsert(c) + int c; +{ + return(pkbufinsert(c, &fbufp)); +} + +pkbufinsert(c, buf) + int c; + struct pkbuf **buf; +{ + if(!*buf){ + if(*buf = (struct pkbuf *) malloc(sizeof(struct pkbuf))) + memset(*buf, 0, sizeof(struct pkbuf)); + else + return(FALSE); + } + + if((*buf)->total % KBLOCK == 0){ + struct pkchunk *p = (*buf)->last; + if((*buf)->last = (struct pkchunk *) malloc(sizeof(struct pkchunk))){ + memset((*buf)->last, 0, sizeof(struct pkchunk)); + if(p) + p->next = (*buf)->last; + else + (*buf)->first = (*buf)->last; + } + else + return(FALSE); + } + + (*buf)->last->bufp[(*buf)->last->used++] = c; + (*buf)->total++; + return (TRUE); +} + + +/* + * These functions get characters from the requested buffer. If the + * character index "n" is off the end, it returns "-1". This lets the + * caller just scan along until it gets a "-1" back. + */ +kremove(n) + int n; +{ + return(pkbufremove(n, kbufp)); +} + +fremove(n) + int n; +{ + return(pkbufremove(n, fbufp)); +} + + +pkbufremove(n, buf) + int n; + struct pkbuf *buf; +{ + if(n >= 0 && buf && n < buf->total){ + register struct pkchunk *p = buf->first; + int block = n / KBLOCK; + + while(block--) + if(!(p = p->next)) + return(-1); + + return(p->bufp[n % KBLOCK] & 0xff); + } + else + return(-1); +} + + +/* + * This function just returns the current size of the kill buffer + */ +ksize() +{ + return(kbufp ? (int) kbufp->total : 0); +} diff --git a/main.c b/main.c new file mode 100755 index 0000000..e55ce3d --- /dev/null +++ b/main.c @@ -0,0 +1,707 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: main.c 13547 2004-03-26 22:36:45Z hubert $"; +#endif +/* + * Program: Main stand-alone Pine Composer routines + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + * + * WEEMACS/PICO NOTES: + * + * 08 Jan 92 - removed PINE defines to simplify compiling + * + * 08 Apr 92 - removed PINE stub calls + * + */ + +#include "headers.h" + + +/* + * Useful internal prototypes + */ +#ifdef _WINDOWS +int pico_file_drop PROTO((int, int, char *)); +#endif + +/* + * this isn't defined in the library, because it's a pine global + * which we use for GetKey's timeout + */ +int timeoutset = 0; + + +int my_timer_period = (300 * 1000); + +/* + * function key mappings + */ +static int fkm[12][2] = { + { F1, (CTRL|'G')}, + { F2, (CTRL|'X')}, + { F3, (CTRL|'O')}, + { F4, (CTRL|'J')}, + { F5, (CTRL|'R')}, + { F6, (CTRL|'W')}, + { F7, (CTRL|'Y')}, + { F8, (CTRL|'V')}, + { F9, (CTRL|'K')}, + { F10, (CTRL|'U')}, + { F11, (CTRL|'C')}, +#ifdef SPELLER + { F12, (CTRL|'T')} +#else + { F12, (CTRL|'D')} +#endif +}; + +char *pico_args PROTO((int, char **, int *, int *, int *, int *)); +void pico_args_help PROTO((void)); +void pico_vers_help PROTO((void)); +void pico_display_args_err PROTO((char *, char **, int)); + +char args_pico_missing_flag[] = "unknown flag \"%c\""; +char args_pico_missing_arg[] = "missing or empty argument to \"%c\" flag"; +char args_pico_missing_num[] = "non numeric argument for \"%c\" flag"; +char args_pico_missing_color[] = "missing color for \"%s\" flag"; + +char *args_pico_args[] = { +"Possible Starting Arguments for Pico editor:", +"", +"\tArgument\t\tMeaning", +"\t -e \t\tComplete - allow file name completion", +"\t -k \t\tCut - let ^K cut from cursor position to end of line", +"\t -a \t\tShowDot - show dot files in file browser", +"\t -j \t\tGoto - allow 'Goto' command in file browser", +"\t -g \t\tShow - show cursor in file browser", +"\t -m \t\tMouse - turn on mouse support", +"\t -x \t\tNoKeyhelp - suppress keyhelp", +"\t -p \t\tPreserveStartStop - preserve \"start\"(^Q) and \"stop\"(^S) characters", +"\t -q \t\tTermdefWins - termcap or terminfo takes precedence over defaults", +"\t -Q \tSet quote string (eg. \"> \") esp. for composing email", +"\t -d \t\tRebind - let delete key delete current character", +"\t -f \t\tKeys - force use of function keys", +"\t -b \t\tReplace - allow search and replace", +"\t -h \t\tHelp - give this list of options", +"\t -r[#cols] \tFill - set fill column to #cols columns, default=72", +"\t -n[#s] \tMail - notify about new mail every #s seconds, default=180", +"\t -s \tSpeller - specify alternative speller", +"\t -t \t\tShutdown - enable special shutdown mode", +"\t -o \tOperation - specify the operating directory", +"\t -z \t\tSuspend - allow use of ^Z suspension", +"\t -w \t\tNoWrap - turn off word wrap", +#if defined(DOS) || defined(OS2) +"\t -cnf color \tforeground color", +"\t -cnb color \tbackground color", +"\t -crf color \treverse foreground color", +"\t -crb color \treverse background color", +#endif +"\t +[line#] \tLine - start on line# line, default=1", +"\t -v \t\tView - view file", +"\t -setlocale_ctype\tdo setlocale(LC_CTYPE) if available", +"\t -no_setlocale_collate\tdo not do setlocale(LC_COLLATE)", +"\t -version\tPico version number", +"", +"\t All arguments may be followed by a file name to display.", +"", +NULL +}; + + +/* + * main standalone pico routine + */ +#ifdef _WINDOWS +app_main (argc, argv) +#else +main(argc, argv) +#endif +char *argv[]; +{ + register int c; + register int f; + register int n; + register BUFFER *bp; + int viewflag = FALSE; /* are we starting in view mode?*/ + int starton = 0; /* where's dot to begin with? */ + int setlocale_collate = 1; + int setlocale_ctype = 0; + char bname[NBUFN]; /* buffer name of file to read */ + char *file_to_edit = NULL; + + timeo = 600; + Pmaster = NULL; /* turn OFF composer functionality */ + km_popped = 0; + opertree[0] = opertree[NLINE] = '\0'; + browse_dir[0] = browse_dir[NLINE] = '\0'; + + /* + * Read command line flags before initializing, otherwise, we never + * know to init for f_keys... + */ + file_to_edit = pico_args(argc, argv, &starton, &viewflag, + &setlocale_collate, &setlocale_ctype); + + set_collation(setlocale_collate, setlocale_ctype); + +#if defined(DOS) || defined(OS2) + if(file_to_edit){ /* strip quotes? */ + int l; + + if(strchr("'\"", file_to_edit[0]) + && (l = strlen(file_to_edit)) > 1 + && file_to_edit[l-1] == file_to_edit[0]){ + file_to_edit[l-1] = '\0'; /* blat trailing quote */ + file_to_edit++; /* advance past leading quote */ + } + } +#endif + + if(!vtinit()) /* Displays. */ + exit(1); + + strcpy(bname, "main"); /* default buffer name */ + edinit(bname); /* Buffers, windows. */ + + update(); /* let the user know we are here */ + +#ifdef _WINDOWS + mswin_setwindow(NULL, NULL, NULL, NULL, NULL, NULL); + mswin_showwindow(); + mswin_showcaret(1); /* turn on for main window */ + mswin_allowpaste(MSWIN_PASTE_FULL); + mswin_setclosetext("Use the ^X command to exit Pico."); + mswin_setscrollcallback (pico_scroll_callback); +#endif + +#if defined(USE_TERMCAP) || defined(USE_TERMINFO) || defined(VMS) + if(kbesc == NULL){ /* will arrow keys work ? */ + (*term.t_putchar)('\007'); + emlwrite("Warning: keypad keys may non-functional", NULL); + } +#endif /* USE_TERMCAP/USE_TERMINFO/VMS */ + + if(file_to_edit){ /* Any file to edit? */ + + makename(bname, file_to_edit); /* set up a buffer for this file */ + + bp = curbp; /* read in first file */ + makename(bname, file_to_edit); + strcpy(bp->b_bname, bname); + + if(strlen(file_to_edit) >= NFILEN){ + char buf[128]; + + sprintf(buf, "Filename \"%.10s...\" too long", file_to_edit); + emlwrite(buf, NULL); + file_to_edit = NULL; + } + else{ + strcpy(bp->b_fname, file_to_edit); + if ((gmode&MDTREE) && !in_oper_tree(file_to_edit) || + readin(file_to_edit, (viewflag==FALSE), TRUE) == ABORT) { + if ((gmode&MDTREE) && !in_oper_tree(file_to_edit)) + emlwrite("Can't read file from outside of %s", opertree); + + file_to_edit = NULL; + } + } + + if(!file_to_edit){ + strcpy(bp->b_bname, "main"); + strcpy(bp->b_fname, ""); + } + + bp->b_dotp = bp->b_linep; + bp->b_doto = 0; + + if (viewflag) /* set the view mode */ + bp->b_mode |= MDVIEW; + } + + /* setup to process commands */ + lastflag = 0; /* Fake last flags. */ + curbp->b_mode |= gmode; /* and set default modes*/ + + curwp->w_flag |= WFMODE; /* and force an update */ + + if(timeoutset) + emlwrite("Checking for new mail every %D seconds", (void *)timeo); + + forwline(0, starton - 1); /* move dot to specified line */ + + while(1){ + + if(km_popped){ + km_popped--; + if(km_popped == 0) /* cause bottom three lines to be repainted */ + curwp->w_flag |= WFHARD; + } + + if(km_popped){ /* temporarily change to cause menu to be painted */ + term.t_mrow = 2; + curwp->w_ntrows -= 2; + curwp->w_flag |= WFMODE; + movecursor(term.t_nrow-2, 0); /* clear status line, too */ + peeol(); + } + + update(); /* Fix up the screen */ + if(km_popped){ + term.t_mrow = 0; + curwp->w_ntrows += 2; + } + +#ifdef MOUSE +#ifdef EX_MOUSE + /* New mouse function for real mouse text seletion. */ + register_mfunc(mouse_in_pico, 2, 0, term.t_nrow - (term.t_mrow + 1), + term.t_ncol); +#else + mouse_in_content(KEY_MOUSE, -1, -1, 0, 0); + register_mfunc(mouse_in_content, 2, 0, term.t_nrow - (term.t_mrow + 1), + term.t_ncol); +#endif +#endif +#ifdef _WINDOWS + mswin_setdndcallback (pico_file_drop); + mswin_mousetrackcallback(pico_cursor); +#endif + c = GetKey(); +#ifdef MOUSE +#ifdef EX_MOUSE + clear_mfunc(mouse_in_pico); +#else + clear_mfunc(mouse_in_content); +#endif +#endif +#ifdef _WINDOWS + mswin_cleardndcallback (); + mswin_mousetrackcallback(NULL); +#endif + + if(timeoutset && (c == NODATA || time_to_check())){ + if(pico_new_mail()) + emlwrite("You may possibly have new mail.", NULL); + } + + if(km_popped) + switch(c){ + case NODATA: + case (CTRL|'L'): + km_popped++; + break; + + default: + /* clear bottom three lines */ + mlerase(); + break; + } + + if(c == NODATA) + continue; + + if(mpresf){ /* erase message line? */ + if(mpresf++ > MESSDELAY) + mlerase(); + } + + f = FALSE; + n = 1; + +#ifdef MOUSE + clear_mfunc(mouse_in_content); +#endif + /* Do it. */ + execute(normalize_cmd(c, fkm, 1), f, n); + } +} + + +/* + * Parse the command line args. + * + * Args ac + * av + * starton -- place to return starton value + * viewflag -- place to return viewflag value + * + * Result: command arguments parsed + * possible printing of help for command line + * various global flags set + * returns the name of any file to open, else NULL + */ +char * +pico_args(ac, av, starton, viewflag, setlocale_collate, setlocale_ctype) + int ac; + char **av; + int *starton; + int *viewflag; + int *setlocale_collate; + int *setlocale_ctype; +{ + int c, usage = 0; + char *str; + char tmp_1k_buf[1000]; /* tmp buf to contain err msgs */ + +Loop: + /* while more arguments with leading - or + */ + while(--ac > 0 && (**++av == '-' || **av == '+')){ + if(**av == '+'){ + if(*++*av) + str = *av; + else if(--ac) + str = *++av; + else{ + sprintf(tmp_1k_buf, args_pico_missing_arg, '+'); + pico_display_args_err(tmp_1k_buf, NULL, 1); + usage++; + goto Loop; + } + + if(!isdigit((unsigned char)str[0])){ + sprintf(tmp_1k_buf, args_pico_missing_num, '+'); + pico_display_args_err(tmp_1k_buf, NULL, 1); + usage++; + } + + if(starton) + *starton = atoi(str); + + goto Loop; + } + + /* while more chars in this argument */ + else while(*++*av){ + + if(strcmp(*av, "version") == 0){ + pico_vers_help(); + } + else if(strcmp(*av, "setlocale_ctype") == 0){ + *setlocale_ctype = 1; + goto Loop; + } + else if(strcmp(*av, "no_setlocale_collate") == 0){ + *setlocale_collate = 0; + goto Loop; + } +#if defined(DOS) || defined(OS2) + else if(strcmp(*av, "cnf") == 0 + || strcmp(*av, "cnb") == 0 + || strcmp(*av, "crf") == 0 + || strcmp(*av, "crb") == 0){ + + char *cmd = *av; /* save it to use below */ + + if(--ac){ + str = *++av; + if(cmd[1] == 'n'){ + if(cmd[2] == 'f') + pico_nfcolor(str); + else if(cmd[2] == 'b') + pico_nbcolor(str); + } + else if(cmd[1] == 'r'){ + if(cmd[2] == 'f') + pico_rfcolor(str); + else if(cmd[2] == 'b') + pico_rbcolor(str); + } + } + else{ + sprintf(tmp_1k_buf, args_pico_missing_color, cmd); + pico_display_args_err(tmp_1k_buf, NULL, 1); + usage++; + } + + goto Loop; + } +#endif + + /* + * Single char options. + */ + switch(c = **av){ + /* + * These don't take arguments. + */ + case 'a': + gmode ^= MDDOTSOK; /* show dot files */ + break; + case 'b': + gmode ^= MDREPLACE; /* -b for replace string in where is command */ + break; + case 'd': /* -d for rebind delete key */ + bindtokey(0x7f, forwdel); + break; + case 'e': /* file name completion */ + gmode ^= MDCMPLT; + break; + case 'f': /* -f for function key use */ + gmode ^= MDFKEY; + break; + case 'g': /* show-cursor in file browser */ + gmode ^= MDSHOCUR; + break; + case 'h': + usage++; + break; + case 'j': /* allow "Goto" in file browser */ + gmode ^= MDGOTO; + break; + case 'k': /* kill from dot */ + gmode ^= MDDTKILL; + break; + case 'm': /* turn on mouse support */ + gmode ^= MDMOUSE; + break; + case 'p': + preserve_start_stop = 1; + break; + case 'q': /* -q for termcap takes precedence */ + gmode ^= MDTCAPWINS; + break; + case 't': /* special shutdown mode */ + gmode ^= MDTOOL; + rebindfunc(wquit, quickexit); + break; + case 'v': /* -v for View File */ + case 'V': + *viewflag = !*viewflag; + break; /* break back to inner-while */ + case 'w': /* -w turn off word wrap */ + gmode ^= MDWRAP; + break; + case 'x': /* suppress keyhelp */ + sup_keyhelp = !sup_keyhelp; + break; + case 'z': /* -z to suspend */ + gmode ^= MDSSPD; + break; + + /* + * These do take arguments. + */ + case 'r': /* set fill column */ + case 'n': /* -n for new mail notification */ + case 's' : /* speller */ + case 'o' : /* operating tree */ + case 'Q' : /* Quote string */ + if(*++*av) + str = *av; + else if(--ac) + str = *++av; + else{ + if(c == 'r') + str= "72"; + else if(c == 'n') + str = "180"; + else{ + sprintf(tmp_1k_buf, args_pico_missing_arg, c); + pico_display_args_err(tmp_1k_buf, NULL, 1); + usage++; + goto Loop; + } + } + + switch(c){ + case 's': + alt_speller = str; + break; + case 'o': + strncpy(opertree, str, NLINE); + gmode ^= MDTREE; + break; + case 'Q': + strncpy(glo_quote_str_buf, str, NLINE); + glo_quote_str = glo_quote_str_buf; + break; + + /* numeric args */ + case 'r': + case 'n': + if(!isdigit((unsigned char)str[0])){ + sprintf(tmp_1k_buf, args_pico_missing_num, c); + pico_display_args_err(tmp_1k_buf, NULL, 1); + usage++; + } + + if(c == 'r'){ + if((userfillcol = atoi(str)) < 1) + userfillcol = 72; + } + else{ + timeoutset = 1; + timeo = 180; + if((timeo = atoi(str)) < 30) + timeo = 180; + } + + break; + } + + goto Loop; + + default: /* huh? */ + sprintf(tmp_1k_buf, args_pico_missing_flag, c); + pico_display_args_err(tmp_1k_buf, NULL, 1); + usage++; + break; + } + } + } + + if(usage) + pico_args_help(); + + /* return the first filename for editing */ + if(ac > 0) + return(*av); + else + return(NULL); +} + + +#ifdef _WINDOWS +/* + * + */ +int +pico_file_drop(x, y, filename) + int x, y; + char *filename; +{ + /* + * if current buffer is unchanged + * *or* "new buffer" and no current text + */ + if(((curwp->w_bufp->b_flag & BFCHG) == 0) + || (curwp->w_bufp->b_fname[0] == '\0' + && curwp->w_bufp->b_linep == lforw(curwp->w_bufp->b_linep) + && curwp->w_doto == 0)){ + register BUFFER *bp = curwp->w_bufp; + char bname[NBUFN]; + + makename(bname, filename); + strcpy(bp->b_bname, bname); + strcpy(bp->b_fname, filename); + bp->b_flag &= ~BFCHG; /* turn off change bit */ + if (readin(filename, 1, 1) == ABORT) { + strcpy(bp->b_bname, ""); + strcpy(bp->b_fname, ""); + } + bp->b_dotp = bp->b_linep; + bp->b_doto = 0; + } + else{ + ifile(filename); + curwp->w_flag |= WFHARD; + update(); + emlwrite("Inserted dropped file \"%s\"", filename); + } + + curwp->w_flag |= WFHARD; + update(); /* restore cursor */ + return(1); +} +#endif + + +/*---------------------------------------------------------------------- + print a few lines of help for command line arguments + + Args: none + + Result: prints help messages + ----------------------------------------------------------------------*/ +void +pico_args_help() +{ + /** print out possible starting arguments... **/ + pico_display_args_err(NULL, args_pico_args, 0); + exit(1); +} + + +void +pico_vers_help() +{ + char v0[100]; + char *v[2]; + + sprintf(v0, "Pico %.50s", version); + v[0] = v0; + v[1] = NULL; + + pico_display_args_err(NULL, v, 0); + exit(1); +} + + +/*---------------------------------------------------------------------- + write argument error to the display... + + Args: none + + Result: prints help messages + ----------------------------------------------------------------------*/ +void +pico_display_args_err(s, a, err) + char *s; + char **a; + int err; +{ + char errstr[256], *errp; + FILE *fp = err ? stderr : stdout; +#ifdef _WINDOWS + char tmp_20k_buf[20480]; +#endif + + + if(err && s) + sprintf(errp = errstr, "Argument Error: %.200s", s); + else + errp = s; + +#ifdef _WINDOWS + if(errp) + mswin_messagebox(errp, err); + + if(a && *a){ + strcpy(tmp_20k_buf, *a++); + while(a && *a){ + strcat(tmp_20k_buf, "\n"); + strcat(tmp_20k_buf, *a++); + } + + mswin_messagebox(tmp_20k_buf, err); + } +#else + if(errp) + fprintf(fp, "%s\n", errp); + + while(a && *a) + fprintf(fp, "%s\n", *a++); +#endif +} diff --git a/makefile.3b1 b/makefile.3b1 new file mode 100644 index 0000000..9c66cec --- /dev/null +++ b/makefile.3b1 @@ -0,0 +1,94 @@ +## $Id: makefile.3b1 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for Convergent Technologies made for AT&T 3b1 and 7300 computers +# version of the PINE composer library and stand-alone editor pico. +# +# Port Contributor: Robert Lewis +# + +include $(MAKEINC)/Makepre.h + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O2 +PROFILE= # -pg +DEBUG= # -g -DDEBUG + +STDCFLAGS= -Dct -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= : + +LIBS= $(EXTRALDFLAGS) -ltermcap + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(LD) $(LDFLAGS) -s libpico.a $(SHAREDLIB) -o pico +# $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(LD) $(LDFLAGS) -s libpico.a $(SHAREDLIB) -o pilot +# $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-3b1.h + $(RM) os.h + $(LN) osdep/os-3b1.h os.h + +pico_os.c: osdep/os-3b1.c + $(RM) pico_os.c + $(LN) osdep/os-3b1.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-3b1.c: osdep/header osdep/unix osdep/read.sel osdep/raw.io \ + osdep/spell.unx osdep/term.cap \ + osdep/os-3b1.ic + cd osdep; $(MAKE) includer os-3b1.c; cd .. diff --git a/makefile.a32 b/makefile.a32 new file mode 100644 index 0000000..e0fcf0b --- /dev/null +++ b/makefile.a32 @@ -0,0 +1,88 @@ +# $Id: makefile.a32 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for AIX 3.2 version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -D_ALL_SOURCE -Da32 -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= : + +LIBS= $(EXTRALDFLAGS) -lcurses -lc + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-a32.h + $(RM) os.h + $(LN) osdep/os-a32.h os.h + +pico_os.c: osdep/os-a32.c + $(RM) pico_os.c + $(LN) osdep/os-a32.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-a32.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.cap \ + osdep/os-a32.ic + cd osdep; $(MAKE) includer os-a32.c; cd .. diff --git a/makefile.a41 b/makefile.a41 new file mode 100644 index 0000000..9ad61a1 --- /dev/null +++ b/makefile.a41 @@ -0,0 +1,88 @@ +# $Id: makefile.a41 13476 2004-02-24 22:11:23Z jpf $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for AIX 4.1 version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -D_ALL_SOURCE -Da41 -DJOB_CONTROL -DPOSIX -DMOUSE -qro -qroconst +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= : + +LIBS= $(EXTRALDFLAGS) -lcurses -lc + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-a41.h + $(RM) os.h + $(LN) osdep/os-a41.h os.h + +pico_os.c: osdep/os-a41.c + $(RM) pico_os.c + $(LN) osdep/os-a41.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-a41.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.inf \ + osdep/os-a41.ic + cd osdep; $(MAKE) includer os-a41.c; cd .. diff --git a/makefile.aix b/makefile.aix new file mode 100644 index 0000000..061f817 --- /dev/null +++ b/makefile.aix @@ -0,0 +1,88 @@ +# $Id: makefile.aix 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for AIX 370 version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -I/usr/include -Daix -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap -lc + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-aix.h + $(RM) os.h + $(LN) osdep/os-aix.h os.h + +pico_os.c: osdep/os-aix.c + $(RM) pico_os.c + $(LN) osdep/os-aix.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-aix.c: osdep/header osdep/unix osdep/read.sel osdep/raw.brk \ + osdep/spell.unx osdep/term.cap \ + osdep/os-aix.ic + cd osdep; $(MAKE) includer os-aix.c; cd .. diff --git a/makefile.att b/makefile.att new file mode 100644 index 0000000..f5fd473 --- /dev/null +++ b/makefile.att @@ -0,0 +1,89 @@ +## $Id: makefile.att 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for ?? version of the PINE composer library and +# stand-alone editor pico. +# Port Contributor: Robert Lewis +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= # -g -DDEBUG + +STDCFLAGS= -Dsv3 -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= : + +LIBS= $(EXTRALDFLAGS) -ltermcap -lc -lc_s + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-att.h + $(RM) os.h + $(LN) osdep/os-att.h os.h + +pico_os.c: osdep/os-att.c + $(RM) pico_os.c + $(LN) osdep/os-att.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-att.c: osdep/header osdep/unix osdep/read.sel osdep/raw.io \ + osdep/spell.unx osdep/term.cap \ + osdep/os-att.ic + cd osdep; $(MAKE) includer os-att.c; cd .. diff --git a/makefile.aux b/makefile.aux new file mode 100644 index 0000000..94f0a2f --- /dev/null +++ b/makefile.aux @@ -0,0 +1,88 @@ +# $Id: makefile.aux 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for A/UX version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dconst= -DAUX -DJOB_CONTROL -D_POSIX_SOURCE -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= -ru +RANLIB= /bin/true + +LIBS= $(EXTRALDFLAGS) -ltermcap -lposix + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-aux.h + $(RM) os.h + $(LN) osdep/os-aux.h os.h + +pico_os.c: osdep/os-aux.c + $(RM) pico_os.c + $(LN) osdep/os-aux.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-aux.c: osdep/header osdep/unix osdep/read.sel osdep/raw.io \ + osdep/spell.unx osdep/term.cap \ + osdep/os-aux.ic + cd osdep; $(MAKE) includer os-aux.c; cd .. diff --git a/makefile.bs2 b/makefile.bs2 new file mode 100644 index 0000000..3787e7e --- /dev/null +++ b/makefile.bs2 @@ -0,0 +1,88 @@ +# $Id: makefile.bs2 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for BSDI V2-V4 version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -DBSDI -DBSDI2 -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-bs2.h + $(RM) os.h + $(LN) osdep/os-bs2.h os.h + +pico_os.c: osdep/os-bs2.c + $(RM) pico_os.c + $(LN) osdep/os-bs2.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-bs2.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.cap \ + osdep/os-bs2.ic + cd osdep; $(MAKE) includer os-bs2.c; cd .. diff --git a/makefile.bsd b/makefile.bsd new file mode 100644 index 0000000..0da340e --- /dev/null +++ b/makefile.bsd @@ -0,0 +1,89 @@ +# $Id: makefile.bsd 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for BSD 4.3 version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dconst= -Dbsd -DJOB_CONTROL +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap -lc + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-bsd.h + $(RM) os.h + $(LN) osdep/os-bsd.h os.h + +pico_os.c: osdep/os-bsd.c + $(RM) pico_os.c + $(LN) osdep/os-bsd.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-bsd.c: osdep/header osdep/unix osdep/read.sel osdep/raw.brk \ + osdep/spell.unx osdep/term.cap \ + osdep/getcwd \ + osdep/os-bsd.ic + cd osdep; $(MAKE) includer os-bsd.c; cd .. diff --git a/makefile.bsf b/makefile.bsf new file mode 100644 index 0000000..bc73906 --- /dev/null +++ b/makefile.bsf @@ -0,0 +1,90 @@ +# $Id: makefile.bsf 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for FreeBSD shared-lib version of the PINE composer library and +# stand-alone editor pico. +# +# Port Contributor: Josh Gilliam +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -DDEBUG # -g + +STDCFLAGS= -DBSDI -DBSDI2 -DPOSIX -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-bsf.h + $(RM) os.h + $(LN) osdep/os-bsf.h os.h + +pico_os.c: osdep/os-bsf.c + $(RM) pico_os.c + $(LN) osdep/os-bsf.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-bsf.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.cap \ + osdep/os-bsf.ic + cd osdep; $(MAKE) includer os-bsf.c; cd .. diff --git a/makefile.bsi b/makefile.bsi new file mode 100644 index 0000000..c003e95 --- /dev/null +++ b/makefile.bsi @@ -0,0 +1,88 @@ +# $Id: makefile.bsi 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for BSDI V1 version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -DBSDI -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-bsi.h + $(RM) os.h + $(LN) osdep/os-bsi.h os.h + +pico_os.c: osdep/os-bsi.c + $(RM) pico_os.c + $(LN) osdep/os-bsi.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-bsi.c: osdep/header osdep/unix osdep/read.sel osdep/raw.brk \ + osdep/spell.unx osdep/term.cap \ + osdep/os-bsi.ic + cd osdep; $(MAKE) includer os-bsi.c; cd .. diff --git a/makefile.bso b/makefile.bso new file mode 100644 index 0000000..b40ed59 --- /dev/null +++ b/makefile.bso @@ -0,0 +1,102 @@ +# $Id: makefile.bso 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1999 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for OpenBSD shared-lib version of the PINE composer library and +# stand-alone editor pico. +# +# Port Contributor: Marco S Hyman +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -DDEBUG # -g + +STDCFLAGS= -DBSDI -DBSDI2 -DPOSIX -DJOB_CONTROL -DMOUSE +CFLAGS+= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +SOFILES= ${OFILES:.o=.so} + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# Need this for the shared library rule to work correctly +.SUFFIXES: .o .so + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o -L. -lpico $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o -L. -lpico $(LIBS) -o pilot + +.c.so: ; $(CC) -fpic -DPIC -c $(CFLAGS) ${@:.so=.c} -o $@ + +.c.o: ; $(CC) -c $(CFLAGS) $*.c + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +libpico.so.1.3: $(SOFILES) + ld -Bshareable -x -o libpico.so.1.3 $(SOFILES) + +clean: + rm -f *.a *.so.1.3 *.o *.so *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-bso.h + $(RM) os.h + $(LN) osdep/os-bso.h os.h + +pico_os.c: osdep/os-bso.c + $(RM) pico_os.c + $(LN) osdep/os-bso.c pico_os.c + +$(SOFILES) $(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-bso.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.cap \ + osdep/os-bso.ic + cd osdep; $(MAKE) includer os-bso.c; cd .. diff --git a/makefile.cvx b/makefile.cvx new file mode 100644 index 0000000..2ea6deb --- /dev/null +++ b/makefile.cvx @@ -0,0 +1,88 @@ +# $Id: makefile.cvx 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for Convex version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -cxdb -DDEBUG + +STDCFLAGS= -Dconst= -Dcvx -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap -lc + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot .XCdb/* + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-cvx.h + $(RM) os.h + $(LN) osdep/os-cvx.h os.h + +pico_os.c: osdep/os-cvx.c + $(RM) pico_os.c + $(LN) osdep/os-cvx.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-cvx.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.cap \ + osdep/os-cvx.ic + cd osdep; $(MAKE) includer os-cvx.c; cd .. diff --git a/makefile.cyg b/makefile.cyg new file mode 100644 index 0000000..88e6dbc --- /dev/null +++ b/makefile.cyg @@ -0,0 +1,90 @@ +# $Id: makefile.cyg 12623 2002-11-15 16:34:35Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-2002 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for Cygwin version of the PINE composer library and +# stand-alone editor pico. +# +# Port Contributor: Eduardo Chappa +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -DCYGWIN -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALIBES) -ltermcap + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico.exe pilot.exe + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-cyg.h + $(RM) os.h + $(LN) osdep/os-cyg.h os.h + +pico_os.c: osdep/os-cyg.c + $(RM) pico_os.c + $(LN) osdep/os-cyg.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-cyg.c: osdep/header osdep/unix osdep/read.sel osdep/raw.io \ + osdep/spell.unx osdep/term.cap \ + osdep/os-cyg.ic + cd osdep; $(MAKE) includer os-cyg.c; cd .. diff --git a/makefile.d-g b/makefile.d-g new file mode 100644 index 0000000..6698af6 --- /dev/null +++ b/makefile.d-g @@ -0,0 +1,91 @@ +# $Id: makefile.d-g 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for DG/UX version of the PINE composer library and +# stand-alone editor pico. +# +# [Port courtesy of Jeff Ferguson ] +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dsv4 -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= true + +LIBS= $(EXTRALDFLAGS) -l`case \`uname -r\` in R4.11*) echo "nsl"\ + ;; *) echo "nsl_s";;esac` -lgen -lcurses + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-sv4.h + $(RM) os.h + $(LN) osdep/os-sv4.h os.h + +pico_os.c: osdep/os-sv4.c + $(RM) pico_os.c + $(LN) osdep/os-sv4.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-sv4.c: osdep/header osdep/unix osdep/read.pol osdep/raw.ios \ + osdep/spell.unx osdep/term.inf \ + osdep/os-sv4.ic + cd osdep; $(MAKE) includer os-sv4.c; cd .. diff --git a/makefile.dpx b/makefile.dpx new file mode 100644 index 0000000..9e95484 --- /dev/null +++ b/makefile.dpx @@ -0,0 +1,95 @@ +# $Id: makefile.dpx 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for Bull DPX/2 B.O.S version of the PINE composer library and +# stand-alone editor pico. +# +# [Port courtesy of David Brownlee ] +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +#for GNU C +#CC= gcc +#STDCFLAGS= -Ddpx -DJOB_CONTROL -DPOSIX -ansi -DMOUSE + +#otherwise +STDCFLAGS= -Dconst= -Ddpx -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= true + +LIBS= $(EXTRALDFLAGS) -lcurses + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-dpx.h + $(RM) os.h + $(LN) osdep/os-dpx.h os.h + +pico_os.c: osdep/os-dpx.c + $(RM) pico_os.c + $(LN) osdep/os-dpx.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-dpx.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.cap \ + osdep/os-dpx.ic + cd osdep; $(MAKE) includer os-dpx.c; cd .. diff --git a/makefile.dyn b/makefile.dyn new file mode 100644 index 0000000..31ad50c --- /dev/null +++ b/makefile.dyn @@ -0,0 +1,88 @@ +# $Id: makefile.dyn 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for Dynix version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dconst= -Ddyn -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap -lc + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-dyn.h + $(RM) os.h + $(LN) osdep/os-dyn.h os.h + +pico_os.c: osdep/os-dyn.c + $(RM) pico_os.c + $(LN) osdep/os-dyn.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-dyn.c: osdep/header osdep/unix osdep/read.sel osdep/raw.brk \ + osdep/spell.unx osdep/term.cap osdep/getcwd \ + osdep/os-dyn.ic + cd osdep; $(MAKE) includer os-dyn.c; cd .. diff --git a/makefile.epx b/makefile.epx new file mode 100644 index 0000000..62380a8 --- /dev/null +++ b/makefile.epx @@ -0,0 +1,91 @@ +# $Id: makefile.epx 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for EP/IX version of the PINE composer library and +# stand-alone editor pico. +# +# [Port courtesy of Ed Greshko - hubert, 960313] +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dsv4 -DJOB_CONTROL -DPOSIX -DMOUSE -systype svr4 +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) \ + -Olimit 800 + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= true + +LIBS= $(EXTRALDFLAGS) -ltermlib + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-sv4.h + $(RM) os.h + $(LN) osdep/os-sv4.h os.h + +pico_os.c: osdep/os-sv4.c + $(RM) pico_os.c + $(LN) osdep/os-sv4.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-sv4.c: osdep/header osdep/unix osdep/read.pol osdep/raw.ios \ + osdep/spell.unx osdep/term.inf \ + osdep/os-sv4.ic + cd osdep; $(MAKE) includer os-sv4.c; cd .. diff --git a/makefile.ga4 b/makefile.ga4 new file mode 100644 index 0000000..f1fdaa5 --- /dev/null +++ b/makefile.ga4 @@ -0,0 +1,88 @@ +# $Id: makefile.ga4 13483 2004-02-25 22:33:10Z jpf $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for AIX 4.1 version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -D_ALL_SOURCE -Da41 -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= : + +LIBS= $(EXTRALDFLAGS) -lcurses -lc + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-a41.h + $(RM) os.h + $(LN) osdep/os-a41.h os.h + +pico_os.c: osdep/os-a41.c + $(RM) pico_os.c + $(LN) osdep/os-a41.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-a41.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.inf \ + osdep/os-a41.ic + cd osdep; $(MAKE) includer os-a41.c; cd .. diff --git a/makefile.gen b/makefile.gen new file mode 100644 index 0000000..289dbd7 --- /dev/null +++ b/makefile.gen @@ -0,0 +1,89 @@ +# $Id: makefile.gen 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for a generic version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -DGEN -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermlib + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-gen.h + $(RM) os.h + $(LN) osdep/os-gen.h os.h + +pico_os.c: osdep/os-gen.c + $(RM) pico_os.c + $(LN) osdep/os-gen.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +# The dependencies here will be slightly different for each port. +osdep/os-gen.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.cap \ + osdep/os-gen.ic + cd osdep; $(MAKE) includer os-gen.c; cd .. diff --git a/makefile.gh9 b/makefile.gh9 new file mode 100644 index 0000000..61673eb --- /dev/null +++ b/makefile.gh9 @@ -0,0 +1,89 @@ +# $Id: makefile.gh9 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for HP/UX 9.x version of the PINE composer library and +# stand-alone editor pico. (using gcc) +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +CC= gcc +STDCFLAGS= -Dhpp -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= : + +LIBS= $(EXTRALDFLAGS) -ltermcap -lV3 + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $& $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-hpp.h + $(RM) os.h + $(LN) osdep/os-hpp.h os.h + +pico_os.c: osdep/os-hpp.c + $(RM) pico_os.c + $(LN) osdep/os-hpp.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-hpp.c: osdep/header osdep/unix osdep/read.sel osdep/raw.io \ + osdep/spell.unx osdep/term.cap \ + osdep/os-hpp.ic + cd osdep; $(MAKE) includer os-hpp.c; cd .. diff --git a/makefile.go5 b/makefile.go5 new file mode 100644 index 0000000..f192bb6 --- /dev/null +++ b/makefile.go5 @@ -0,0 +1,94 @@ +# $Id: makefile.go5 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-2001 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for Open Server 5 with gcc version of the PINE composer library and +# stand-alone editor pico. +# +# Port courtesy of Tim Rice . +# + +RM= rm -f +LN= ln -s +MAKE= make +SHELL= /bin/sh +OPTIMIZE= # -O3 +PROFILE= # -pg +DEBUG= # -g -DDEBUG + +STDCFLAGS= -Dsco -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= true + +# When USE_TERMINFO is defined link with library tinfo. +LIBS= $(EXTRALDFLAGS) -ltinfo -lc +# When USE_TERMCAP is defined link with library termcap. +#LIBS= $(EXTRALIBES) -ltermcap -lc -lc_s -lx + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-sc5.h + $(RM) os.h + $(LN) osdep/os-sc5.h os.h + +pico_os.c: osdep/os-sc5.c + $(RM) pico_os.c + $(LN) osdep/os-sc5.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-sc5.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.inf \ + osdep/os-sc5.ic + cd osdep; $(MAKE) includer os-sc5.c; cd .. diff --git a/makefile.gso b/makefile.gso new file mode 100644 index 0000000..1d06313 --- /dev/null +++ b/makefile.gso @@ -0,0 +1,99 @@ +# $Id: makefile.gso 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for Sun Solaris version of the PINE composer library and +# stand-alone editor pico. (using gcc) +# +# [Port courtesy of Marc Unangst - mss, 921020] +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +CC= gcc +LDCC= gcc +# LDCC= /usr/bin/cc +# If you don't have /usr/bin/cc (our Solaris 2.2 doesn't seem to have it, +# it only has /usr/ucb/cc) then change LDCC to the following line and +# give that a try. This is still using the Solaris compiler but +# leaving out the UCB compatibility includes and libraries. +# LDCC= cc5.sol + +STDCFLAGS= -Dsv4 -DPOSIX -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= true + +LIBS= $(EXTRALDFLAGS) -ltermlib + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $& $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-gso.h + $(RM) os.h + $(LN) osdep/os-gso.h os.h + +pico_os.c: osdep/os-sv4.c + $(RM) pico_os.c + $(LN) osdep/os-sv4.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-sv4.c: osdep/header osdep/unix osdep/read.pol osdep/raw.ios \ + osdep/spell.unx osdep/term.cap \ + osdep/os-sv4.ic + cd osdep; $(MAKE) includer os-sv4.c; cd .. diff --git a/makefile.gsu b/makefile.gsu new file mode 100644 index 0000000..be92f7a --- /dev/null +++ b/makefile.gsu @@ -0,0 +1,89 @@ +# $Id: makefile.gsu 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for SunOS 4.1 version of the PINE composer library and +# stand-alone editor pico. (using gcc) +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +CC= gcc +STDCFLAGS= -Dsun -Dgsu -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap -lc -ldl + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-gsu.h + $(RM) os.h + $(LN) osdep/os-gsu.h os.h + +pico_os.c: osdep/os-sun.c + $(RM) pico_os.c + $(LN) osdep/os-sun.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-sun.c: osdep/header osdep/unix osdep/read.sel osdep/raw.brk \ + osdep/spell.unx osdep/term.cap \ + osdep/os-sun.ic + cd osdep; $(MAKE) -f makefile.dl includer os-sun.c; cd .. diff --git a/makefile.gul b/makefile.gul new file mode 100644 index 0000000..d21716f --- /dev/null +++ b/makefile.gul @@ -0,0 +1,89 @@ +# $Id: makefile.gul 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for RISC Ultrix 4.1 version of the PINE composer library and +# stand-alone editor pico. (using gcc) +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +CC= gcc +STDCFLAGS= -Dult -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap -lc + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-ult.h + $(RM) os.h + $(LN) osdep/os-ult.h os.h + +pico_os.c: osdep/os-ult.c + $(RM) pico_os.c + $(LN) osdep/os-ult.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-ult.c: osdep/header osdep/unix osdep/read.sel osdep/raw.brk \ + osdep/spell.unx osdep/term.cap \ + osdep/os-ult.ic + cd osdep; $(MAKE) includer os-ult.c; cd .. diff --git a/makefile.hpp b/makefile.hpp new file mode 100644 index 0000000..f435849 --- /dev/null +++ b/makefile.hpp @@ -0,0 +1,90 @@ +# $Id: makefile.hpp 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for HP/UX version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dconst= -Aa -D_HPUX_SOURCE -Dhpp -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= : + +LIBS= $(EXTRALDFLAGS) -ltermcap -lV3 + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(PURIFY) $(PURIFYOPTIONS) $(CC) $(CFLAGS) main.o \ + libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(PURIFY) $(PURIFYOPTIONS) $(CC) $(CFLAGS) pilot.o \ + libpico.a $(LIBS) -o pilot + +libpico.a: $& $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-hpp.h + $(RM) os.h + $(LN) osdep/os-hpp.h os.h + +pico_os.c: osdep/os-hpp.c + $(RM) pico_os.c + $(LN) osdep/os-hpp.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-hpp.c: osdep/header osdep/unix osdep/read.sel osdep/raw.io \ + osdep/spell.unx osdep/term.cap \ + osdep/os-hpp.ic + cd osdep; $(MAKE) includer os-hpp.c; cd .. diff --git a/makefile.isc b/makefile.isc new file mode 100644 index 0000000..4414a98 --- /dev/null +++ b/makefile.isc @@ -0,0 +1,89 @@ +# $Id: makefile.isc 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for ISC Unix version of the PINE composer library and +# stand-alone editor pico. +# Contributed by Andy Brager +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -I/usr/include -Disc -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= echo + +LIBS= $(EXTRALDFLAGS) -ltermcap -lc -lcposix -linet + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-isc.h + $(RM) os.h + $(LN) osdep/os-isc.h os.h + +pico_os.c: osdep/os-isc.c + $(RM) pico_os.c + $(LN) osdep/os-isc.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-isc.c: osdep/header osdep/unix osdep/read.sel osdep/raw.io \ + osdep/spell.unx osdep/term.cap osdep/truncate \ + osdep/os-isc.ic + cd osdep; $(MAKE) includer os-isc.c; cd .. diff --git a/makefile.lnx b/makefile.lnx new file mode 100644 index 0000000..3ee2a8a --- /dev/null +++ b/makefile.lnx @@ -0,0 +1,94 @@ +# $Id: makefile.lnx 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for Linux version of the PINE composer library and +# stand-alone editor pico. +# +# NOTE: We are told that it may be advantageous to use the -q flag +# when running pico or pilot on a Linux console, and to turn on the +# feature "termdef-takes-precedence" when running pine. That +# feature doesn't show up in the Config screen, you need to turn +# it on in the pine.conf file or by editing the .pinerc file. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dlnx -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -lncurses + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-lnx.h + $(RM) os.h + $(LN) osdep/os-lnx.h os.h + +pico_os.c: osdep/os-lnx.c + $(RM) pico_os.c + $(LN) osdep/os-lnx.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-lnx.c: osdep/header osdep/unix osdep/read.sel osdep/raw.io \ + osdep/spell.unx osdep/term.inf \ + osdep/os-lnx.ic + cd osdep; $(MAKE) includer os-lnx.c; cd .. diff --git a/makefile.lyn b/makefile.lyn new file mode 100644 index 0000000..ff54ead --- /dev/null +++ b/makefile.lyn @@ -0,0 +1,88 @@ +# $Id: makefile.lyn 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for Lynxos version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dbsd -Dlyn -DJOB_CONTROL +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap -lc + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-lyn.h + $(RM) os.h + $(LN) osdep/os-lyn.h os.h + +pico_os.c: osdep/os-lyn.c + $(RM) pico_os.c + $(LN) osdep/os-lyn.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-lyn.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.cap osdep/getcwd \ + osdep/os-lyn.ic + cd osdep; $(MAKE) includer os-lyn.c; cd .. diff --git a/makefile.mct b/makefile.mct new file mode 100644 index 0000000..dfa2254 --- /dev/null +++ b/makefile.mct @@ -0,0 +1,89 @@ +# $Id: makefile.mct 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for Machten version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dmct -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-mct.h + $(RM) os.h + $(LN) osdep/os-mct.h os.h + +pico_os.c: osdep/os-nxt.c + $(RM) pico_os.c + $(LN) osdep/os-nxt.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-nxt.c: osdep/header osdep/unix osdep/read.sel osdep/raw.brk \ + osdep/spell.unx osdep/term.cap \ + osdep/getcwd \ + osdep/os-nxt.ic + cd osdep; $(MAKE) includer os-nxt.c; cd .. diff --git a/makefile.mnt b/makefile.mnt new file mode 100644 index 0000000..d467c34 --- /dev/null +++ b/makefile.mnt @@ -0,0 +1,88 @@ +# $Id: makefile.mnt 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1999 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for MiNT version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dmnt -DJOB_CONTROL -DPOSIX +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-mnt.h + $(RM) os.h + $(LN) osdep/os-mnt.h os.h + +pico_os.c: osdep/os-mnt.c + $(RM) pico_os.c + $(LN) osdep/os-mnt.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-mnt.c: osdep/header osdep/unix osdep/read.sel osdep/raw.brk \ + osdep/spell.unx osdep/term.cap \ + osdep/os-mnt.ic + cd osdep; $(MAKE) includer os-mnt.c; cd .. diff --git a/makefile.msc b/makefile.msc new file mode 100644 index 0000000..2728eea --- /dev/null +++ b/makefile.msc @@ -0,0 +1,116 @@ +# $Id: makefile.msc 7883 1998-02-28 00:10:21Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# +# Makefile for MS-DOS version of the PINE composer library and +# stand-alone editor pico. +# +# MSC version of makefile +# +CC=cl +RM=del +CP=copy + +#includes mouse support +MOUSE= -DMOUSE +#includes symbol info for debugging +DEBUG= #-Zi -Od + +!IF DEFINED(PCTCP) +NET= -DPCTCP +!ELSE +NET= +!ENDIF + +#in general, no debugging and optimize for size +CFLAGS= -Os $(DEBUG) -WX -AL -Gt4 -Gy $(NET) -DJOB_CONTROL -DDOS $(MOUSE) + +# switches for library building +LIBER=lib +LIBARGS=/NOL -+ + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +CFILES= attach.c basic.c bind.c browse.c \ + buffer.c composer.c display.c file.c fileio.c \ + line.c pico_os.c pico.c random.c region.c \ + search.c window.c word.c + +OFILES= attach.obj basic.obj bind.obj browse.obj \ + buffer.obj composer.obj display.obj file.obj fileio.obj \ + line.obj pico_os.obj pico.obj random.obj region.obj \ + search.obj window.obj word.obj + +all: blddate.exe pico.exe + +.c.obj: + $(CC) -c $(CFLAGS) $*.c + $(LIBER) libpico $(LIBARGS) $*; + +$(OFILES): $(HFILES) +pico.o: ebind.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +os.h: osdep\os-dos.h + $(RM) os.h + $(CP) osdep\os-dos.h os.h + +pico_os.c: osdep\os-dos.c + $(RM) pico_os.c + $(CP) osdep\os-dos.c pico_os.c + +osdep\os-dos.c: osdep\header osdep\dos osdep\dosgen osdep\term.dos + cd osdep + $(MAKE) -f makefile.dos includer.exe os-dos.c + cd .. + +pico_os.o: osdep\dos_gen.h + + +libpico.lib: $(OFILES) +# del libpico.lib +# $(LIBER) libpico +ansi+attach+basic+bind+browse; +# $(LIBER) libpico +buffer+composer+display+file+fileio; +# $(LIBER) libpico +line+ibmpc+osdep+pico+random+region; +# $(LIBER) libpico +search+spell+window+word; + +blddate.exe: blddate.c + $(CC) blddate.c + +main.obj: main.c $(HFILES) + $(CC) /c $(CFLAGS) main.c + +pico.exe: libpico.lib main.obj + link /I /NOI /NOE /stack:32768 main.obj,pico.exe,nul,libpico.lib; +# link /CO /I /NOI /NOE /stack:32768 main.obj,pico.exe,nul,libpico.lib; + +#clean: +# $(RM) *.lib +# $(RM) *.obj +# $(RM) pico_os.c +# $(RM) os.h +# diff --git a/makefile.neb b/makefile.neb new file mode 100644 index 0000000..7c2054b --- /dev/null +++ b/makefile.neb @@ -0,0 +1,88 @@ +# $Id: makefile.neb 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for NetBSD version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dneb -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-neb.h + $(RM) os.h + $(LN) osdep/os-neb.h os.h + +pico_os.c: osdep/os-neb.c + $(RM) pico_os.c + $(LN) osdep/os-neb.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-neb.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.cap \ + osdep/os-neb.ic + cd osdep; $(MAKE) includer os-neb.c; cd .. diff --git a/makefile.nto b/makefile.nto new file mode 100644 index 0000000..d8fb46e --- /dev/null +++ b/makefile.nto @@ -0,0 +1,88 @@ +# $Id: makefile.nto 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for a QNX Neutrino version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -DNTO -DJOB_CONTROL +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -lncurses + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-nto.h + $(RM) os.h + $(LN) osdep/os-nto.h os.h + +pico_os.c: osdep/os-nto.c + $(RM) pico_os.c + $(LN) osdep/os-nto.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-nto.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.cap \ + osdep/os-nto.ic + cd osdep; $(MAKE) includer os-nto.c; cd .. diff --git a/makefile.nxt b/makefile.nxt new file mode 100644 index 0000000..a1f4139 --- /dev/null +++ b/makefile.nxt @@ -0,0 +1,89 @@ +# $Id: makefile.nxt 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for NeXT version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dnxt -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-nxt.h + $(RM) os.h + $(LN) osdep/os-nxt.h os.h + +pico_os.c: osdep/os-nxt.c + $(RM) pico_os.c + $(LN) osdep/os-nxt.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-nxt.c: osdep/header osdep/unix osdep/read.sel osdep/raw.brk \ + osdep/spell.unx osdep/term.cap \ + osdep/getcwd \ + osdep/os-nxt.ic + cd osdep; $(MAKE) includer os-nxt.c; cd .. diff --git a/makefile.os2 b/makefile.os2 new file mode 100644 index 0000000..3b90bc0 --- /dev/null +++ b/makefile.os2 @@ -0,0 +1,134 @@ +# $Id: makefile.os2 7883 1998-02-28 00:10:21Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for OS/2 version of the PINE composer library and +# stand-alone editor pico. +# + +# Common macros + +CC= gcc +CP= cp +MAKE= make +MV= mv +RM= rm -f + +OS= os2 + +# emx OMF format build +# Used to build .dlls with data exports + +DEBUG= +ZOMF= -Zomf +O= .obj +A= .lib +E= .exe +D= .dll +AR= emxomfar r +ZLIB= -Zcrtdll +ZOPT= -O3 -fno-strength-reduce -mprobe +ZDEF= -DOS2 -DOMF + +.SUFFIXES: .c .obj .exe + +# emx AOUT format build +# Useful for debugging with gdb + +#DEBUG= -g +#ZOMF= +#O= .o +#A= .a +#D= .dll +#E= .exe +#AR= ar rus +#ZLIB= -Zcrtdll +#ZOPT= -O3 -fno-strength-reduce -mprobe +#ZDEF= -DOS2 + +#.SUFFIXES: .c .o .exe + +.c$O: ; $(CC) $(ZOMF) $(CFLAGS) -c $< + +#includes symbol for debugging +#for normal build +MOUSE= -DMOUSE +DASHO= $(ZOPT) $(DEBUG) +CFLAGS= $(ZDEF) -Dbsd -DFASTVIO -DHELPFILE -DJOB_CONTROL -DANSI $(MOUSE) $(DASHO) +LDFLAGS= $(ZOMF) $(ZLIB) $(DEBUG) +ARCHIVE= picolib$A + +# switches for library building + +LIBS= + +OFILES= attach$O basic$O bind$O browse$O buffer$O \ + composer$O display$O file$O fileio$O line$O pico_os$O \ + pico$O random$O region$O search$O \ + window$O word$O + +CFILES= attach.c basic.c bind.c browse.c buffer.c \ + composer.c display.c file.c fileio.c line.c pico_os.c \ + pico.c random.c region.c search.c \ + window.c word.c + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and pico.lib +# + +all: blddate$E pico$E pilot$E + +$(ARCHIVE): $(OFILES) picolib.def + $(CC) -Zdll -o picolib$D $(OFILES) picolib.def $(LDFLAGS) + emximp -o picolib$A picolib.def + +pico$E: main.c $(ARCHIVE) + $(CC) $(CFLAGS) main.c -L. -lpicolib $(LIBS) -o pico$E $(LDFLAGS) + +pilot$E: pilot.c $(ARCHIVE) osdep.h + $(CC) $(CFLAGS) pilot.c -L. -lpicolib $(LIBS) -o pilot$E $(LDFLAGS) + +blddate$E: blddate.c + $(CC) $(CFLAGS) blddate.c -o blddate$E $(LDFLAGS) -lsocket + +$(OFILES): osdep.h $(HFILES) +pico.o: ebind.h + +clean: + rm -f *$E *$A *$D *$O *~ *.bak osdep.c osdep.h pico pilot + +os.h: osdep/os-os2.h + $(RM) os.h + $(CP) osdep/os-os2.h os.h + +pico_os.c: osdep/os-os2.c + $(RM) pico_os.c + $(CP) osdep/os-os2.c pico_os.c + +osdep/os-os2.c: \ + osdep/header osdep/os2 osdep/term.dos osdep/spell.os2 \ + osdep/os-os2.ic + ( cd osdep && $(MAKE) -f makefile.os2 includer.exe os-os2.c ) diff --git a/makefile.osf b/makefile.osf new file mode 100644 index 0000000..8f040b5 --- /dev/null +++ b/makefile.osf @@ -0,0 +1,88 @@ +# $Id: makefile.osf 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for OSF/1 version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dosf -D_BSD -DPOSIX -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -lcurses -lc + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-osf.h + $(RM) os.h + $(LN) osdep/os-osf.h os.h + +pico_os.c: osdep/os-osf.c + $(RM) pico_os.c + $(LN) osdep/os-osf.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-osf.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.cap \ + osdep/os-osf.ic + cd osdep; $(MAKE) includer os-osf.c; cd .. diff --git a/makefile.osx b/makefile.osx new file mode 100644 index 0000000..b10c8d4 --- /dev/null +++ b/makefile.osx @@ -0,0 +1,88 @@ +# $Id: makefile.osx 12485 2002-09-20 18:23:11Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for BSD 4.3 version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dbsd -DJOB_CONTROL +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -lncurses + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-osx.h + $(RM) os.h + $(LN) osdep/os-osx.h os.h + +pico_os.c: osdep/os-osx.c + $(RM) pico_os.c + $(LN) osdep/os-osx.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-osx.c: osdep/header osdep/unix osdep/read.sel osdep/raw.brk \ + osdep/spell.unx osdep/term.cap \ + osdep/os-osx.ic + cd osdep; $(MAKE) includer os-osx.c; cd .. diff --git a/makefile.pt1 b/makefile.pt1 new file mode 100644 index 0000000..1f78f3c --- /dev/null +++ b/makefile.pt1 @@ -0,0 +1,88 @@ +# $Id: makefile.pt1 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for Sequent Dynix/PTX 1.4 version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dptx -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= true + +LIBS= $(EXTRALDFLAGS) -ltermlib -linet + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-pt1.h + $(RM) os.h + $(LN) osdep/os-pt1.h os.h + +pico_os.c: osdep/os-pt1.c + $(RM) pico_os.c + $(LN) osdep/os-pt1.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-pt1.c: osdep/header osdep/unix osdep/read.pol osdep/raw.io \ + osdep/spell.unx osdep/term.inf \ + osdep/os-pt1.ic + cd osdep; $(MAKE) includer os-pt1.c; cd .. diff --git a/makefile.ptx b/makefile.ptx new file mode 100644 index 0000000..0e7cb60 --- /dev/null +++ b/makefile.ptx @@ -0,0 +1,88 @@ +# $Id: makefile.ptx 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for Sequent Dynix/PTX version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dptx -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= true + +LIBS= $(EXTRALDFLAGS) -ltermlib -linet + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $& $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-ptx.h + $(RM) os.h + $(LN) osdep/os-ptx.h os.h + +pico_os.c: osdep/os-ptx.c + $(RM) pico_os.c + $(LN) osdep/os-ptx.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-ptx.c: osdep/header osdep/unix osdep/read.pol osdep/raw.io \ + osdep/spell.unx osdep/term.inf \ + osdep/os-ptx.ic + cd osdep; $(MAKE) includer os-ptx.c; cd .. diff --git a/makefile.s40 b/makefile.s40 new file mode 100644 index 0000000..e1edced --- /dev/null +++ b/makefile.s40 @@ -0,0 +1,88 @@ +# $Id: makefile.s40 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for SunOS 4.0 version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dconst= -Ds40 -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap -lc + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-s40.h + $(RM) os.h + $(LN) osdep/os-s40.h os.h + +pico_os.c: osdep/os-s40.c + $(RM) pico_os.c + $(LN) osdep/os-s40.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-s40.c: osdep/header osdep/unix osdep/read.sel osdep/raw.brk \ + osdep/spell.unx osdep/term.cap \ + osdep/os-s40.ic + cd osdep; $(MAKE) -f makefile.dl includer os-s40.c; cd .. diff --git a/makefile.sc5 b/makefile.sc5 new file mode 100644 index 0000000..1b74246 --- /dev/null +++ b/makefile.sc5 @@ -0,0 +1,94 @@ +# $Id: makefile.sc5 13443 2004-01-30 19:43:25Z jpf $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for SCO 3.2v5.0.x version of the PINE composer library and +# stand-alone editor pico. +# +# Port courtesy of J. Kean Johnston , 970319 +# + +RM= rm -f +LN= ln -s +MAKE= make +SHELL= /bin/sh +OPTIMIZE= -O3 +PROFILE= # -pg +DEBUG= # -g -DDEBUG + +STDCFLAGS= -belf -Dsco -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= true + +# When USE_TERMINFO is defined link with library tinfo. +LIBS= $(EXTRALDFLAGS) -ltinfo -lc +# When USE_TERMCAP is defined link with library termcap. +#LIBS= $(EXTRALIBES) -ltermcap -lc -lc_s -lx + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-sc5.h + $(RM) os.h + $(LN) osdep/os-sc5.h os.h + +pico_os.c: osdep/os-sc5.c + $(RM) pico_os.c + $(LN) osdep/os-sc5.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-sc5.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.inf \ + osdep/os-sc5.ic + cd osdep; $(MAKE) includer os-sc5.c; cd .. diff --git a/makefile.sco b/makefile.sco new file mode 100644 index 0000000..84343af --- /dev/null +++ b/makefile.sco @@ -0,0 +1,93 @@ +# $Id: makefile.sco 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for SCO 3.2vx version of the PINE composer library and +# stand-alone editor pico. +# +# Port courtesy of Robert Lewis , 921217 +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dsco -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= true + +# When USE_TERMINFO is defined link with library tinfo. +LIBS= $(EXTRALDFLAGS) -lc -lc_s -lx -lm -ltinfo +# When USE_TERMCAP is defined link with library termcap. +#LIBS= $(EXTRALIBES) -lc -lc_s -lx -lm -ltermcap + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-sco.h + $(RM) os.h + $(LN) osdep/os-sco.h os.h + +pico_os.c: osdep/os-sco.c + $(RM) pico_os.c + $(LN) osdep/os-sco.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-sco.c: osdep/header osdep/unix osdep/read.sel osdep/raw.io \ + osdep/spell.unx osdep/term.inf osdep/truncate osdep/fsync.non \ + osdep/os-sco.ic + cd osdep; $(MAKE) includer os-sco.c; cd .. diff --git a/makefile.sgi b/makefile.sgi new file mode 100644 index 0000000..0d07e48 --- /dev/null +++ b/makefile.sgi @@ -0,0 +1,88 @@ +# $Id: makefile.sgi 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for SGI IRIX 4.0.1 version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dsgi -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= /bin/true + +LIBS= $(EXTRALDFLAGS) -ltermcap -lc + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-sgi.h + $(RM) os.h + $(LN) osdep/os-sgi.h os.h + +pico_os.c: osdep/os-sgi.c + $(RM) pico_os.c + $(LN) osdep/os-sgi.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-sgi.c: osdep/header osdep/unix osdep/read.sel osdep/raw.ios \ + osdep/spell.unx osdep/term.inf \ + osdep/os-sgi.ic + cd osdep; $(MAKE) includer os-sgi.c; cd .. diff --git a/makefile.soc b/makefile.soc new file mode 100644 index 0000000..976b0b8 --- /dev/null +++ b/makefile.soc @@ -0,0 +1,90 @@ +# $Id: makefile.soc 13589 2004-04-08 16:49:39Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for Sun Solaris version of the PINE composer library and +# stand-alone editor pico. +# +# [Port courtesy of Marc Unangst - mss, 921020] +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dconst= -Dsv4 -DPOSIX -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= true + +LIBS= $(EXTRALDFLAGS) -ltermlib + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $& $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-sol.h + $(RM) os.h + $(LN) osdep/os-sol.h os.h + +pico_os.c: osdep/os-sv4.c + $(RM) pico_os.c + $(LN) osdep/os-sv4.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-sv4.c: osdep/header osdep/unix osdep/read.pol osdep/raw.ios \ + osdep/spell.unx osdep/term.cap \ + osdep/os-sv4.ic + cd osdep; $(MAKE) includer os-sv4.c; cd .. diff --git a/makefile.sol b/makefile.sol new file mode 100644 index 0000000..17c4095 --- /dev/null +++ b/makefile.sol @@ -0,0 +1,97 @@ +# $Id: makefile.sol 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for Sun Solaris version of the PINE composer library and +# stand-alone editor pico. +# +# [Port courtesy of Marc Unangst - mss, 921020] +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +# LDCC= /usr/bin/cc +# If you don't have /usr/bin/cc (our Solaris 2.2 doesn't seem to have it, +# it only has /usr/ucb/cc) then change LDCC to the following line and +# give that a try. This is still using the Solaris compiler but +# leaving out the UCB compatibility includes and libraries. +LDCC= ./cc5.sol + +STDCFLAGS= -Dconst= -Dsv4 -DPOSIX -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= true + +LIBS= $(EXTRALDFLAGS) -ltermlib + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(LDCC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(LDCC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $& $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-sol.h + $(RM) os.h + $(LN) osdep/os-sol.h os.h + +pico_os.c: osdep/os-sv4.c + $(RM) pico_os.c + $(LN) osdep/os-sv4.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-sv4.c: osdep/header osdep/unix osdep/read.pol osdep/raw.ios \ + osdep/spell.unx osdep/term.cap \ + osdep/os-sv4.ic + cd osdep; $(MAKE) includer os-sv4.c; cd .. diff --git a/makefile.sun b/makefile.sun new file mode 100644 index 0000000..8bbfb60 --- /dev/null +++ b/makefile.sun @@ -0,0 +1,88 @@ +# $Id: makefile.sun 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for SunOS 4.1 version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dconst= -Dsun -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap -lc -ldl + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-sun.h + $(RM) os.h + $(LN) osdep/os-sun.h os.h + +pico_os.c: osdep/os-sun.c + $(RM) pico_os.c + $(LN) osdep/os-sun.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-sun.c: osdep/header osdep/unix osdep/read.sel osdep/raw.brk \ + osdep/spell.unx osdep/term.cap \ + osdep/os-sun.ic + cd osdep; $(MAKE) -f makefile.dl includer os-sun.c; cd .. diff --git a/makefile.sv4 b/makefile.sv4 new file mode 100644 index 0000000..a054c92 --- /dev/null +++ b/makefile.sv4 @@ -0,0 +1,90 @@ +# $Id: makefile.sv4 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for System V R4 version of the PINE composer library and +# stand-alone editor pico. +# +# [Port courtesy of Marc Unangst - mss, 921020] +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dsv4 -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= true + +LIBS= $(EXTRALDFLAGS) -ltermlib + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-sv4.h + $(RM) os.h + $(LN) osdep/os-sv4.h os.h + +pico_os.c: osdep/os-sv4.c + $(RM) pico_os.c + $(LN) osdep/os-sv4.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-sv4.c: osdep/header osdep/unix osdep/read.pol osdep/raw.ios \ + osdep/spell.unx osdep/term.inf \ + osdep/os-sv4.ic + cd osdep; $(MAKE) includer os-sv4.c; cd .. diff --git a/makefile.ult b/makefile.ult new file mode 100644 index 0000000..4aa95a5 --- /dev/null +++ b/makefile.ult @@ -0,0 +1,88 @@ +# $Id: makefile.ult 12448 2002-09-09 22:13:57Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for RISC Ultrix 4.1 version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dconst= -Dult -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap -lc + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pico.exe pilot pilot.exe + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-ult.h + $(RM) os.h + $(LN) osdep/os-ult.h os.h + +pico_os.c: osdep/os-ult.c + $(RM) pico_os.c + $(LN) osdep/os-ult.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-ult.c: osdep/header osdep/unix osdep/read.sel osdep/raw.brk \ + osdep/spell.unx osdep/term.cap \ + osdep/os-ult.ic + cd osdep; $(MAKE) includer os-ult.c; cd .. diff --git a/makefile.uw2 b/makefile.uw2 new file mode 100644 index 0000000..cb82116 --- /dev/null +++ b/makefile.uw2 @@ -0,0 +1,90 @@ +# $Id: makefile.uw2 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for UnixWare 2.x version of the PINE composer library and +# stand-alone editor pico. +# +# [Port courtesy of Tim Rice - hubert, 960311] +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dsv4 -DJOB_CONTROL -DPOSIX -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= true + +LIBS= $(EXTRALDFLAGS) -ltermlib + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-sv4.h + $(RM) os.h + $(LN) osdep/os-sv4.h os.h + +pico_os.c: osdep/os-sv4.c + $(RM) pico_os.c + $(LN) osdep/os-sv4.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-sv4.c: osdep/header osdep/unix osdep/read.pol osdep/raw.ios \ + osdep/spell.unx osdep/term.inf \ + osdep/os-sv4.ic + cd osdep; $(MAKE) includer os-sv4.c; cd .. diff --git a/makefile.vul b/makefile.vul new file mode 100644 index 0000000..122a2b7 --- /dev/null +++ b/makefile.vul @@ -0,0 +1,88 @@ +# $Id: makefile.vul 11894 2001-10-23 22:18:36Z hubert $ +# +# Michael Seibel +# Networks and Distributed Computing +# Computing and Communications +# University of Washington +# Administration Builiding, AG-44 +# Seattle, Washington, 98195, USA +# Internet: mikes@cac.washington.edu +# +# Please address all bugs and comments to "pine-bugs@cac.washington.edu" +# +# +# Pine and Pico are registered trademarks of the University of Washington. +# No commercial use of these trademarks may be made without prior written +# permission of the University of Washington. +# +# Pine, Pico, and Pilot software and its included text are Copyright +# 1989-1998 by the University of Washington. +# +# The full text of our legal notices is contained in the file called +# CPYRIGHT, included with this distribution. +# + +# +# Makefile for VAX Ultrix 4.1 version of the PINE composer library and +# stand-alone editor pico. +# + +RM= rm -f +LN= ln -s +MAKE= make +OPTIMIZE= # -O +PROFILE= # -pg +DEBUG= -g -DDEBUG + +STDCFLAGS= -Dconst= -Dult -DJOB_CONTROL -DMOUSE +CFLAGS= $(OPTIMIZE) $(PROFILE) $(DEBUG) $(EXTRACFLAGS) $(STDCFLAGS) + +# switches for library building +LIBCMD= ar +LIBARGS= ru +RANLIB= ranlib + +LIBS= $(EXTRALDFLAGS) -ltermcap -lc + +OFILES= attach.o basic.o bind.o browse.o buffer.o \ + composer.o display.o file.o fileio.o line.o pico_os.o \ + pico.o random.o region.o search.o \ + window.o word.o + +HFILES= headers.h estruct.h edef.h efunc.h pico.h os.h + +# +# dependencies for the Unix versions of pico and libpico.a +# +all: pico pilot +pico pilot: libpico.a + +pico: main.o + $(CC) $(CFLAGS) main.o libpico.a $(LIBS) -o pico + +pilot: pilot.o + $(CC) $(CFLAGS) pilot.o libpico.a $(LIBS) -o pilot + +libpico.a: $(OFILES) + $(LIBCMD) $(LIBARGS) libpico.a $(OFILES) + $(RANLIB) libpico.a + +clean: + rm -f *.a *.o *~ pico_os.c os.h pico pilot + cd osdep; $(MAKE) clean; cd .. + +os.h: osdep/os-ult.h + $(RM) os.h + $(LN) osdep/os-ult.h os.h + +pico_os.c: osdep/os-ult.c + $(RM) pico_os.c + $(LN) osdep/os-ult.c pico_os.c + +$(OFILES) main.o pilot.o: $(HFILES) +pico.o: ebind.h + +osdep/os-ult.c: osdep/header osdep/unix osdep/read.sel osdep/raw.brk \ + osdep/spell.unx osdep/term.cap \ + osdep/os-ult.ic + cd osdep; $(MAKE) includer os-ult.c; cd .. diff --git a/msdlg.c b/msdlg.c new file mode 100644 index 0000000..eb248af --- /dev/null +++ b/msdlg.c @@ -0,0 +1,1003 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: msdlg.c 11710 2001-07-02 22:31:28Z jpf $"; +#endif +/*--------------------------------------------------------------------------- + * + * Module: msdlg.c + * + * Thomas Unger + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: tunger@cac.washington.edu + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-1998 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + *--------------------------------------------------------------------------*/ + +#define WIN31 +#define STRICT + +#include "headers.h" + + +extern HWND ghTTYWnd; +extern HINSTANCE ghInstance; +extern BOOL gfUseDialogs; +extern FILE *mswin_debugfile; +extern int mswin_debug; +extern char gszAppName[45]; + + + +#define BTN_FIRSTID 200 +#define BSPACE 4 +#define BWIDTH_MIN 120 + + +typedef struct { + char *prompt; /* Prompt. */ + char *string; /* Resulting string. */ + int strlen; /* Length of buffer. */ + int append; /* Append to existing string. */ + int passwd; /* Passwd, don't echo. */ + unsigned flags; /* other flags. */ + int dflt; + int cancel; + int button_count; /* Number of additional buttons. */ + MDlgButton *button_list; /* List of other buttons. */ + char **helptext; /* Help text. */ + char helpkey; + int result; +} OEInfo; + + +static OEInfo gOEInfo; +static BOOL gDoHelpFirst; +static WNDPROC gpOldEditProc; /* Old Edit window proc. */ +static WNDPROC gpEditProc; +static WNDPROC gpOldBtnProc; /* Old Edit window proc. */ +static WNDPROC gpBtnProc; + + + + +/* + * Forward function declaratins. + */ +LONG FAR PASCAL __export EditProc(HWND hBtn, UINT msg, WPARAM wParam, + LPARAM lParam); +LONG FAR PASCAL __export ButtonProc(HWND hBtn, UINT msg, WPARAM wParam, + LPARAM lParam); +BOOL CALLBACK __export mswin_dialog_proc (HWND hDlg, UINT uMsg, + WPARAM wParam, LPARAM lParam); +BOOL CALLBACK __export mswin_select_proc (HWND hDlg, UINT uMsg, + WPARAM wParam, LPARAM lParam); +LONG FAR PASCAL __export KBCProc (HWND hWnd, UINT uMsg, WPARAM wParam, + LPARAM lParam); + + +static void BuildButtonList (HWND hDlg, MDlgButton *built_in, + int biCount, MDlgButton *button_list); +static BOOL ProcessChar (HWND hWnd, WPARAM wParam, + OEInfo *oeinfo, long *ret); +static void GetBtnPos (HWND hPrnt, HWND hWnd, RECT *r); + + + + + + + +int +mswin_usedialog (void) +{ + return (gfUseDialogs); +} + + + +/*---------------------------------------------------------------------- + + + Generic text entry. Prompt user for a string. + + + Args: + prompt -- The string to prompt with + string -- the buffer result is returned in, and original string (if + any) is passed in. + field_len -- Maximum length of string to accept + append_current -- flag indicating string should not be truncated before + accepting input + passwd -- a pass word is being fetch. Don't echo on screen + button_list -- pointer to array of mDlgButton's. input chars matching + those in list return value from list. Nearly identical + to Pine's ESCKEY structure. + help -- Arrary of strings for help text in bottom screen lines + flags -- flags + + Result: editing input string + returns -1 unexpected errors + returns 0 typed CR or pressed "OK" + returns 1 typed ESC or pressed "Cancel" + returns 3 typed ^G or PF1 (help) + returns 4 typed ^L for a screen redraw + or one of the other return values defined in button_list. + + WARNING: Care is required with regard to the escape_list processing. + The passed array is terminated with an entry that has ch = -1. + Function key labels and key strokes need to be setup externally! + Traditionally, a return value of 2 is used for ^T escapes. + + + Note About Help: We don't get the help text on the first call. If we + want help text we have to return 3. We'll get called again + with help text. To make it look good, we want to display + this the second time we're called. But we don't want to + display the help text every time we're called with help + text. To know the difference we set gDoHelpFirst when + exiting to request help text. If this is set then we + display help. If not, then no help. + + +----------------------------------------------------------------------*/ + + +/* + * xxx implement flags. + * xxx display.d uses flags QFFILE, QDEFLT, and QBOBUF + */ + +int +mswin_dialog (char *prompt, char *string, int field_len, int append_current, + int passwd, MDlgButton *button_list, char **help, unsigned flags) +{ + DLGPROC dlgprc; + int c; + + + mswin_flush (); + + + gOEInfo.prompt = prompt; + gOEInfo.string = string; + gOEInfo.strlen = field_len; + gOEInfo.append = append_current; + gOEInfo.passwd = passwd; + gOEInfo.helptext = help; + gOEInfo.helpkey = 0x07; /* ^G */ + gOEInfo.flags = flags; + gOEInfo.button_list = button_list; + gOEInfo.result = 0; + + for (c = 0; button_list && button_list[c].ch != -1; ++c); + gOEInfo.button_count = c; + + gpEditProc = (WNDPROC) MakeProcInstance ((FARPROC) EditProc, + ghInstance); + + gpBtnProc = (WNDPROC) MakeProcInstance ((FARPROC) ButtonProc, + ghInstance); + + + dlgprc = (DLGPROC) MakeProcInstance ((FARPROC) mswin_dialog_proc, + ghInstance); + DialogBox (ghInstance, MAKEINTRESOURCE (IDD_OPTIONALYENTER), + ghTTYWnd, dlgprc); + FreeProcInstance((FARPROC) dlgprc); + FreeProcInstance((FARPROC) gpBtnProc); + FreeProcInstance((FARPROC) gpEditProc); + return (gOEInfo.result); +} + + + + +/* + * Dialog procedure for the generic text entry dialog box. + */ +BOOL CALLBACK __export +mswin_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + BOOL ret = FALSE; + int i, l; + int biCount; + HWND hEdit; + MDlgButton built_in[3]; + + + switch (uMsg) { + case WM_INITDIALOG: + /* + * Set the prompt text. + */ + SetDlgItemText (hDlg, IDC_PROMPT, gOEInfo.prompt); + + /* + * Set the initial edit text and configure the edit control + */ + if (!gOEInfo.append) + *gOEInfo.string = '\0'; + SetDlgItemText (hDlg, IDC_RESPONCE, gOEInfo.string); + SendDlgItemMessage (hDlg, IDC_RESPONCE, EM_SETPASSWORDCHAR, + gOEInfo.passwd ? '*' : 0, 0L); + SendDlgItemMessage (hDlg, IDC_RESPONCE, EM_LIMITTEXT, + gOEInfo.strlen - 1, 0L); + l = lstrlen (gOEInfo.string); + SendDlgItemMessage(hDlg, IDC_RESPONCE, EM_SETSEL, 0, + MAKELONG(l, l)); + hEdit = GetDlgItem (hDlg, IDC_RESPONCE); + SetFocus (hEdit); + gpOldEditProc = (WNDPROC) GetWindowLong (hEdit, GWL_WNDPROC); + SetWindowLong (hEdit, GWL_WNDPROC, (DWORD)(FARPROC)gpEditProc); + + + /* + * Subclass the standard buttons and build buttons for each item + * in the button_list. + */ + gpOldBtnProc = (WNDPROC) GetWindowLong (GetDlgItem (hDlg, IDOK), GWL_WNDPROC); + SetWindowLong (GetDlgItem (hDlg, IDOK), GWL_WNDPROC, + (DWORD)(FARPROC)gpBtnProc); + SetWindowLong (GetDlgItem (hDlg, IDCANCEL), GWL_WNDPROC, + (DWORD)(FARPROC)gpBtnProc); + + memset (&built_in, 0, sizeof (built_in)); + built_in[0].id = IDOK; + built_in[1].id = IDCANCEL; + if (1) { + built_in[2].id = IDC_GETHELP; + biCount = 3; + } + else { + DestroyWindow (GetDlgItem (hDlg, IDC_GETHELP)); + biCount = 2; + } + BuildButtonList (hDlg, built_in, biCount, gOEInfo.button_list); + + + if (gOEInfo.helptext && gDoHelpFirst) { + mswin_showhelpmsg ((WINHAND)hDlg, gOEInfo.helptext); + gDoHelpFirst = FALSE; + } + return (0); + + + case WM_ACTIVATE: + /* + * Keep focus on the edit item so key strokes are always + * received. + */ + SetFocus (GetDlgItem (hDlg, IDC_RESPONCE)); + break; + + + case WM_COMMAND: + switch (wParam) { + case IDOK: + /* + * Normal exit. Accept the new text. + */ + GetDlgItemText (hDlg, IDC_RESPONCE, gOEInfo.string, + gOEInfo.strlen); + gOEInfo.result = 0; + EndDialog (hDlg, gOEInfo.result); + ret = TRUE; + break; + + case IDCANCEL: + /* + * Cancel operation. Don't retreive new text. + */ + gOEInfo.result = 1; + EndDialog (hDlg, gOEInfo.result); + ret = TRUE; + break; + + case IDC_GETHELP: + /* + * Get help. If we have help text display it. If not, + * return value 3, which tells the caller to provide us + * with help text. + */ + if (gOEInfo.helptext != NULL) { + mswin_showhelpmsg ((WINHAND)hDlg, gOEInfo.helptext); + } + else { + GetDlgItemText (hDlg, IDC_RESPONCE, gOEInfo.string, + gOEInfo.strlen); + gOEInfo.result = 3; + gDoHelpFirst = TRUE; + EndDialog (hDlg, gOEInfo.result); + } + ret = TRUE; + break; + + default: + /* + * Search button list for button with this ID. If found + * return it's result code. Retreive text. + */ + if ( wParam >= BTN_FIRSTID && + wParam < BTN_FIRSTID + gOEInfo.button_count) { + GetDlgItemText (hDlg, IDC_RESPONCE, gOEInfo.string, + gOEInfo.strlen); + i = wParam - BTN_FIRSTID; + gOEInfo.result = gOEInfo.button_list[i].rval; + EndDialog (hDlg, gOEInfo.result); + ret = TRUE; + } + } + + } + return (ret) ; +} + + + + +/* + * Subclassed window procedure for Edit control on generic text + * entry dialog box. + */ +LONG FAR PASCAL __export +EditProc (HWND hEdit, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HWND hDlg; + int i; + int id; + LONG ret; + + hDlg = GetParent (hEdit); + + if (msg == WM_GETDLGCODE) { + /* + * Tell windows that we want to receive ALL keystrokes. + */ + ret = CallWindowProc (gpOldEditProc, hEdit, msg, wParam, lParam); + ret |= DLGC_WANTALLKEYS; + return (ret); + } + + + if (msg == WM_CHAR) { + /* + * See if the character typed is a shortcut for any of the + * buttons. + */ + if (ProcessChar (hDlg, wParam, &gOEInfo, &ret)) + return (ret); + + /* No... Fall through for deault processing. */ + } + + return (CallWindowProc (gpOldEditProc, hEdit, msg, wParam, lParam)); +} + + + + +/* + * Subclass button windows. + * + * These buttons will automatically return the input focus to + * a control with id IDC_RESPONCE. + */ +LONG FAR PASCAL __export +ButtonProc (HWND hBtn, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + HWND hDlg; + int i; + int id; + LONG ret; + + + if (uMsg == WM_LBUTTONUP || uMsg == WM_MBUTTONUP || uMsg == WM_RBUTTONUP) { + /* + * On mouse button up restore input focus to IDC_RESPONCE, which + * processes keyboard input. + */ + ret = CallWindowProc (gpOldBtnProc, hBtn, uMsg, wParam, lParam); + hDlg = GetParent (hBtn); + SetFocus (GetDlgItem (hDlg, IDC_RESPONCE)); + return (ret); + } + + return (CallWindowProc (gpOldBtnProc, hBtn, uMsg, wParam, lParam)); +} + + + + +/* + * Ask a yes/no question with the MessageBox procedure. + * + * Returns: + * 0 - Cancel operation. + * 1 - "Yes" was selected. + * 2 - "No" was selected. + */ +int +mswin_yesno (char *prompt) +{ + int ret; + + mswin_flush (); + + mswin_killsplash(); + + ret = MessageBox (ghTTYWnd, prompt, gszAppName, + MB_APPLMODAL | MB_ICONQUESTION | MB_YESNOCANCEL); + + switch (ret) { + case IDYES: ret = 1; break; + case IDNO: ret = 2; break; + default: + case IDCANCEL: ret = 0; break; + } + return (ret); +} + + + + + + + + + + + +/*---------------------------------------------------------------------- + + + Generic selection routine. Display a prompt and a set of buttons for + each possible answer. + + + + Args: + prompt -- The string to prompt with. + button_list -- pointer to array of mDlgButton's. input chars + matching those in list return value from + mlist. Nearly identical to Pine's ESCKEY + mstructure. + dflt -- Value returned when "Enter" is pressed. + on_ctrl_C -- Value returned to cancel dialog (ESC). + help -- Arrary of strings for help text in bottom screen + lines + flags -- flags + + Result: + dflt -- Default option selected. + on_ctrl_C -- Calcel operation. + or one of the other return values defined in button_list. + + +Note: To prcess keyboard in put we use a custom dialog control + which is invisible but always has the input focus. + +----------------------------------------------------------------------*/ + +int +mswin_select (char *prompt, MDlgButton *button_list, int dflt, int on_ctrl_C, + char **help, unsigned flags) +{ + WNDCLASS wndclass; + DLGPROC dlgprc; + WNDPROC kbcProc; + int c; + + + mswin_flush (); + + + /* + * Setup dialog config structure. + */ + gOEInfo.prompt = prompt; + gOEInfo.string = NULL; + gOEInfo.strlen = 0; + gOEInfo.append = 0; + gOEInfo.passwd = 0; + gOEInfo.helptext = help; + gOEInfo.helpkey = 'g'; + gOEInfo.dflt = dflt; + gOEInfo.cancel = on_ctrl_C; + gOEInfo.flags = flags; + gOEInfo.button_list = button_list; + gOEInfo.result = 0; + + /* + * Count the buttons. + */ + for (c = 0; button_list && button_list[c].ch != -1; ++c); + gOEInfo.button_count = c; + + + /* + * Register the class for the user control which will receive keyboard + * input events. + */ + kbcProc = (WNDPROC) MakeProcInstance ((FARPROC) KBCProc, ghInstance); + wndclass.style = 0; + wndclass.lpfnWndProc = kbcProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = ghInstance; + wndclass.hIcon = NULL; + wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); + wndclass.hbrBackground = 0; + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = "KeyboardCapture"; + + if (RegisterClass (&wndclass) == 0) { + /* + * There is no good return value to indicate an error. + * Cancel the operation. + */ + return (on_ctrl_C); + } + + + + + /* + * Make other procedure instances. + */ + dlgprc = (DLGPROC) MakeProcInstance ((FARPROC) mswin_select_proc, + ghInstance); + gpBtnProc = (WNDPROC) MakeProcInstance ((FARPROC) ButtonProc, + ghInstance); + + + /* + * Bring up the dialog box. + */ + DialogBox(ghInstance, MAKEINTRESOURCE (IDD_SELECT), ghTTYWnd, + dlgprc); + + + + /* + * Free the proc instances and window class. + */ + FreeProcInstance((FARPROC) dlgprc); + FreeProcInstance((FARPROC) gpBtnProc); + UnregisterClass ("KeyboardCapture", ghInstance); + FreeProcInstance((FARPROC) kbcProc); + return (gOEInfo.result); +} + + + + +/* + * Dialog procedure for the button selection dialog box. + */ +BOOL CALLBACK __export +mswin_select_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + BOOL ret = FALSE; + int i, l; + int biCount; + HWND hEdit; + MDlgButton built_in[3]; + + if (mswin_debug >= 1) + fprintf (mswin_debugfile, "Select: uMsg x%x (%d), wParam x%x, lParam x%lx\n", + uMsg, uMsg, wParam, lParam); + + + switch (uMsg) { + case WM_INITDIALOG: + /* + * Show the prompt. + */ + SetDlgItemText (hDlg, IDC_PROMPT, gOEInfo.prompt); + + /* + * Set focus to the invisible custom control + */ + SetFocus (GetDlgItem (hDlg, IDC_RESPONCE)); + + /* + * Subclass the standard buttons and build buttons for each item + * in the button_list. + */ + gpOldBtnProc = (WNDPROC) GetWindowLong (GetDlgItem (hDlg, IDCANCEL), GWL_WNDPROC); + SetWindowLong (GetDlgItem (hDlg, IDC_GETHELP), GWL_WNDPROC, + (DWORD)(FARPROC)gpBtnProc); + SetWindowLong (GetDlgItem (hDlg, IDCANCEL), GWL_WNDPROC, + (DWORD)(FARPROC)gpBtnProc); + + memset (&built_in, 0, sizeof (built_in)); + built_in[0].id = IDCANCEL; + if (gOEInfo.helptext != NULL) { + built_in[1].id = IDC_GETHELP; + biCount = 2; + } + else { + DestroyWindow (GetDlgItem (hDlg, IDC_GETHELP)); + gOEInfo.helpkey = 0; + biCount = 1; + } + BuildButtonList (hDlg, built_in, biCount, gOEInfo.button_list); + gDoHelpFirst = FALSE; + return (0); + + + case WM_ACTIVATE: + /* + * Keep focus on the custom control item so key strokes are always + * received. + */ + SetFocus (GetDlgItem (hDlg, IDC_RESPONCE)); + break; + + + case WM_COMMAND: + switch (wParam) { + case IDOK: + gOEInfo.result = gOEInfo.dflt; + EndDialog (hDlg, gOEInfo.result); + ret = TRUE; + break; + + case IDCANCEL: + gOEInfo.result = gOEInfo.cancel; + EndDialog (hDlg, gOEInfo.result); + ret = TRUE; + break; + + case IDC_GETHELP: + /* + * Get help. If we have help text display it. If not, + * return value 3, which tells the caller to provide us + * with help text. + */ + if (gOEInfo.helptext != NULL) { + mswin_showhelpmsg ((WINHAND) hDlg, gOEInfo.helptext); + } + ret = TRUE; + break; + + default: + if ( wParam >= BTN_FIRSTID && + wParam < BTN_FIRSTID + gOEInfo.button_count) { + i = wParam - BTN_FIRSTID; + gOEInfo.result = gOEInfo.button_list[i].rval; + EndDialog (hDlg, gOEInfo.result); + ret = TRUE; + } + } + + } + return (ret) ; +} + + + +/* + * Window procedure for the hidden custom control. + */ +LONG FAR PASCAL __export +KBCProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + int i; + LONG ret; + + + if (uMsg == WM_GETDLGCODE) { + /* + * Tell windows that we want all the character messages. + */ + ret = DefWindowProc (hWnd, uMsg, wParam, lParam); + ret |= DLGC_WANTALLKEYS; + return (ret); + } + + + if (uMsg == WM_CHAR) { + /* + * See if the character typed is a shortcut for any of the + * buttons. + */ + if (ProcessChar (GetParent (hWnd), wParam, &gOEInfo, &ret)) + return (ret); + + /* Fall through for default processing. */ + } + + return (DefWindowProc (hWnd, uMsg, wParam, lParam)); +} + + + + + + +/* + * Check if character activates any button. If it does, send WM_COMMAND + * to target window. + * + * Args: + * hWnd - Window to send message to. + * wParam - character typed. + * oeinfo - dialog config structure. Contains button list. + * ret - value to return to windows. + * + * Returns: + * TRUE - Found a match. Exit from Window Procedure returning + * *ret to windows. + * + * FALSE - No match. Continue with default processing of character + * message. + * + */ +static BOOL +ProcessChar (HWND hWnd, WPARAM wParam, OEInfo *oeinfo, long *ret) +{ + int i; + int id; + + + *ret = 0; + if (wParam == 0x0d) { + /* + * "Enter" is same as clicking on OK button. + */ + PostMessage (hWnd, WM_COMMAND, IDOK, + MAKELONG (GetDlgItem (hWnd, IDOK), 1)); + return (TRUE); + } + if (wParam == 0x1b || wParam == 0x03) { + /* + * Esc is same as clicking on Cancel button. + */ + PostMessage (hWnd, WM_COMMAND, IDCANCEL, + MAKELONG (GetDlgItem (hWnd, IDCANCEL), 1)); + return (TRUE); + } + + /* + * Any of the custom buttons respond to this key? + */ + for (i = 0; i < oeinfo->button_count; ++i) { + if (wParam == oeinfo->button_list[i].ch) { + id = oeinfo->button_list[i].id; + PostMessage (hWnd, WM_COMMAND, id, + MAKELONG (GetDlgItem (hWnd, id), 1)); + return (TRUE); + } + } + + /* + * Lastly, is it the help key? + */ + if (oeinfo->helpkey != 0 && wParam == oeinfo->helpkey) { + id = IDC_GETHELP; + PostMessage (hWnd, WM_COMMAND, id, + MAKELONG (GetDlgItem (hWnd, id), 1)); + return (TRUE); + } + + + /* + * Nothing we understand. + */ + return (FALSE); +} + + + + + +/* + * Get a button position in the parent's coordinate space. + */ +static void +GetBtnPos (HWND hPrnt, HWND hWnd, RECT *r) +{ + GetWindowRect (hWnd, r); + ScreenToClient (hPrnt, (POINT *) r); + ScreenToClient (hPrnt, (POINT *) &r->right); +} + + + + +/* + * Add buttons to the dialog box. + */ +static void +BuildButtonList (HWND hDlg, MDlgButton *built_in, int biCount, + MDlgButton *button_list) +{ + RECT rDlg, rb1, rb2, r; + HDC hdc; + MDlgButton *pB; /* pointer to button struct*/ + HWND hBtn, hBtn1, hBtn2; /* handle to buttons */ + int btnCount; /* extra button count */ + int rows, cols; /* button rows and columns */ + int bpos; /* button position */ + int i; + int maxstrIdx, maxstrLen; /* button w/ longest caption*/ + DWORD textExtent; /* width of button caption */ + int margine; /* left and right margines */ + int btop, bleft; /* button position */ + int bwidth, bheight, w; /* button size */ + int bMinWidth; /* minimum buttonwidth */ + int bvertSpace, bhorzSpace; /* button spacing */ + int newWHeight, delta; /* window resizing */ + char caption[128]; + HFONT btnFont; + + + /* + * Are there any buttons to add? + */ + if (button_list == NULL) + return; + maxstrIdx = 0; + for (btnCount = 0; button_list[btnCount].ch != -1; ++btnCount) { + if (lstrlen (button_list[btnCount].label) > + lstrlen (button_list[maxstrIdx].label)) + maxstrIdx = btnCount; + } + if (btnCount == 0) + return; + + + /* + * Get the size of the dialog box and the positions of the + * first and, if there is one, the second button. Calculate or + * default button offsets and positions. + */ + GetClientRect (hDlg, &rDlg); + hBtn1 = GetDlgItem (hDlg, built_in[0].id); + GetBtnPos (hDlg, hBtn1, &rb1); + margine = rb1.left; /* left and right margine */ + bheight = rb1.bottom - rb1.top; /* button width */ + bwidth = rb1.right - rb1.left; /* button height. */ + if (biCount > 1) { + hBtn2 = GetDlgItem (hDlg, built_in[1].id); + GetBtnPos (hDlg, hBtn2, &rb2); + bvertSpace = rb2.top - rb1.top; /* vertical spacing */ + } + else { + bvertSpace = bheight + BSPACE; /* vertical spacing */ + } + + + /* + * Get the button font. + */ + btnFont = (HFONT) SendMessage (hBtn1, WM_GETFONT, 0, 0); + + + + /* + * Get the screen extent of the longest button label. min width + * is the extent, plus the average width of 5 extra characters for + * key stroke, plus margine. + */ + hdc = GetDC (hBtn1); + wsprintf (caption, "%s '%s'", button_list[maxstrIdx].label, + button_list[maxstrIdx].name); + maxstrLen = lstrlen (caption); +#ifdef WIN32 + { + SIZE size; + + GetTextExtentPoint32 (hdc, caption, maxstrLen, &size); + textExtent = size.cx; + } +#else + textExtent = GetTextExtent (hdc, caption, maxstrLen); + textExtent = LOWORD (textExtent); +#endif + ReleaseDC (hBtn1, hdc); + bMinWidth = LOWORD (textExtent) + (2 * (LOWORD(textExtent) / maxstrLen)); + if (bwidth < bMinWidth) + bwidth = bMinWidth; + + + + /* + * Calculate button positions. If the buttons are going to extend + * past the right edge of the dialog box, shrink their width. But + * if they get narrower than the min width calculated above then + * increase the number of rows. + */ + rows = 1; + do { + ++rows; /* More rows. */ + w = bwidth; /* Original button width. */ + cols = 1 + ((biCount + btnCount) - 1) / rows; /* Calc num cols. */ + + /* Need to srink button width? */ + if (2 * margine + bwidth * cols + BSPACE * (cols - 1) > rDlg.right) { + w = ((rDlg.right - (2 * margine)) - (BSPACE * (cols-1))) / cols; + } + /* Did buttons get too narrow? */ + } while (w < bMinWidth && cols > 1); + + bwidth = w; + bhorzSpace = bwidth + BSPACE; /* horizontal spacing */ + + + + + + /* + * Resize window. + */ + newWHeight = rb1.top + (rows * bvertSpace); + delta = newWHeight - rDlg.bottom; + if (delta != 0) { + GetWindowRect (hDlg, &r); + MoveWindow (hDlg, r.left, r.top, r.right - r.left, + (r.bottom - r.top) + delta, FALSE); + } + + + + /* + * Create new buttons. + */ + for (bpos = 0; bpos < biCount + btnCount; ++bpos) { + /* + * Calculate position for this button. + */ + btop = rb1.top + (bpos % rows) * bvertSpace; + bleft = rb1.left + (bpos / rows) * bhorzSpace; + + if (bpos < biCount) { + /* + * Resize existing buttons. + */ + MoveWindow (GetDlgItem (hDlg, built_in[bpos].id), + bleft, btop, bwidth, bheight, FALSE); + } + else { + i = bpos - biCount; + pB = &button_list[i]; + + wsprintf (caption, "%s '%s'", pB->label, pB->name); + hBtn = CreateWindow ("BUTTON", caption, + WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, + bleft, btop, bwidth, bheight, + hDlg, NULL, ghInstance, NULL); + + pB->id = BTN_FIRSTID + i; +#ifdef WIN32 + SetWindowLong (hBtn, GWL_ID, pB->id); +#else + SetWindowWord (hBtn, GWW_ID, pB->id); +#endif + SendMessage (hBtn, WM_SETFONT, (WPARAM)btnFont, MAKELPARAM (0, 0)); + + /* Subclass button. */ + SetWindowLong (hBtn, GWL_WNDPROC, (DWORD)(FARPROC)gpBtnProc); + EnableWindow (hBtn, TRUE); + } + } +} + + + + + diff --git a/msmem.c b/msmem.c new file mode 100644 index 0000000..4565e5d --- /dev/null +++ b/msmem.c @@ -0,0 +1,1301 @@ +#ifndef MSC_MALLOC + +#define WIN31 +#define STRICT + +#include +#include +#include + +#include "mswin.h" + + + + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * Memory allocation routines. + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +/* + * The plan is to allocate small blocks in the local heap and + * large blocks in the global heap. The intention is to keep + * the number of global allocations to a minimum. + * + * The boundry between small memory and large memory is + * controld by the constant SMALL_MEM_BOUNDRY. Blocks smaller + * than SMALL_MEM_BOUNDRY go into the local heap. This should + * be set large enough to capture the majority of small memory + * blocks in the local heap. But if it is too large, the local + * heap will fill up and we will end up allocating a lot of small + * blocks in the global heap. + * + * Unfortunatly, pine seems to need a large stack. With the + * stack, some global data, and the heap all cramed in to a 64K + * segment we end up with a heap that is smaller than ideal. + * This could be improved by reducing the size of the stack, or + * by moving the heap to a seperate memory block. I did a little + * work on moving the heap, but was not successful. My attepts + * can be seen in the function MemATest(). + * + * Currently (7/8/94) I've set the stack to 32K (in pine/makefile.win), + * the heap to 12K, and the small memory boundry to 32 bytes. + * Statistics on pine memory allocation suggest that it would be better + * to have a 25K local heap and a 95 byte small memory boundry. + * + * Statistics on memory use can be gathered by logging memory debugging + * to a file, then running the following awk script: + * + + # mem.awk + # + # Looks through log and find blocks that were allocated but not + # freed uses block id numbers, rather than addresses, since this is + # more accurate (and since this is what block ids exist!) + # + # awk may run out of memory if the logfile gets too big. If this + # happens, then another strategy will be needed... + # + + BEGIN { + FS = "[ ()]+"; + + b[0] = 16; + b[1] = 32; + b[2] = 64; + b[3] = 96; + b[4] = 128; + b[5] = 256; + b[6] = 512; + b[7] = 1024; + b[8] = 2048; + b[9] = 4096; + b[10] = 9600; + b[11] = 20000; + b[12] = 40000; + b[13] = 80000; + b[14] = 200000000; + b[15] = 0; + bcount = 15; + for (i = 0; i < bcount; ++i) + c[i] = 0; + + maxmem = 0; + maxsmallmem = 0; + + allocs = 0; + frees = 0; + globalallocs = 0; + pallocs = 0; + pfrees = 0; + } + + { + #print "one", $1, "two", $2, "three", $3, "four ", $4, "five ", $5; + if( $1 == "MemAlloc:" ) { + m[$5] = $0; + + ++allocs; + if ($9 == 1) ++globalallocs; + + for (i = 0; i < bcount; ++i) { + if (b[i] > $7) { + ++c[i]; + break; + } + } + } + else if( $1 == "MemFree:" ) { + delete m[$5]; + ++frees; + } + if( $1 == "PageAlloc:" ) { + p[$5] = $0; + + ++pallocs; + } + else if( $1 == "PageFree:" ) { + delete p[$5]; + ++pfrees; + } + else if ($1 == "Memory") { + if ($6 > maxmem) maxmem = $6; + } + else if ($1 == "Small") { + if ($7 > maxsmallmem) maxsmallmem = $7; + } + } + + + END { + for( i in m ) { + print m[i] + } + for (i in p) { + print p[i] + } + + cumulative = 0; + for (i = 0; i < bcount; ++i) { + cumulative += c[i]; + printf "%9d : %5d (%5d)\n", b[i], c[i], cumulative; + } + + print; + print "Max memory use: ", maxmem; + print "Max small memory use: ", maxsmallmem; + print; + print "Local allocations ", allocs - globalallocs; + print "Global allocations ", globalallocs; + print "Total allocations ", allocs; + print "Total memory frees ", frees; + print "Blocks not freed ", allocs - frees; + print; + print "Page allocations ", pallocs; + print "Page frees ", pfrees; + print "Pages not freed ", pallocs - pfrees; + } + + * + * Each memory block is assigned a unique id. This is only used + * to match allocations with frees in the debug log. + */ + + + +/* + * SEGHEAP selectes between two different implementations of the memory + * management functions. Defined and it uses a sub allocation scheme. + * Undefined and it comples a direct allocation scheme. + * + * The sub allocation scheme is greatly prefered because it greatly reduces + * the number of global memory allocations. + */ +#define SEGHEAP /* Use the sub allocation scheme. */ + + + + +#define MEM_DEBUG /* Compile in memory debugging code.*/ +#define MEM_DEBUG_LEVEL 8 /* Pine debug level at which memory + * debug messages will be generated.*/ +#ifdef MEM_DEBUG +static int MemDebugLevel = 0; /* Doing debugging. */ +static FILE *MemDebugFile = NULL; /* File to write to. */ +#endif + + + +#ifdef DEBUG +#define LOCAL +#else +#define LOCAL static +#endif + + +#define GET_SEGMENT(x) (0xffff & ((DWORD)(x) >> 16)) +#define GET_OFFSET(x) (0xffff & (DWORD)(x)) + + +#undef malloc +#undef realloc +#undef free + + +void MemATest (void); + + + + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * Standard memory allcation functions. + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + + +void * +malloc (size_t size) +{ + return (MemAlloc (size)); +} + + +void __far * +_fmalloc (size_t size) +{ + return (MemAlloc (size)); +} + + +void __far * +realloc (void *memblock, size_t size) +{ + return (MemRealloc (memblock, size)); +} + + +void __far * +_frealloc (void *memblock, size_t size) +{ + return (MemRealloc (memblock, size)); +} + + +void +free (void *memblock) +{ + MemFree (memblock); +} + +void +_ffree (void *memblock) +{ + MemFree (memblock); +} + + +/* + * Turn on memory debugging and specify file to write to. + */ +void +MemDebug (int debug, FILE *debugFile) +{ +#ifdef MEM_DEBUG + if (debugFile == NULL) { + MemDebugLevel = 0; + MemDebugFile = NULL; + } + else { + MemDebugLevel = debug; + MemDebugFile = debugFile; + fprintf (MemDebugFile, "Memory Debuging set on\n"); + } +#endif /* MEM_DEBUG */ +} + + + + + + + +#ifdef SEGHEAP + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * SEGHEAP Memory allocation routines. + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +/* + * This implementation allocates memory in pages then sub alloates from the + * pages. This greatly reduces the number of global memory blocks allocated. + * This code originally written by Stephen Chung and posted to a Usenet news + * group. I've modified them for use in Pine. The author says: + * + * + * Copyright (C) Stephen Chung, 1991-1992. All rights reserved. + * + * Afterwords + * ---------- + * + * Theoretically, you are required to obtain special approval from me (because + * I copyrighted these routines) if you want to use them in your programs. + * However, I usually don't really care if you are not using these routines in + * a commercial, shareware etc. product. + * + * Any questions and/or bug fixes, please send email to: + * + * Stephen Chung stephenc@cunixf.cc.columbia.edu + * + * If it bounces, then try schung@cogsci.Berkeley.EDU + * + * Have fun! + * + */ + + +/* + * The folloing control debugging code for testing out of memory conditions. + * there are to test code. + * + * MEM_ALLOC_LIMT + * Setting this to anything other than zero will limit memory allocation + * to (rougly) that many bytes. + * + * MEM_FAIL_SOON + * Compiles in a function which will cause the memory allocation to fail + * soon after that function is called. this can be used to test + * mem alloc failurs in specific code segments. + */ +#define MEM_ALLOC_LIMIT 0 +#define MEM_FAIL_SOON 0 + + +#if MEM_FAIL_SOON +static long MemFailSoonLimit = 0; +#endif + + + +#define MAGIC 0x42022667 +#define MAGIC2 0x56743296 + +typedef struct MemoryStruct { + long int magic; + void far *page; + WORD id; + MemSize size; + BOOL allocated; + struct MemoryStruct far *next, far *prev; + long int magic2; +} MEMHEADER; + +typedef struct PageHeaderStruct { + long int magic; + HANDLE handle; + WORD id; + MemSize size; + MemSize used; + MemSize overhead; + MEMHEADER far *data, far *empty; + struct PageHeaderStruct far *next, far *prev; + long int magic2; +} MEMPAGEHEADER; + +typedef struct { + MEMPAGEHEADER far *pages; + int nr_pages; +} MAINMEMHEADER; + +#define PAGESIZE (6 * 1024) +#define USEABLESIZE (PAGESIZE - sizeof(MEMPAGEHEADER) - sizeof(MEMHEADER)) + + +LOCAL MAINMEMHEADER MemHeader = { NULL, 0 }; +LOCAL WORD MemID = 0; /* Keep track of ID. */ +LOCAL WORD PageID = 0; +LOCAL unsigned long MemInUse = 0; /* Total bytes in use. */ +LOCAL unsigned long MemInUseMax = 0; /* max in use at one time. */ +LOCAL unsigned long PageMemInUse = 0; +LOCAL unsigned long PageMemInUseMax = 0; + + + +static MEMPAGEHEADER far * +AddPage(MemSize n) +{ + void far *cp; + MEMHEADER far *mp; + MEMPAGEHEADER far *p; + HANDLE handle = NULL; + + +#if MEM_ALLOC_LIMIT + if (n + PageMemInUse > MEM_ALLOC_LIMIT) { + MessageBox (NULL, "PageAlloc: Above preset limit, allocation fails", + "Out Of Memory", MB_ICONSTOP | MB_OK); + return (NULL); + } +#endif + + handle = GlobalAlloc(GHND, n); + if (handle == NULL) { +#ifdef MEM_DEBUG + if (MemDebugLevel >= 1) + fprintf (MemDebugFile, "***\n*** Out of memory: allocating %d bytes\n***\n", n); +#endif + return (NULL); + } + + if (MemHeader.pages == NULL || MemHeader.nr_pages <= 0) { + p = MemHeader.pages = (MEMPAGEHEADER far *) GlobalLock(handle); + p->prev = NULL; + } else { + for (p = MemHeader.pages; p->next != NULL; p = p->next); + p->next = (MEMPAGEHEADER far *) GlobalLock(handle); + p->next->prev = p; + p = p->next; + } + + p->magic = MAGIC; + p->handle = handle; + p->next = NULL; + p->id = PageID++; + p->size = n; + p->used = 0; + p->overhead = sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER); + p->magic2 = MAGIC2; + + cp = ((char far *) p) + sizeof(MEMPAGEHEADER); + mp = (MEMHEADER far *) cp; + + p->data = p->empty = mp; + + mp->magic = 0L; + mp->magic2 = 0L; + mp->allocated = FALSE; + mp->page = p; + mp->size = p->size - p->overhead; + mp->next = mp->prev = NULL; + + MemHeader.nr_pages++; + + +#ifdef MEM_DEBUG + if (MemDebugLevel >= MEM_DEBUG_LEVEL) { + fprintf (MemDebugFile, "PageAlloc: addr(%lx) id(%u) size(%ld) global(%d)\n", + p, p->id, (long)n, 1); + fflush (MemDebugFile); + } +#endif /* MEM_DEBUG */ + + PageMemInUse += n; + if (PageMemInUse > PageMemInUseMax) + PageMemInUseMax = PageMemInUse; + + + return (p); +} + + + +static void +DeletePage (MEMPAGEHEADER far *p) +{ +#ifdef MEM_DEBUG + /* Deubgging info... */ + if (MemDebugLevel >= 4) { + if (PageMemInUse == PageMemInUseMax) + fprintf (MemDebugFile, "Page usage is up to %lu\n", PageMemInUseMax); + } + if (MemDebugLevel >= MEM_DEBUG_LEVEL) { + fprintf (MemDebugFile, "PageFree: addr(%lx) id(%u)\n", + p, p->id); + fflush (MemDebugFile); + } +#endif /* MEM_DEBUG */ + + PageMemInUse -= p->size; + + + if (p->next == NULL && p->prev == NULL) { + MemHeader.pages = NULL; + MemHeader.nr_pages = 0; + GlobalUnlock (p->handle); + GlobalFree (p->handle); + } else { + if (p == MemHeader.pages) MemHeader.pages = p->next; + MemHeader.nr_pages--; + + if (p->prev != NULL) p->prev->next = p->next; + if (p->next != NULL) p->next->prev = p->prev; + + GlobalUnlock (p->handle); + GlobalFree (p->handle); + } +} + + +/* + * Segmented heap memory allocation. + */ + +MemPtr +_MemAlloc (MemSize n, char __far * file, int line) +{ + MEMPAGEHEADER far *p; + MEMHEADER far *mp; + char far *cp; + + if (n >= 65535) { + assert (n < 65535); + goto AllocFail; + } + +#if MEM_FAIL_SOON + if (MemFailSoonLimit != 0 && MemFailSoonLimit < MemInUse + n) { + MessageBox (NULL, "MemAlloc: Told to fail here, allocation fails", + "Out Of Memory", MB_ICONSTOP | MB_OK); + return (NULL); + } +#endif + + /* Larger than page size? */ + + if (n > USEABLESIZE) { + p = AddPage(n + sizeof(MEMPAGEHEADER) + sizeof(MEMHEADER)); + if (p == NULL) + goto AllocFail; + + mp = p->data; + mp->magic = MAGIC; + mp->magic2 = MAGIC2; + mp->id = MemID++; + mp->allocated = TRUE; + + + p->used = n; + p->empty = NULL; + + cp = ((char far *) mp) + sizeof(MEMHEADER); +#ifdef MEM_DEBUG + if (MemDebugLevel >= MEM_DEBUG_LEVEL) { + fprintf (MemDebugFile, "MemAlloc: addr(%lx) id(%u) size(%ld) global(%d)\n", + cp, mp->id, (long)n, 0); + fflush (MemDebugFile); + } +#endif /* MEM_DEBUG */ + + MemInUse += n; + if (MemInUse > MemInUseMax) + MemInUseMax = MemInUse; + return ((MemPtr) cp); + } + + + /* Search for the hole */ + + for (p = MemHeader.pages; p != NULL; p = p->next) { + /* Scan the chains */ + if (p->size - p->used - p->overhead <= 0) continue; + if (p->empty == NULL) continue; + + for (mp = p->empty; mp != NULL; mp = mp->next) { + if (!mp->allocated && mp->size >= n) break; + } + + if (mp != NULL) break; + } + + /* New page needed? */ + + if (p == NULL) { + p = AddPage(PAGESIZE); + if (p == NULL) + goto AllocFail; + mp = p->data; + } + + /* Do we need to break it up? */ + + if (mp->size - n > sizeof(MEMHEADER)) { + MEMHEADER far *mp2; + + cp = ((char far *) mp) + n + sizeof(MEMHEADER); + mp2 = (MEMHEADER far *) cp; + + mp2->magic = 0L; + mp2->magic2 = 0L; + mp2->allocated = FALSE; + mp2->page = p; + mp2->size = mp->size - n - sizeof(MEMHEADER); + + mp2->next = mp->next; + mp2->prev = mp; + if (mp->next != NULL) mp->next->prev = mp2; + mp->next = mp2; + + + p->overhead += sizeof(MEMHEADER); + + mp->size = n; + } + + mp->magic = MAGIC; + mp->magic2 = MAGIC2; + mp->allocated = TRUE; + mp->id = MemID++; + + p->used += n; + cp = ((char far *) mp) + sizeof(MEMHEADER); + + + /* Debugging info... */ +#ifdef MEM_DEBUG + if (MemDebugLevel >= MEM_DEBUG_LEVEL) { + fprintf (MemDebugFile, "MemAlloc: addr(%lx) id(%u) size(%ld) global(%d)\n", + cp, mp->id, (long)n, 0); + fflush (MemDebugFile); + } +#endif /* MEM_DEBUG */ + + MemInUse += n; + if (MemInUse > MemInUseMax) + MemInUseMax = MemInUse; + + + /* Search for the next empty hole */ + + for (; mp != NULL; mp = mp->next) { + if (!mp->allocated && mp->size > 0) break; + } + + p->empty = mp; + + return ((MemPtr) cp); + + +AllocFail: +#if 0 + assert (FALSE /* Memory allocation failed! */);*/ +#endif + return (NULL); +} + + + +/* + * Segmented heap memory free. + */ +int +_MemFree (MemPtr vp, char __far *file, int line) +{ + MEMPAGEHEADER far *p; + MEMHEADER far *mp, far *mp2; + char far *cp; + + if (vp == NULL) + return (0); + + + cp = ((char far *) vp) - sizeof(MEMHEADER); + mp = (MEMHEADER far *) cp; + + if (mp->magic != MAGIC || mp->magic2 != MAGIC2|| !mp->allocated) { + assert (mp->magic == MAGIC); + assert (mp->magic2 == MAGIC2); + assert (mp->allocated); + return (-1); + } + +#ifdef MEM_DEBUG + /* Deubgging info... */ + if (MemDebugLevel >= 4) { + if (MemInUse == MemInUseMax) + fprintf (MemDebugFile, "Memory usage is up to %lu\n", MemInUseMax); + } + if (MemDebugLevel >= MEM_DEBUG_LEVEL) { + fprintf (MemDebugFile, "MemFree: addr(%lx) id(%u)\n", vp, mp->id); + fflush (MemDebugFile); + } +#endif /* MEM_DEBUG */ + + MemInUse -= mp->size; + + + p = (MEMPAGEHEADER far *) mp->page; + p->used -= mp->size; + + mp->magic = 0L; + mp->magic2 = 0L; + mp->allocated = FALSE; + + /* Merge? */ + + mp2 = mp->prev; + + if (mp2 != NULL && !mp2->allocated) { + mp2->next = mp->next; + if (mp->next != NULL) mp->next->prev = mp2; + mp2->size += mp->size + sizeof(MEMHEADER); + + p->overhead -= sizeof(MEMHEADER); + + mp = mp2; + } + + mp2 = mp->next; + + if (mp2 != NULL && !mp2->allocated) { + mp->next = mp2->next; + if (mp2->next != NULL) + mp2->next->prev = mp; + + mp->size += mp2->size + sizeof(MEMHEADER); + + p->overhead -= sizeof(MEMHEADER); + } + + if (mp->prev == NULL && mp->next == NULL) { + DeletePage(p); + } else { + if (p->empty == NULL || mp < p->empty) p->empty = mp; + } + return (0); +} + + + +MemPtr +_MemRealloc (MemPtr p, MemSize n, char __far *file, int line) +{ + MEMHEADER far *mp; + char far *cp; + + if (p != NULL) { + /* Block already large enough? */ + cp = ((char far *) p) - sizeof(MEMHEADER); + mp = (MEMHEADER far *) cp; + + if (mp->magic != MAGIC || mp->magic2 != MAGIC2) { + assert (mp->magic == MAGIC); + assert (mp->magic2 == MAGIC2); + return (p); + } + + if (mp->size >= n) return (p); /* No need to do anything */ + } + /* Else swap to another block */ + + cp = MemAlloc (n); + if (cp == NULL) + return (NULL); + + if (p != NULL) { + _fmemcpy(cp, p, (size_t)((mp->size >= n) ? n : mp->size)); + MemFree (p); + } + + return ((void far *) cp); +} + + + +void +MemFailSoon (MemSize n) +{ +#if MEM_FAIL_SOON + MemFailSoonLimit = MemInUse + n; +#ifdef MEM_DEBUG + if (MemDebugLevel >= 1) { + fprintf (MemDebugFile, + "MemFailSoon: Fail when allocation increases by %ld (Max %ld)\n", + n, MemFailSoonLimit); + } +#endif +#endif +} + + + + + +MemSize +MemBlkSize (MemPtr p) +{ + MEMHEADER far *mp; + char far *cp; + + if (p == NULL) return (0); + cp = ((char far *) p) - sizeof(MEMHEADER); + + mp = (MEMHEADER far *) cp; + + if (mp->magic != MAGIC || mp->magic2 != MAGIC2) { + assert (mp->magic == MAGIC); + assert (mp->magic2 == MAGIC2); + return (0); + } + + return (mp->size); +} + + +#if 0 +MemPtr +MemDup (void far *p) +{ + unsigned int len; + void far *p1; + + len = MgetBlkSize (p); + p1 = MemAlloc (len); + if (p1 != NULL) + _fmemcpy(p1, p, len); + + return (p1); +} + + +void +MemoryStatistics (long int *allocated, long int *used, long int *overhead) +{ + MEMPAGEHEADER far *p; + + *allocated = *used = *overhead = 0L; + + for (p = MemHeader.pages; p != NULL; p = p->next) { + *allocated += p->size; + *used += p->used; + *overhead += p->overhead; + } +} +#endif + + +void +MemFreeAll (void) +{ + MEMPAGEHEADER far *p, far *p1; + + for (p = MemHeader.pages; p != NULL; ) { + p1 = p->next; + GlobalUnlock (p->handle); + GlobalFree (p->handle); + p = p1; + } + + MemHeader.pages = NULL; + MemHeader.nr_pages = 0; +} + + +#ifdef MEM_DEBUG + +/* For debugging purposes... not very pretty */ + +void PrintMemoryChains(void) +{ + MEMPAGEHEADER far *p; + MEMHEADER far *mp; + char far *cp; + char buffer[100]; + + /* Block already large enough? */ + + + for (p = MemHeader.pages; p != NULL; p = p->next) { + for (mp = p->data; mp != NULL; mp = mp->next) { + fprintf (MemDebugFile, "%Fp | %u | %s", mp, mp->size, mp->allocated ? "Alloc" : "Free"); + } + } +} + +#endif /* DEBUG */ + + + +#else /* !SEGHEAP. Old version, not used. */ + + + + + + + +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * Direct memory allocation + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +/* + * This following implementation allocates large memory blocks directly + * from global memory and small memory blocks from the local heap. The + * problem with this method is that pine's local heap is quite small + * so most of the memory ends up comming from the global heap. + */ + + +#define GUARD_LOW0 0xbbbb +#define GUARD_LOW 0x9999 +#define GUARD_HIGH 0xaaaaaaaa + +#define SMALL_MEM_BOUNDRY 32 + +#define HEAP_SIZE 32000 + + +/* Memory block header. Placed at beginning of each allocated block. */ +typedef struct { /*size len */ + WORD guard0; /* 00 - 02 */ + HGLOBAL handle; /* 02 - 02 */ + short globalBlk; /* 04 - 02 */ + MemSize size; /* 06 - 04 */ + WORD id; /* 0A - 02 */ + WORD guard1; /* 0C - 02 */ +} MemBlk; /* Total size: 0E */ + +typedef MemBlk __far * MemBlkPtr; + + +/* Memory high guard tailer. Placed at end of each allocated block. */ +typedef struct { + unsigned long guard1; +} MemHighGuard; + +typedef MemHighGuard __far *MemHighGuardPtr; + + +/* + * Memory allocation globals. + */ +LOCAL WORD MemID = 0; /* Keep track of ID. */ +LOCAL unsigned long MemLocalFails = 0; +LOCAL BOOL MemLocalFull = FALSE; /* True when local heap full*/ +#ifdef MEM_DEBUG +LOCAL unsigned long MemInUse = 0; /* Total bytes in use. */ +LOCAL unsigned long MemInUseMax = 0; /* max in use at one time. */ +LOCAL unsigned long SmallMemInUse = 0; +LOCAL unsigned long SmallMemInUseMax = 0; +#endif /* MEM_DEBUG */ + + + +/* + * Allocate a memory block. + * The file and line indicate where we are called from (for debugging) + * but in pine these mostly point to a bottel neck routine and are + * useless. + */ +MemPtr +_MemAlloc (MemSize size, char __far * file, int line) +{ + MemBlkPtr pBlk; + MemHighGuardPtr pHG; + HGLOBAL hBlk; + HLOCAL hLBlk; + UINT totalSize; + BYTE __far * pb; + + assert (size <= MEM_BLOCK_SIZE_MAX); + + + /* + * Calculate total size we need to allocate. + */ + totalSize = (UINT)size + sizeof (MemBlk) + sizeof (MemHighGuard); + + + pBlk = NULL; + + /* + * If it's a small block and the local heap is not full, try + * allocating from the local heap. + */ + if (size <= SMALL_MEM_BOUNDRY && !MemLocalFull) { + + /* Allocate block from local storage. */ + hLBlk = LocalAlloc (LMEM_MOVEABLE, totalSize); + if (hLBlk != NULL) { + + /* Lock block and dereference. */ + pBlk = (MemBlkPtr) LocalLock (hLBlk); + if (pBlk != NULL) { + pBlk->handle = hLBlk; + pBlk->globalBlk = FALSE; + } + else + LocalFree (hLBlk); + } + else { + ++MemLocalFails; + MemLocalFull = TRUE; +#ifdef MEM_DEBUG + if (MemDebugLevel >= MEM_DEBUG_LEVEL) + fprintf (MemDebugFile, "Local Memory alloc failed, %lu fails, %lu bytes in use\n", + MemLocalFails, SmallMemInUse); +#endif + } + } + + + /* + * If it is a large block, or local alloc failed, we allocate from + * global space. + */ + if (pBlk == NULL) { + + /* Allocate block from global storage. */ + hBlk = GlobalAlloc (GMEM_MOVEABLE, totalSize); + if (hBlk == NULL) + return (NULL); + + + /* Lock block and dereference. */ + pBlk = (MemBlkPtr) GlobalLock (hBlk); + if (pBlk == NULL) { + GlobalFree (hBlk); + return (NULL); + } + pBlk->handle = hBlk; + pBlk->globalBlk = TRUE; + } + + + + /* Fill rest of header. */ + pBlk->guard0 = GUARD_LOW0; + pBlk->size = size; + pBlk->id = ++MemID; + pBlk->guard1 = GUARD_LOW; + + + /* Find address that will be returned to caller. */ + pb = (BYTE __far *) (pBlk + 1); + + + /* Find high guard and fill. */ + pHG = (MemHighGuardPtr) (pb + size); + pHG->guard1 = GUARD_HIGH; + + + /* Debugging info... */ +#ifdef MEM_DEBUG + if (MemDebugLevel >= MEM_DEBUG_LEVEL) { + if( !file ) file = "??"; + fprintf (MemDebugFile, "MemAlloc: addr(%lx) id(%u) size(%ld) global(%d)\n", + pb, pBlk->id, (long)size, pBlk->globalBlk); + fflush (MemDebugFile); + } + MemInUse += totalSize; + if (MemInUse > MemInUseMax) + MemInUseMax = MemInUse; + if (size <= SMALL_MEM_BOUNDRY) { + SmallMemInUse += totalSize; + if (SmallMemInUse > SmallMemInUseMax) + SmallMemInUseMax = SmallMemInUse; + } +#endif /* MEM_DEBUG */ + + + return ((MemPtr) pb); +} + + + + +/* + * Free a block. + */ +int +_MemFree (MemPtr block, char __far *file, int line) +{ + MemBlkPtr pBlk; + MemHighGuardPtr pHG; + HGLOBAL hBlk; + HLOCAL hLBlk; + BOOL brc; + UINT totalSize; + + if (block == NULL) + return (0); + + + /* Find header and high guard and check them. */ + pBlk = ((MemBlkPtr)block) - 1; + pHG = (MemHighGuardPtr) ((char __far *)block + pBlk->size); + + totalSize = pBlk->size + sizeof (MemBlk) + sizeof (MemHighGuard); + + /* If these changed them someone wrote where the should not have. */ + assert (pBlk->guard0 == GUARD_LOW0); + assert (pBlk->guard1 == GUARD_LOW); + assert (pHG->guard1 == GUARD_HIGH); + + + +#ifdef MEM_DEBUG + /* Deubgging info... */ + if (MemDebugLevel >= MEM_DEBUG_LEVEL) { + if (pBlk->size <= SMALL_MEM_BOUNDRY && + SmallMemInUse == SmallMemInUseMax) + fprintf (MemDebugFile, "Small memory usage is up to %lu\n", SmallMemInUseMax); + if (MemInUse == MemInUseMax) + fprintf (MemDebugFile, "Memory usage is up to %lu\n", MemInUseMax); + } + MemInUse -= totalSize; + if (pBlk->size <= SMALL_MEM_BOUNDRY) + SmallMemInUse -= totalSize; + if (MemDebugLevel >= MEM_DEBUG_LEVEL) { + fprintf (MemDebugFile, "MemFree: addr(%lx) id(%u)\n", + block, pBlk->id); + fflush (MemDebugFile); + } +#endif /* MEM_DEBUG */ + + + + /* + * Header indicates which block it came from + */ + if (!pBlk->globalBlk) { + /* Unlock block */ + hLBlk = pBlk->handle; + brc = LocalUnlock (hLBlk); + assert (!brc); + + /* And free block. */ + hLBlk = LocalFree (hLBlk); + assert (hLBlk == NULL); + MemLocalFull = FALSE; + } + else { + /* Unlock block */ + hBlk = pBlk->handle; + brc = GlobalUnlock (hBlk); + assert (!brc); + + /* And free block. */ + hBlk = GlobalFree (hBlk); + assert (hBlk == NULL); + } + return (0); +} + + + + +/* + * Reallocate a memory block. Simplistic approach. + */ +MemPtr +_MemRealloc (MemPtr block, MemSize size, char __far * file, int line) +{ + MemPtr newBlock; + + + newBlock = MemAlloc (size); + if (newBlock == NULL) + return (NULL); + + if (block != NULL) { + _fmemcpy (newBlock, block , (size_t)MIN (size, MemBlkSize (block))); + MemFree (block); + } + + return (newBlock); +} + + + +/* + * Return the size of a memory block + */ +MemSize +MemBlkSize (MemPtr block) +{ + MemBlkPtr pBlk; + + if (block == NULL) return (0); + pBlk = ((MemBlkPtr)block) - 1; + assert (pBlk->guard1 == GUARD_LOW); + + return (pBlk->size); +} + + +#ifdef MEM_DEBUG +struct testblock { + struct testblock __far * prev; + HLOCAL h; +}; + + + +void +MemATest (void) +{ + void __near *n; + struct testblock __far *p; + struct testblock __far *pnew; + HLOCAL hl; + int bcount; + UINT segment, start, end; + void __far *f; + HGLOBAL hg; + DWORD dw; + LOCALINFO li; + UINT DataSeg; + +#if 0 + hg = GlobalAlloc (GMEM_FIXED, HEAP_SIZE); /* Allocate global block */ + if (hg == NULL) + return; + f = GlobalLock (hg); /* Lock and get pointer. */ + if (f == NULL) + goto Fail1; + segment = (UINT) GET_SEGMENT (f); /* Get segment and offsets. */ + start = (UINT) GET_OFFSET (f); + end = start + HEAP_SIZE - 1; + start += 16; + if (!LocalInit (segment, start, end)) /* Init it as the local heap*/ + goto Fail2; +#endif +#if 0 + __asm MOV DataSeg,DS; /* Get current DS. */ + __asm MOV DS,segment; /* Set DS to new heap. */ + hl = LocalAlloc (0, SMALL_MEM_BOUNDRY); /* Now allocate something. */ + __asm MOV DS,DataSeg; /* Restore DS. */ + if (hl == NULL) + return; + n = LocalLock (hl); /* Find where it is. */ + f = (void __far *)n; + segment = GET_SEGMENT(f); /* What Segment. */ + dw = GlobalHandle (segment); + hg = (HGLOBAL) (dw & 0xffff); + if (hg == NULL) + return; + + li.dwSize = sizeof (li); /* What size. */ + if (!LocalInfo (&li, hg)) + return; + + dw = GlobalSize (hg); + f = GlobalLock (hg); + GlobalUnlock (hg); + + LocalUnlock (hl); + LocalFree (hl); + + +#endif + + + + + p = NULL; + pnew = NULL; + bcount = 0; + + do { + hl = LocalAlloc (0, SMALL_MEM_BOUNDRY); + if (hl != NULL) { + ++bcount; + n = LocalLock (hl); + pnew = (struct testblock __far*) n; + pnew->h = hl; + pnew->prev = p; + p = pnew; + } + } while (hl != NULL); + + + if (MemDebugFile != NULL) + fprintf (MemDebugFile, "Allocated %d blocks of size %d\n", + bcount, SMALL_MEM_BOUNDRY); + + while (p != NULL) { + pnew = p->prev; + hl = p->h; + LocalUnlock (hl); + LocalFree (hl); + p = pnew; + } + fflush (MemDebugFile); +#if 0 +Fail2: GlobalUnlock (hg); +Fail1: GlobalFree (hg); +#endif + return; +} +#endif /* MEM_DEBUG */ + +#endif /* ifdef SEGHEAP */ + +#endif /* MSC_MALLOC */ diff --git a/msmenu.h b/msmenu.h new file mode 100644 index 0000000..e9573e9 --- /dev/null +++ b/msmenu.h @@ -0,0 +1,107 @@ +#line 2 "msmenu.h" +/* + * $Id: msmenu.h 7883 1998-02-28 00:10:21Z hubert $ + * + * Program: Menu item definitions - Microsoft Windows 3.1 + * + * + * Thomas Unger + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: tunger@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-1998 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + */ + +#ifndef MSMENU_H +#define MSMENU_H + + +/* + * var in pine's key structure we'll use + */ +#define KS_OSDATAVAR short menuitem; +#define KS_OSDATAGET(X) ((X)->menuitem) +#define KS_OSDATASET(X, Y) ((X)->menuitem = (Y)) + +/* + * Menu key definitions. + * Should be same values as in resouce.h + */ +#define KS_NONE 0 +#define KS_RANGESTART 150 + +#define KS_VIEW 150 +#define KS_EXPUNGE 151 +#define KS_ZOOM 152 +#define KS_SORT 153 +#define KS_HDRMODE 154 +#define KS_MAINMENU 155 +#define KS_FLDRLIST 156 +#define KS_FLDRINDEX 157 +#define KS_COMPOSER 158 +#define KS_PREVPAGE 159 +#define KS_PREVMSG 160 +#define KS_NEXTMSG 161 +#define KS_ADDRBOOK 162 +#define KS_WHEREIS 163 +#define KS_PRINT 164 +#define KS_REPLY 165 +#define KS_FORWARD 166 +#define KS_BOUNCE 167 +#define KS_DELETE 168 +#define KS_UNDELETE 169 +#define KS_FLAG 170 +#define KS_SAVE 171 +#define KS_EXPORT 172 +#define KS_TAKEADDR 173 +#define KS_SELECT 174 +#define KS_APPLY 175 +#define KS_POSTPONE 176 +#define KS_SEND 177 +#define KS_CANCEL 178 +#define KS_ATTACH 179 +#define KS_TOADDRBOOK 180 +#define KS_READFILE 181 +#define KS_JUSTIFY 182 +#define KS_ALTEDITOR 183 +#define KS_GENERALHELP 184 +#define KS_SCREENHELP 185 +#define KS_EXIT 186 +#define KS_NEXTPAGE 187 +#define KS_SAVEFILE 188 +#define KS_CURPOSITION 189 +#define KS_GOTOFLDR 190 +#define KS_JUMPTOMSG 191 +#define KS_RICHHDR 192 +#define KS_EXITMODE 193 +#define KS_REVIEW 194 +#define KS_KEYMENU 195 +#define KS_SELECTCUR 196 +#define KS_UNDO 197 +#define KS_SPELLCHK 198 + +#define KS_RANGEEND 198 + +#define KS_COUNT ((KS_RANGEEND - KS_RANGESTART) + 1) + + + +#define MENU_DEFAULT 300 /* Default menu for application. */ +#define MENU_COMPOSER 301 /* Menu for pine's composer. */ + +#endif /* MSMENU_H */ diff --git a/osdep/dos b/osdep/dos new file mode 100644 index 0000000..78d5f92 --- /dev/null +++ b/osdep/dos @@ -0,0 +1,624 @@ +#line 2 "osdep/dos" +/* + * $Id: dos 13299 2003-11-25 17:35:10Z hubert $ + * + * Program: Operating system dependent routines - MS DOS + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-1998 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + * + * Notes: + * - mouse support added (mss, 921215) + * + * Portions of this code derived from MicroEMACS 3.10: + * + * MSDOS.C: Operating specific I/O and Spawning functions + * under the MS/PCDOS operating system + * for MicroEMACS 3.10 + * (C)opyright 1988 by Daniel M. Lawrence + * + */ + +#include +#include +#include "dos_gen.h" + + +/* + * Internal functions... + */ +int enhanced_keybrd PROTO((void)); +int dont_interrupt PROTO((void)); +int interrupt_ok PROTO((void)); +int specialkey PROTO((unsigned int)); +char *pfnexpand PROTO((char *, size_t)); +int ssleep PROTO((long)); +int sleep PROTO((int)); + + +/* + * Useful global def's + */ +int timeo = 0; +time_t time_of_last_input; +int (*pcollator)(); +static int enhncd = 0; /* keyboard of enhanced variety? */ +union REGS rg; +struct SREGS segreg; + +static int oldbut; /* Previous state of mouse buttons */ +static unsigned short oldbreak; /* Original state of break key */ +static char ptmpfile[128]; /* popen temp file */ + + +/* + * Include generic DOS/Windows routines + */ +/* #include "dos_gen.c" */ + + +/* + * DISable ctrl-break interruption + */ +dont_interrupt() +{ + /* get original value, to be restored later... */ + rg.h.ah = 0x33; /* control-break check dos call */ + rg.h.al = 0; /* get the current state */ + rg.h.dl = 0; /* pre-set it OFF */ + intdos(&rg, &rg); /* go for it! */ + oldbreak = rg.h.dl; + /* kill the ctrl-break interupt */ + rg.h.ah = 0x33; /* control-break check dos call */ + rg.h.al = 1; /* set the current state */ + rg.h.dl = 0; /* set it OFF */ + intdos(&rg, &rg); /* go for it! */ +} + + +/* + * re-enable ctrl-break interruption + */ +interrupt_ok() +{ + /* restore the ctrl-break interupt */ + rg.h.ah = 0x33; /* control-break check dos call */ + rg.h.al = 1; /* set to new state */ + rg.h.dl = oldbreak; /* set it to its original value */ + intdos(&rg, &rg); /* go for it! */ +} + + +/* + * return true if an enhanced keyboard is present + */ +enhanced_keybrd() +{ + /* and check for extended keyboard */ + rg.h.ah = 0x05; + rg.x.cx = 0xffff; + int86(BIOS_KEYBRD, &rg, &rg); + rg.h.ah = 0x10; + int86(BIOS_KEYBRD, &rg, &rg); + return(rg.x.ax == 0xffff); +} + + +/* + * This function is called once to set up the terminal device streams. + */ +ttopen() +{ + dont_interrupt(); /* don't allow interrupt */ + enhncd = enhanced_keybrd(); /* check for extra keys */ +#if MOUSE + init_mouse(); +#else /* !MOUSE */ + mexist = 0; +#endif /* MOUSE */ + return(1); +} + + +/* + * ttresize - recompute the screen dimensions if necessary, and then + * adjust pico's internal buffers accordingly + */ +void +ttresize () +{ + return; +} + + +#ifdef MOUSE +/* + * init_mouse - check for and initialize mouse driver... + */ +init_mouse() +{ + long miaddr; /* mouse interupt routine address */ + + if(mexist) + return(TRUE); + + /* check if the mouse drive exists first */ + rg.x.ax = 0x3533; /* look at the interrupt 33 address */ + intdosx(&rg, &rg, &segreg); + miaddr = (((long)segreg.es) << 16) + (long)rg.x.bx; + if (miaddr == 0 || *(char *)miaddr == 0xcf) { + mexist = FALSE; + return(TRUE); + } + + /* and then check for the mouse itself */ + rg.x.ax = 0; /* mouse status flag */ + int86(BIOS_MOUSE, &rg, &rg); /* check for the mouse interupt */ + mexist = (rg.x.ax != 0); + nbuttons = rg.x.bx; + + if (mexist == FALSE) + return(TRUE); + + /* if the mouse exists.. get it in the upper right corner */ + rg.x.ax = 4; /* set mouse cursor position */ + rg.x.cx = (term.t_ncol/2) << 3; /* Center of display... */ + rg.x.dx = 1 << 3; /* Second line down */ + int86(BIOS_MOUSE, &rg, &rg); + + /* and set its attributes */ + rg.x.ax = 10; /* set text cursor */ + rg.x.bx = 0; /* software text cursor please */ + rg.x.cx = 0x77ff; /* screen mask */ + rg.x.dx = 0x7700; /* cursor mask */ + int86(BIOS_MOUSE, &rg, &rg); + return(TRUE); +} + + +/* + * mouseon - call made available for programs calling pico to turn ON the + * mouse cursor. + */ +void +mouseon() +{ + rg.x.ax = 1; /* Show Cursor */ + int86(BIOS_MOUSE, &rg, &rg); +} + + +/* + * mouseon - call made available for programs calling pico to turn OFF the + * mouse cursor. + */ +void +mouseoff() +{ + rg.x.ax = 2; /* Hide Cursor */ + int86(BIOS_MOUSE, &rg, &rg); +} +#endif + + +/* + * This function gets called just before we go back home to the command + * interpreter. + */ +ttclose() +{ + if(!Pmaster) + interrupt_ok(); + + return(1); +} + + +/* + * Flush terminal buffer. Does real work where the terminal output is buffered + * up. A no-operation on systems where byte at a time terminal I/O is done. + */ +ttflush() +{ + return(1); +} + + +/* + * specialkey - return special key definition + */ +specialkey(kc) +unsigned kc; +{ + switch(kc){ + case 0x3b00 : return(F1); + case 0x3c00 : return(F2); + case 0x3d00 : return(F3); + case 0x3e00 : return(F4); + case 0x3f00 : return(F5); + case 0x4000 : return(F6); + case 0x4100 : return(F7); + case 0x4200 : return(F8); + case 0x4300 : return(F9); + case 0x4400 : return(F10); + case 0x8500 : return(F11); + case 0x8600 : return(F12); + case 0x4800 : return(KEY_UP); + case 0x5000 : return(KEY_DOWN); + case 0x4b00 : return(KEY_LEFT); + case 0x4d00 : return(KEY_RIGHT); + case 0x4700 : return(KEY_HOME); + case 0x4f00 : return(KEY_END); + case 0x4900 : return(KEY_PGUP); + case 0x5100 : return(KEY_PGDN); + case 0x5300 : return(KEY_DEL); + case 0x48e0 : return(KEY_UP); /* grey key version */ + case 0x50e0 : return(KEY_DOWN); /* grey key version */ + case 0x4be0 : return(KEY_LEFT); /* grey key version */ + case 0x4de0 : return(KEY_RIGHT); /* grey key version */ + case 0x47e0 : return(KEY_HOME); /* grey key version */ + case 0x4fe0 : return(KEY_END); /* grey key version */ + case 0x49e0 : return(KEY_PGUP); /* grey key version */ + case 0x51e0 : return(KEY_PGDN); /* grey key version */ + case 0x53e0 : return(KEY_DEL); /* grey key version */ + default : return(NODATA); + } +} + + +/* + * Read a character from the terminal, performing no editing and doing no echo + * at all. Also mouse events are forced into the input stream here. + */ +int +ttgetc(return_on_intr, recorder, bail_handler) + int return_on_intr; + int (*recorder)(); + int (*bail_handler)(); +{ + return(_bios_keybrd(enhncd ? _NKEYBRD_READ : _KEYBRD_READ)); +} + + +/* + * ctrlkey - used to check if the key hit was a control key. + */ +ctrlkey() +{ + return(_bios_keybrd(enhncd ? _NKEYBRD_SHIFTSTATUS : _KEYBRD_SHIFTSTATUS) + & 0x04); +} + + +/* + * win_multiplex - give DOS in a window a shot at the CPU + */ +win_multiplex() +{ + rg.x.ax = 0x1680; + int86(DOS_MULTIPLEX, &rg, &rg); +} + + +/* + * Read in a key. + * Do the standard keyboard preprocessing. Convert the keys to the internal + * character set. Resolves escape sequences and returns no-op if global + * timeout value exceeded. + */ +GetKey() +{ + unsigned ch = 0, lch, intrupt = 0; + long timein; + + if(mexist || timeo){ + timein = time(0L); +#ifdef MOUSE + if(mexist){ + rg.x.ax = 1; /* Show Cursor */ + int86(BIOS_MOUSE, &rg, &rg); + } +#endif + while(!_bios_keybrd(enhncd ? _NKEYBRD_READY : _KEYBRD_READY)){ +#if MOUSE + if(timeo && time(0L) >= timein+timeo){ + if(mexist){ + rg.x.ax = 2; /* Hide Cursor */ + int86(BIOS_MOUSE, &rg, &rg); + } + return(NODATA); + } + + if(checkmouse(&ch,0,0,0)){ /* something happen ?? */ + if(mexist){ + rg.x.ax = 2; /* Hide Cursor */ + int86(BIOS_MOUSE, &rg, &rg); + } + curwp->w_flag |= WFHARD; + return(ch); + } +#else + if(time(0L) >= timein+timeo) + return(NODATA); +#endif /* MOUSE */ + + /* + * Surrender the CPU... + */ + if(!intrupt++) + win_multiplex(); + } +#ifdef MOUSE + if(mexist){ + rg.x.ax = 2; /* Hide Cursor */ + int86(BIOS_MOUSE, &rg, &rg); + } +#endif /* MOUSE */ + } + + ch = (*term.t_getchar)(0, NULL, NULL); + lch = (ch&0xff); + + if(lch & 0x80 && Pmaster && Pmaster->hibit_entered) + *Pmaster->hibit_entered = 1; + + return((lch && (lch != 0xe0 || !(ch & 0xff00))) + ? (lch < ' ') ? (CTRL|(lch + '@')) + : (lch == ' ' && ctrlkey()) ? (CTRL|'@') : lch + : specialkey(ch)); +} + + +#if MOUSE +/* + * checkmouse - look for mouse events in key menu and return + * appropriate value. + * NOTE: "down", "xxx", and "yyy" aren't used under DOS. + */ +int +checkmouse(ch, down, xxx, yyy) +unsigned *ch; +int down, xxx, yyy; +{ + register int k; /* current bit/button of mouse */ + int mcol; /* current mouse column */ + int mrow; /* current mouse row */ + int sstate; /* current shift key status */ + int newbut; /* new state of the mouse buttons */ + int button; + int rv = 0; + + if(!mexist) + return(FALSE); + + /* check to see if any mouse buttons are different */ + rg.x.ax = 3; /* Get button status and mouse position */ + int86(BIOS_MOUSE, &rg, &rg); + newbut = rg.x.bx; + mcol = rg.x.cx >> 3; + mrow = (rg.x.dx >> 3); + + /* only notice changes */ + if (oldbut == newbut) + return(FALSE); + + if (mcol < 0) /* only on screen presses are legit! */ + mcol = 0; + if (mrow < 0) + mrow = 0; + + sstate = 0; /* get the shift key status as well */ + rg.h.ah = 2; + int86(BIOS_KEYBRD, &rg, &rg); + sstate = rg.h.al; + + button = M_BUTTON_LEFT; + for (k=1; k != (1 << nbuttons); k = k<<1) { + /* For each button on the mouse */ + if ((oldbut&k) != (newbut&k)) { + if(k == 1){ + static int oindex; + int i = 0; + MENUITEM *mp; + + if(newbut&k) /* button down */ + oindex = -1; + + for(mp = mfunc; mp; mp = mp->next) + if(mp->action && M_ACTIVE(mrow, mcol, mp)) + break; + + if(mp){ + unsigned long r; + + r = (*mp->action)((newbut&k) ? M_EVENT_DOWN : M_EVENT_UP, + mrow, mcol, button, 0); + if(r & 0xffff){ + *ch = (unsigned)((r>>16)&0xffff); + rv = TRUE; + } + } + else{ + while(1){ /* see if we understand event */ + if(i >= 12){ + i = -1; + break; + } + + if(M_ACTIVE(mrow, mcol, &menuitems[i])) + break; + + i++; + } + + if(newbut&k){ /* button down */ + oindex = i; /* remember where */ + if(i != -1) /* invert label */ + invert_label(1, &menuitems[i]); + } + else{ /* button up */ + if(oindex != -1){ + if(i == oindex){ + *ch = menuitems[i].val; + rv = 1; + } + } + } + } + + if(!(newbut&k) && oindex != -1) + invert_label(0, &menuitems[oindex]); /* restore label */ + } + + oldbut = newbut; + return(rv); + } + + ++button; + } + + return(FALSE); +} + + +/* + * invert_label - highlight the label of the given menu item. + */ +void +invert_label(state, m) +int state; +MENUITEM *m; +{ + int i, j, r, c, p, col_offset; + char *lp; + int old_state = getrevstate(); + + if(m->val == mnoop) + return; + + rg.h.ah = 3; /* get cursor position */ + int86(BIOS_VIDEO, &rg, &rg); + p = rg.h.bh; + c = rg.h.dl; + r = rg.h.dh; + rg.x.ax = 2; /* Hide Cursor */ + int86(BIOS_MOUSE, &rg, &rg); + /* + * Leave the command name bold + */ + col_offset = (state || !(lp=strchr(m->label, ' '))) ? 0 : (lp - m->label); + (*term.t_move)(m->tl.r, m->tl.c + col_offset); + (*term.t_rev)(state); + for(i = m->tl.r; i <= m->br.r; i++) + for(j = m->tl.c + col_offset; j <= m->br.c; j++) + if(i == m->lbl.r && j == m->lbl.c + col_offset){ /* show label?? */ + lp = m->label + col_offset; + while(*lp && j++ < m->br.c) + (*term.t_putchar)(*lp++); + + continue; + } + else + (*term.t_putchar)(' '); + + (*term.t_rev)(old_state); + rg.h.ah = 2; + rg.h.bh = p; + rg.h.dh = r; + rg.h.dl = c; + int86(BIOS_VIDEO, &rg, &rg); /* restore old position */ + rg.x.ax = 1; /* Show Cursor */ + int86(BIOS_MOUSE, &rg, &rg); +} +#endif /* MOUSE */ + + +/* + * alt_editor - fork off an alternate editor for mail message composition + * + * NOTE: Not yet used under DOS + */ +alt_editor(f, n) + int f, n; +{ + return(-1); +} + + +/* + * bktoshell - suspend and wait to be woken up + */ +int +bktoshell() /* suspend MicroEMACS and wait to wake up */ +{ + int i; + char *shell; + + (*term.t_move)(term.t_nrow, 0); + if(system((shell = getenv("COMSPEC")) ? shell : "command") == -1) + emlwrite("Error loading %s", shell ? shell : "COMMAND.COM"); + else + pico_refresh(0, 1); /* redraw */ + + return(1); +} + + +/* + * P_open - run the given command in a sub-shell returning a file pointer + * from which to read the output + * + * note: + * For OS's other than unix, you will have to rewrite this function. + * Hopefully it'll be easy to exec the command into a temporary file, + * and return a file pointer to that opened file or something. + */ +FILE *P_open(c) +char *c; +{ + char cmdbuf[NLINE]; + sprintf(ptmpfile, tmpnam(NULL)); + sprintf(cmdbuf, "%s > %s", c, ptmpfile); + if(system(cmdbuf) == -1){ + unlink(ptmpfile); + return(NULL); + } + + return(fopen(ptmpfile, "r")); +} + + + +/* + * P_close - close the given descriptor + * + */ +void +P_close(fp) +FILE *fp; +{ + fclose(fp); /* doesn't handle return codes */ + unlink(ptmpfile); +} + + diff --git a/osdep/dos_gen.h b/osdep/dos_gen.h new file mode 100644 index 0000000..adc4a6c --- /dev/null +++ b/osdep/dos_gen.h @@ -0,0 +1,41 @@ +/* + * $Id: dos_gen.h 7884 1998-02-28 00:15:44Z hubert $ + * + * Program: Operating system dependent header - MS DOS Generic + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-1998 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + * + * Notes: + * - This file should contain the cross section of functions useful + * in both DOS and Windows ports of pico. + * + */ + + +#ifdef TURBOC +/* + * big stack for turbo C + */ +extern unsigned _stklen = 16384; +#endif diff --git a/osdep/dosgen b/osdep/dosgen new file mode 100644 index 0000000..fcda750 --- /dev/null +++ b/osdep/dosgen @@ -0,0 +1,1274 @@ +#line 2 "osdep/dosgen" /* So compiler knows orig name of this file.*/ +/* + * $Id: dosgen 13636 2004-05-05 22:01:21Z hubert $ + * + * Program: Operating system dependent routines - MS DOS Generic + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2001 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + * + * Notes: + * - This file should contain the cross section of functions useful + * in both DOS and Windows ports of pico. + * + */ + + +/* + * picosigs - Install any handlers for the signals we're interested + * in catching. + */ +void +picosigs() +{ + /* no op */ +} + + +/* + * Useful definitions... + */ +#ifdef MOUSE +static int mexist = 0; /* is the mouse driver installed? */ +static int nbuttons; /* number of buttons on the mouse */ +static unsigned mnoop; +#endif +static unsigned char okinfname[32] = { + 0, 0, /* ^@ - ^G, ^H - ^O */ + 0, 0, /* ^P - ^W, ^X - ^_ */ + 0x80, 0x17, /* SP - ' , ( - / */ + 0xff, 0xe4, /* 0 - 7 , 8 - ? */ + 0x7f, 0xff, /* @ - G , H - O */ + 0xff, 0xe9, /* P - W , X - _ */ + 0x7f, 0xff, /* ` - g , h - o */ + 0xff, 0xf6, /* p - w , x - DEL */ + 0, 0, /* > DEL */ + 0, 0, /* > DEL */ + 0, 0, /* > DEL */ + 0, 0, /* > DEL */ + 0, 0 /* > DEL */ +}; + + +/* + * fallowc - returns TRUE if c is allowable in filenames, FALSE otw + */ +fallowc(c) +int c; +{ + return(okinfname[c>>3] & 0x80>>(c&7)); +} + + +#ifdef MOUSE +/* + * end_mouse - a no-op on DOS/Windows + */ +void +end_mouse() +{ +} + + +/* + * mouseexist - function to let outsiders know if mouse is turned on + * or not. + */ +mouseexist() +{ + return(mexist); +} +#endif /* MOUSE */ + + +/* + * fexist - returns TRUE if the file exists, FALSE otherwise + */ +fexist(file, m, l) +char *file, *m; +off_t *l; +{ + struct stat sbuf; + + if(l != NULL) + *l = (off_t)0; + + if(stat(file, &sbuf) < 0){ + if(errno == ENOENT) /* File not found */ + return(FIOFNF); + else + return(FIOERR); + } + + if(l != NULL) + *l = (off_t)sbuf.st_size; + + if(sbuf.st_mode & S_IFDIR) + return(FIODIR); + else if(*m == 't') /* no links, just say yes */ + return(FIOSUC); + + if(m[0] == 'r') /* read access? */ + return((S_IREAD & sbuf.st_mode) ? FIOSUC : FIONRD); + else if(m[0] == 'w') /* write access? */ + return((S_IWRITE & sbuf.st_mode) ? FIOSUC : FIONWT); + else if(m[0] == 'x') /* execute access? */ + return((S_IEXEC & sbuf.st_mode) ? FIOSUC : FIONEX); + return(FIOERR); /* what? */ +} + + +/* + * isdir - returns true if fn is a readable directory, false otherwise + * silent on errors (we'll let someone else notice the problem;)). + */ +isdir(fn, l, d) +char *fn; +long *l; +time_t *d; +{ + struct stat sbuf; + + if(l) + *l = 0; + + if(stat(fn, &sbuf) < 0) + return(0); + + if(l) + *l = sbuf.st_size; + + if(d) + *d = sbuf.st_mtime; + + return(sbuf.st_mode & S_IFDIR); +} + + +/* + * gethomedir - returns the users home directory + * Note: home is malloc'd for life of pico + */ +char *gethomedir(l) +int *l; +{ + static char *home = NULL; + static short hlen = 0; + + if(home == NULL){ + char buf[NLINE], *p; + if(Pmaster && Pmaster->home_dir) + p = Pmaster->home_dir; + else { + sprintf(buf, "%c:\\", _getdrive() + 'A' - 1); + p = buf; + } + hlen = strlen(p); + if((home=(char *)malloc(((size_t)hlen + 1) * sizeof(char))) == NULL){ + emlwrite("Problem allocating space for home dir", NULL); + return(0); + } + strcpy(home, p); + } + + if(l) + *l = hlen; + + return(home); +} + + +/* + * homeless - returns true if given file does not reside in the current + * user's home directory tree. + */ +homeless(f) +char *f; +{ + char *home; + int len; + + home = gethomedir(&len); + return(strncmp(home, f, len)); +} + + +/* + * errstr - return system error string corresponding to given errno + * Note: strerror() is not provided on all systems, so it's + * done here once and for all. + */ +char *errstr(err) +int err; +{ + return((err >= 0 && err < sys_nerr) ? sys_errlist[err] : NULL); +} + + +/* + * getfnames - return all file names in the given directory in a single + * malloc'd string. n contains the number of names + */ +char *getfnames(dn, pat, n, e) +char *dn, *pat, *e; +int *n; +{ + int status; + long l; + size_t avail, alloced, incr = 1024; + char *names, *np, *p; + char buf[NLINE]; + struct stat sbuf; +#ifdef WIN32 + struct _finddata_t dbuf; + long findrv; +#else + struct find_t dbuf; /* opened directory */ +#endif + + *n = 0; + + if(stat(dn, &sbuf) < 0){ + if(e) + sprintf(e, "\007Dir \"%s\": %s", dn, strerror(errno)); + + return(NULL); + } + else{ +#define MAX(x,y) ((x) > (y) ? (x) : (y)) + avail = alloced = MAX(sbuf.st_size, incr); + if(!(sbuf.st_mode & S_IFDIR)){ + if(e) + sprintf(e, "\007Not a directory: \"%s\"", dn); + + return(NULL); + } + } + + if((names=(char *)malloc(alloced * sizeof(char))) == NULL){ + if(e) + sprintf(e, "\007Can't malloc space for file names"); + + return(NULL); + } + + np = names; + + strcpy(buf, dn); + sprintf(buf, "%s%s%s*%s%s", dn, + (dn[strlen(dn)-1] == '\\') ? "" : "\\", + (pat && *pat) ? pat : "", + (pat && *pat && strchr(pat, '.')) ? "" : ".", + (pat && *pat && strchr(pat, '.')) ? "" : "*"); +#ifdef WIN32 + if((findrv = _findfirst(buf, &dbuf)) < 0){ +#else + if(_dos_findfirst(buf, _A_NORMAL|_A_SUBDIR, &dbuf) != 0){ +#endif + if(e) + sprintf(e, "Can't find first file in \"%s\"", dn); + + free((char *) names); + return(NULL); + } + + do{ + (*n)++; + p = dbuf.name; + l = strlen(p); + while(avail < l+1){ + char *oldnames; + + alloced += incr; + avail += incr; + oldnames = names; + if((names = (char *)realloc((void *)names, alloced * sizeof(char))) + == NULL){ + if(e) + sprintf(e, "\007Can't malloc enough space for file names"); + + return(NULL); + } + + np = names + (np-oldnames); + } + + avail -= (l+1); + + while((*np++ = *p++) != '\0') + ; + } +#ifdef WIN32 + while(_findnext(findrv, &dbuf) == 0); + _findclose(findrv); +#else + while(_dos_findnext(&dbuf) == 0); +#endif + + return(names); +} + + +/* + * fioperr - given the error number and file name, display error + */ +void +fioperr(e, f) +int e; +char *f; +{ + switch(e){ + case FIOFNF: /* File not found */ + emlwrite("\007File \"%s\" not found", f); + break; + case FIOEOF: /* end of file */ + emlwrite("\007End of file \"%s\" reached", f); + break; + case FIOLNG: /* name too long */ + emlwrite("\007File name \"%s\" too long", f); + break; + case FIODIR: /* file is a directory */ + emlwrite("\007File \"%s\" is a directory", f); + break; + case FIONWT: + emlwrite("\007Write permission denied: %s", f); + break; + case FIONRD: + emlwrite("\007Read permission denied: %s", f); + break; + case FIONEX: + emlwrite("\007Execute permission denied: %s", f); + break; + default: + emlwrite("\007File I/O error: %s", f); + } +} + + +/* + * pfnexpand - pico's function to expand the given file name if there is + * a leading '~' + */ +char *pfnexpand(fn, len) + char *fn; + size_t len; +{ + register char *x, *y, *z; + char *home = NULL; + char name[_MAX_PATH]; + + if(*fn == '~' && *(x = fn + 1) == '\\') { + if(!(home = (char *) getenv("HOME")) + && getenv("HOMEDRIVE") && getenv("HOMEPATH")) + sprintf(home = name, "%s%s", + (char *) getenv("HOMEDRIVE"), (char *) getenv("HOMEPATH")); + + if(home && strlen(home)+strlen(x)= x; + *y-- = *z--) + ; + + /* and insert the expanded address */ + for(x = fn, y = home; *y != '\0'; *x++ = *y++) + ; + } + } + + return(fn); +} + + +/* + * fixpath - make the given pathname into an absolute path + */ +void +fixpath(name, len) + char *name; + size_t len; +{ + char file[_MAX_PATH]; + int dr; + + if(!len) + return; + + /* return the full path of given file, so drive spec? */ + if(name[1] == ':' && isalpha((unsigned char) name[0])){ + if(name[2] != '\\'){ /* including path? */ + dr = toupper((unsigned char)name[0]) - 'A' + 1; + if(_getdcwd(dr, file, _MAX_PATH) != NULL){ + if(file[strlen(file)-1] != '\\') + strncat(file, "\\", sizeof(file)-1-strlen(file)); + + /* add file name */ + strncat(file, &name[2], sizeof(file)-1-strlen(file)); + } + else + return; + } + else + return; /* fully qualified with drive and path! */ + } + else if(name[0] == '\\' && name[1] != '\\') { /* no drive spec! */ + sprintf(file, "%c:%.*s", _getdrive()+'A'-1, len-3, name); + } + else if(name[0] == '\\' && name[1] == '\\'){ /* Windows network drive */ + return; + } + else{ + if(Pmaster && !(gmode & MDCURDIR)){ + strncpy(file, ((gmode & MDTREE) || opertree[0]) + ? opertree : gethomedir(NULL), sizeof(file)-1); + file[sizeof(file)-1] = '\0'; + } + else if(!_getcwd(file, sizeof(file))) /* no qualification */ + return; + + if(*name){ /* if name, append it */ + if(*file && file[strlen(file)-1] != '\\') + strncat(file, "\\", sizeof(file)-1-strlen(file)); + + strncat(file, name, sizeof(file)-1-strlen(file)); + } + } + + strncpy(name, file, len-1); /* copy back to real buffer */ + name[len-1] = '\0'; /* tie off just in case */ +} + + +/* + * compresspath - given a base path and an additional directory, collapse + * ".." and "." elements and return absolute path (appending + * base if necessary). + * + * returns 1 if OK, + * 0 if there's a problem + * new path, by side effect, if things went OK + */ +compresspath(base, path, len) +char *base, *path; +int len; +{ + register int i; + int depth = 0; + char *p; + char *stack[32]; + char pathbuf[NLINE]; + +#define PUSHD(X) (stack[depth++] = X) +#define POPD() ((depth > 0) ? stack[--depth] : "") + + strcpy(pathbuf, path); + fixpath(pathbuf, len); + + p = pathbuf; + for(i=0; pathbuf[i] != '\0'; i++){ /* pass thru path name */ + if(pathbuf[i] == C_FILESEP){ + if(p != pathbuf) + PUSHD(p); /* push dir entry */ + p = &pathbuf[i+1]; /* advance p */ + pathbuf[i] = '\0'; /* cap old p off */ + continue; + } + + if(pathbuf[i] == '.'){ /* special cases! */ + if(pathbuf[i+1] == '.' /* parent */ + && (pathbuf[i+2] == C_FILESEP || pathbuf[i+2] == '\0')){ + if(!strcmp(POPD(),"")) /* bad news! */ + return(0); + + i += 2; + p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1]; + } + else if(pathbuf[i+1] == C_FILESEP || pathbuf[i+1] == '\0'){ + i++; + p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1]; + } + } + } + + if(*p != '\0') + PUSHD(p); /* get last element */ + + path[0] = '\0'; + for(i = 0; i < depth; i++){ + strcat(path, S_FILESEP); + strcat(path, stack[i]); + } + + return(1); /* everything's ok */ +} + + +/* + * This routine is derived from BSD4.3 code, + * Copyright (c) 1987 Regents of the University of California. + * All rights reserved. + */ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)mktemp.c 5.7 (Berkeley) 6/27/88"; +#endif /* LIBC_SCCS and not lint */ + +static char * +was_nonexistent_tmp_name(as, create_it, ext) + char *as; + int create_it; + char *ext; +{ + register char *start, *trv; + char treplace; + struct stat sbuf; + unsigned pid; + static unsigned n = 0; + int fd, tries = 0; + + pid = ((unsigned)getpid() * 100) + n++; + + /* extra X's get set to 0's */ + for(trv = as; *trv; ++trv) + ; + + /* + * We should probably make the name random instead of having it + * be the pid. + */ + while(*--trv == 'X'){ + *trv = (pid % 10) + '0'; + pid /= 10; + } + + /* add the extension, enough room guaranteed by caller */ + if(ext){ + strcat(as, "."); + strcat(as, ext); + } + + /* + * Check for write permission on target directory; if you have + * six X's and you can't write the directory, this will run for + * a *very* long time. + */ + for(start = ++trv; trv > as && *trv != '\\'; --trv) + ; + + if(*trv == '\\'){ + if((trv - as == 2) && isalpha(as[0]) && as[1] == ':') + trv++; + treplace = *trv; + *trv = '\0'; + if(stat(as==trv ? "\\" : as, &sbuf) || !(sbuf.st_mode & S_IFDIR)) + return((char *)NULL); + + *trv = treplace; + } + else if (stat(".", &sbuf) == -1) + return((char *)NULL); + + for(;;){ + if(stat(as, &sbuf)){ /* stat failed */ + if(errno == ENOENT){ /* no such file, success */ + /* + * If create_it is set, create the file so that the + * evil ones don't have a chance to put something there + * that they can read or write before we create it + * ourselves. + */ + if(!create_it || + ((fd=open(as, O_CREAT|O_EXCL|O_WRONLY,0600)) >= 0 + && close(fd) == 0)) + return(as); + else if(++tries > 3) /* open failed unexpectedly */ + return((char *)NULL); + } + else /* failed for unknown reason */ + return((char *)NULL); + } + + for(trv = start;;){ + if(!*trv) + return((char *)NULL); + + /* + * Change the digits from the initial values into + * lower case letters and try again. + */ + if(*trv == 'z') + *trv++ = 'a'; + else{ + if(isdigit((unsigned char)*trv)) + *trv = 'a'; + else + ++*trv; + + break; + } + } + } + /*NOTREACHED*/ +} + + +/* + * This routine is derived from BSD4.3 code, + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + */ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)tmpnam.c 4.5 (Berkeley) 6/27/88"; +#endif /* LIBC_SCCS and not lint */ +/*---------------------------------------------------------------------- + Return a unique file name in a given directory. This is not quite + the same as the usual tempnam() function, though it is similar. + We want it to use the TMP/TMPDIR environment variable only if dir + is NULL, instead of using it regardless if it is set. + We also want it to be safer than tempnam(). + If we return a filename, we are saying that the file did not exist + at the time this function was called (and it wasn't a symlink pointing + to a file that didn't exist, either). + If dir is NULL this is a temp file in a public directory. In that + case we create the file with permission 0600 before returning. + + Args: dir -- The directory to create the name in + prefix -- Prefix of the name + + Result: Malloc'd string equal to new name is returned. It must be free'd + by the caller. Returns the string on success and NULL on failure. + ----*/ +char * +temp_nam(dir, prefix) + char *dir, *prefix; +{ + struct stat buf; + size_t l, ll; + char *f, *name; + + if(!(name = (char *)malloc((unsigned int)NFILEN))) + return((char *)NULL); + + if(!dir && (f = getenv("TMPDIR")) && !stat(f, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(f, WRITE_ACCESS)){ + strncpy(name, f, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + if(!dir && (f = getenv("TMP")) && !stat(f, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(f, WRITE_ACCESS)){ + strncpy(name, f, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + if(!dir && (f = getenv("TEMP")) && !stat(f, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(f, WRITE_ACCESS)){ + strncpy(name, f, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + if(dir){ + strncpy(name, dir, NFILEN-1); + name[NFILEN-1] = '\0'; + if(!*dir || (isalpha(*dir) && *(dir+1) == ':' && !*(dir+2))) + strcat(name, "\\"); + + if((!stat(name, &buf) && (buf.st_mode&S_IFMT) == S_IFDIR) + && !can_access(name, WRITE_ACCESS)){ + strncpy(name, dir, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + } + +#ifndef P_tmpdir +#define P_tmpdir "\\tmp" +#endif + if(!stat(P_tmpdir, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(P_tmpdir, WRITE_ACCESS)){ + strncpy(name, P_tmpdir, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + free(name); + return((char *)NULL); + +done: + if(name[0] && *((f = &name[l=strlen(name)]) - 1) != '\\' && l+1 < NFILEN){ + *f++ = '\\'; + *f = '\0'; + l++; + } + + if(prefix && (ll = strlen(prefix)) && l+ll < NFILEN){ + strcpy(f, prefix); + f += ll; + l += ll; + } + + if(l+6 < NFILEN) + strcpy(f, "XXXXXX"); + else{ + free(name); + return((char *)NULL); + } + + return(was_nonexistent_tmp_name(name, 1, NULL)); +} + + +/*---------------------------------------------------------------------- + + Like temp_nam but create a unique name with an extension. + + Result: Malloc'd string equal to new name is returned. It must be free'd + by the caller. Returns the string on success and NULL on failure. + ----*/ +char * +temp_nam_ext(dir, prefix, ext) + char *dir, *prefix, *ext; +{ + struct stat buf; + size_t l, ll; + char *f, *name; + + if(ext == NULL || *ext == '\0') + return(temp_nam(dir, prefix)); + + if(!(name = (char *)malloc((unsigned int)NFILEN))) + return((char *)NULL); + + if(!dir && (f = getenv("TMPDIR")) && !stat(f, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(f, WRITE_ACCESS)){ + strncpy(name, f, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + if(!dir && (f = getenv("TMP")) && !stat(f, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(f, WRITE_ACCESS)){ + strncpy(name, f, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + if(!dir && (f = getenv("TEMP")) && !stat(f, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(f, WRITE_ACCESS)){ + strncpy(name, f, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + if(dir){ + strncpy(name, dir, NFILEN-1); + name[NFILEN-1] = '\0'; + if(!*dir || (isalpha(*dir) && *(dir+1) == ':' && !*(dir+2))) + strcat(name, "\\"); + + if((!stat(name, &buf) && (buf.st_mode&S_IFMT) == S_IFDIR) + && !can_access(name, WRITE_ACCESS)){ + strncpy(name, dir, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + } + +#ifndef P_tmpdir +#define P_tmpdir "\\tmp" +#endif + if(!stat(P_tmpdir, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(P_tmpdir, WRITE_ACCESS)){ + strncpy(name, P_tmpdir, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + free(name); + return((char *)NULL); + +done: + if(name[0] && *((f = &name[l=strlen(name)]) - 1) != '\\' && l+1 < NFILEN){ + *f++ = '\\'; + *f = '\0'; + l++; + } + + if(prefix && (ll = strlen(prefix)) && l+ll < NFILEN){ + strcpy(f, prefix); + f += ll; + l += ll; + } + + if(l+6+strlen(ext)+1 < NFILEN) + strcpy(f, "XXXXXX"); + else{ + free(name); + return((char *)NULL); + } + + return(was_nonexistent_tmp_name(name, 1, ext)); +} + + +/* + * tmpname - return a temporary file name in the given buffer, the filename + * is in the directory dir unless dir is NULL + */ +void +tmpname(dir, name) +char *dir; +char *name; +{ + char tmp[_MAX_PATH]; + char *t; + + if(!((dir && *dir) || + (dir = getenv("TMPDIR")) || + (dir = getenv("TMP")) || + (dir = getenv("TEMP")))) + if(!(getcwd(dir = tmp, _MAX_PATH) + && fexist(dir, "w", (off_t *) NULL) == FIOSUC)) + dir = "c:\\"; + + if(t = temp_nam_ext(dir, "ae", "txt")){ + strncpy(name, t, NFILEN-1); + name[NFILEN-1] = '\0'; + free(t); + } + else{ + emlwrite("Unable to construct temp file name", NULL); + name[0] = '\0'; + } +} + + +/* + * Take a file name, and from it + * fabricate a buffer name. This routine knows + * about the syntax of file names on the target system. + * I suppose that this information could be put in + * a better place than a line of code. + */ +void +makename(bname, fname) +char bname[]; +char fname[]; +{ + register char *cp1; + register char *cp2; + + cp1 = &fname[0]; + while (*cp1 != 0) + ++cp1; + + while (cp1!=&fname[0] && cp1[-1]!='\\') + --cp1; + cp2 = &bname[0]; + while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';') + *cp2++ = *cp1++; + *cp2 = 0; +} + + +/* + * copy - copy contents of file 'a' into a file named 'b'. Return error + * if either isn't accessible or is a directory + */ +copy(a, b) +char *a, *b; +{ + int in, out, n, rv = 0; + char *cb; + struct stat tsb, fsb; + + if(stat(a, &fsb) < 0){ /* get source file info */ + emlwrite("Can't Copy: %s", errstr(errno)); + return(-1); + } + + if(!(fsb.st_mode&S_IREAD)){ /* can we read it? */ + emlwrite("\007Read permission denied: %s", a); + return(-1); + } + + if((fsb.st_mode&S_IFMT) == S_IFDIR){ /* is it a directory? */ + emlwrite("\007Can't copy: %s is a directory", a); + return(-1); + } + + if(stat(b, &tsb) < 0){ /* get dest file's mode */ + switch(errno){ + case ENOENT: + break; /* these are OK */ + default: + emlwrite("\007Can't Copy: %s", errstr(errno)); + return(-1); + } + } + else{ + if(!(tsb.st_mode&S_IWRITE)){ /* can we write it? */ + emlwrite("\007Write permission denied: %s", b); + return(-1); + } + + if((tsb.st_mode&S_IFMT) == S_IFDIR){ /* is it directory? */ + emlwrite("\007Can't copy: %s is a directory", b); + return(-1); + } + + if(fsb.st_dev == tsb.st_dev && fsb.st_ino == tsb.st_ino){ + emlwrite("\007Identical files. File not copied", NULL); + return(-1); + } + } + + if((in = open(a, _O_RDONLY)) < 0){ + emlwrite("Copy Failed: %s", errstr(errno)); + return(-1); + } + + if((out=creat(b, fsb.st_mode&0xfff)) < 0){ + emlwrite("Can't Copy: %s", errstr(errno)); + close(in); + return(-1); + } + + if((cb = (char *)malloc(NLINE*sizeof(char))) == NULL){ + emlwrite("Can't allocate space for copy buffer!", NULL); + close(in); + close(out); + return(-1); + } + + while(1){ /* do the copy */ + if((n = read(in, cb, NLINE)) < 0){ + emlwrite("Can't Read Copy: %s", errstr(errno)); + rv = -1; + break; /* get out now */ + } + + if(n == 0) /* done! */ + break; + + if(write(out, cb, n) != n){ + emlwrite("Can't Write Copy: %s", errstr(errno)); + rv = -1; + break; + } + } + + free(cb); + close(in); + close(out); + return(rv); +} + + +/* + * Open a file for writing. Return TRUE if all is well, and FALSE on error + * (cannot create). + */ +ffwopen(fn, readonly) +char *fn; +int readonly; +{ + extern FIOINFO g_pico_fio; + + g_pico_fio.flags = FIOINFO_WRITE; + if ((g_pico_fio.fp = fopen(g_pico_fio.name = fn, "w")) == NULL) { + emlwrite("Cannot open file for writing", NULL); + return (FIOERR); + } + +#ifdef MODE_READONLY + if(readonly) + chmod(fn, MODE_READONLY); /* fix access rights */ +#endif + + return (FIOSUC); +} + + +/* + * Close a file. Should look at the status in all systems. + */ +ffclose() +{ + extern FIOINFO g_pico_fio; + + if (fclose(g_pico_fio.fp) != FALSE) { + emlwrite("Error closing file", NULL); + return(FIOERR); + } + + return(FIOSUC); +} + + +/* + * ffelbowroom - make sure the destination's got enough room to receive + * what we're about to write... + */ +ffelbowroom() +{ + return(TRUE); +} + + +/* + * worthit - generic sort of test to roughly gage usefulness of using + * optimized scrolling. + * + * note: + * returns the line on the screen, l, that the dot is currently on + */ +worthit(l) +int *l; +{ + int i; /* l is current line */ + unsigned below; /* below is avg # of ch/line under . */ + + *l = doton(&i, &below); + below = (i > 0) ? below/(unsigned)i : 0; + + return(below > 3); +} + + +/* + * o_insert - optimize screen insert of char c + */ +o_insert(c) + int c; +{ + return(0); +} + + +/* + * o_delete - optimized character deletion + */ +o_delete() +{ + return(0); +} + + +/* + * pico_new_mail - just checks mtime and atime of mail file and notifies user + * if it's possible that they have new mail. + */ +pico_new_mail() +{ + return(0); +} + + + +/* + * time_to_check - checks the current time against the last time called + * and returns true if the elapsed time is > below. + * Newmail won't necessarily check, but we want to give it + * a chance to check or do a keepalive. + */ +time_to_check() +{ + static time_t lasttime = 0L; + + if(!timeo) + return(FALSE); + + if(time((time_t *) 0) - lasttime > (Pmaster ? (time_t)(FUDGE-10) : timeo)){ + lasttime = time((time_t *) 0); + return(TRUE); + } + else + return(FALSE); +} + + +/* + * sstrcasecmp - compare two pointers to strings case independently + */ +sstrcasecmp(s1, s2) +QcompType *s1, *s2; +{ + return((*pcollator)(*(char **)s1, *(char **)s2)); +} + + +int +strucmp(o, r) + char *o, *r; +{ + return(o ? (r ? stricmp(o, r) : 1) : (r ? -1 : 0)); +} + + +int +struncmp(o, r, n) + char *o, *r; + int n; +{ + return(o ? (r ? strnicmp(o, r, n) : 1) : (r ? -1 : 0)); +} + + +/* + * chkptinit -- initialize anything we need to support composer + * checkpointing + */ +void +chkptinit(file, n) + char *file; + int n; +{ + if(!file[0]){ + long gmode_save = gmode; + + if(gmode&MDCURDIR) + gmode &= ~MDCURDIR; /* so fixpath will use home dir */ + + strcpy(file, "#picoTM0.txt"); + fixpath(file, NLINE); + gmode = gmode_save; + } + else{ + int l = strlen(file); + + if(file[l-1] != '\\'){ + file[l++] = '\\'; + file[l] = '\0'; + } + + strcpy(file + l, "#picoTM0.txt"); + } + + if(fexist(file, "r", (off_t *)NULL) == FIOSUC){ /* does file exist? */ + char copy[NLINE]; + + strcpy(copy, "#picoTM1.txt"); + fixpath(copy, NLINE); + rename(file, copy); /* save so we don't overwrite it */ + } + + unlink(file); +} + + +void +set_collation(collation, ctype) + int collation; + int ctype; +{ + extern int collator(); /* strcoll isn't declared on all systems */ +#ifdef LC_COLLATE + char *status = NULL; +#endif + + pcollator = strucmp; + +#ifdef LC_COLLATE + if(collation){ + /* + * This may not have the desired effect, if collator is not + * defined to be strcoll in os.h and strcmp and friends + * don't know about locales. If your system does have strcoll + * but we haven't defined collator to be strcoll in os.h, let us know. + */ + status = setlocale(LC_COLLATE, ""); + + /* + * If there is an error or if the locale is the "C" locale, then we + * don't want to use strcoll because in the default "C" locale strcoll + * uses strcmp ordering and we want strucmp ordering. + * + * The test for "C" isn't really correct, since status does not have to + * be "C" even if we're in the "C" locale. But this works on some systems. + */ + if(status && !(status[0] == 'C' && status[1] == '\0')) + pcollator = collator; + } +#endif +#ifdef LC_CTYPE + if(ctype){ + (void)setlocale(LC_CTYPE, ""); + } +#endif +} + + +/* + * sleep the given number of microseconds + */ +ssleep(s) + clock_t s; +{ + s += clock(); + while(s > clock()) + ; +} + + +/* + * sleep the given number of seconds + */ +sleep(t) + int t; +{ + time_t out = (time_t)t + time((long *) 0); + while(out > time((long *) 0)) + ; +} + + +/* + * map the ftruncate call into DOS' chsize + */ +int +truncate(file, size) + char *file; + long size; +{ + int fd, rv = -1; + + if((fd = open(file, O_RDWR | O_CREAT | S_IREAD | S_IWRITE)) != -1){ + if(chsize(fd, size) == 0) + rv = 0; + + close(fd); + } + + return(rv); +} diff --git a/osdep/fsync.non b/osdep/fsync.non new file mode 100644 index 0000000..2c26978 --- /dev/null +++ b/osdep/fsync.non @@ -0,0 +1,50 @@ +/* + * Program: File sync emulator + * + * Author: Mark Crispin + * Networks and Distributed Computing + * Computing & Communications + * University of Washington + * Administration Building, AG-44 + * Seattle, WA 98195 + * Internet: MRC@CAC.Washington.EDU + * + * Date: 3 May 1995 + * Last Edited: 3 May 1995 + * + * Copyright 1995 by the University of Washington + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appears in all copies and that both the + * above copyright notice and this permission notice appear in supporting + * documentation, and that the name of the University of Washington not be + * used in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. This software is made + * available "as is", and + * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, + * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN + * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT + * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + + +/* Emulator for BSD fsync() call + * Accepts: file name + * Returns: 0 if successful, -1 if failure + */ + +int +our_fsync(fd) + int fd; +{ + sync(); + return 0; +} + + diff --git a/osdep/getcwd b/osdep/getcwd new file mode 100644 index 0000000..8be92ba --- /dev/null +++ b/osdep/getcwd @@ -0,0 +1,17 @@ +/* + * getcwd + */ +char * +getcwd(pth, len) + char *pth; + size_t len; +{ + extern char *getwd(); + + if(!pth) + pth = (char *)malloc(len+1); + + return(getwd(pth)); +} + + diff --git a/osdep/header b/osdep/header new file mode 100644 index 0000000..9286bb2 --- /dev/null +++ b/osdep/header @@ -0,0 +1,32 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: header 7884 1998-02-28 00:15:44Z hubert $"; +#endif +/* + * Program: Routines to support file browser in pico and Pine composer + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-1998 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +#include "headers.h" + + diff --git a/osdep/includer.c b/osdep/includer.c new file mode 100644 index 0000000..7b69f83 --- /dev/null +++ b/osdep/includer.c @@ -0,0 +1,76 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: includer.c 11688 2001-06-21 17:54:43Z hubert $"; +#endif +#include +#include + +/* + * Inflexible cat with include files. + * The include lines must look exactly like include(filename) with no + * spaces before the include, or between the parens and the surrounding + * characters. + * + * This probably ought to just be a script that uses "cat". + */ +main(argc, argv) +int argc; +char *argv[]; +{ + FILE * infile = stdin; + FILE * outfile = stdout; + + if (argc > 1) { + if ((infile = fopen(argv[1], "r")) == NULL) { + fprintf(stderr, "includer: can't open '%s' for input\n", argv[1]); + exit(1); + } + if (argc > 2) { + if ((outfile = fopen(argv[2], "w")) == NULL) { + fprintf(stderr, "includer: can't create '%s'\n", argv[2]); + exit(1); + } + } + } + readfile(infile, outfile); + exit(0); +} + +readfile(fpin, fpout) +FILE *fpin, *fpout; +{ + char line[BUFSIZ+1]; + FILE *fp; + char *p, *fname, *fend; + + while ((p = fgets(line, BUFSIZ, fpin)) != NULL) { + + if (!strncmp("include(", p, strlen("include("))) { + + /* do include */ + fname = strchr(p, '('); + if (fname == NULL) { + fprintf(stderr, "Can't find include file %s\n", p); + exit(1); + } + fname++; + fend = strrchr(fname, ')'); + if (fend == NULL) { + fprintf(stderr, "Can't find include file %s\n", p); + exit(1); + } + *fend = '\0'; + if ((fp = fopen(fname, "r")) == NULL) { + fprintf(stderr, "Can't open include file %s\n", fname); + exit(1); + } + readfile(fp, fpout); + fclose(fp); + + /* skip if comment line (begins with ;) */ + }else if (*p != ';') { + fputs(p, fpout); + } + } + + return(1); +} diff --git a/osdep/makedep b/osdep/makedep new file mode 100755 index 0000000..ec09c62 --- /dev/null +++ b/osdep/makedep @@ -0,0 +1,26 @@ +#! /bin/csh -f +# +# This only finds include dependencies 1-level deep. +# It's just a big, dumb, grep. + +cp makefile makefile.bak +rm -f /tmp/inc$$ + +foreach i ( `/bin/ls *.ic | sed 's/.ic//'` ) + + echo -n ${i}.c: >> /tmp/inc$$ + + foreach j ( `(/bin/ls)` ) + + grep -s "include($j)" ${i}.ic + if ($status == 0)then + echo -n " ${j}" >> /tmp/inc$$ + endif + + end + echo " ${i}.ic" >> /tmp/inc$$ +end + +cat makefile.bas /tmp/inc$$ > makefile + +rm -f /tmp/inc$$ diff --git a/osdep/makefile b/osdep/makefile new file mode 100644 index 0000000..2c7993c --- /dev/null +++ b/osdep/makefile @@ -0,0 +1,73 @@ +# Don't edit makefile, edit makefile.bas instead. +# + +RM= rm -f + +ALL= os-a32.c os-a41.c os-aix.c \ + os-aux.c os-bs2.c os-bsd.c os-bsf.c os-bsi.c os-bso.c \ + os-cvx.c os-dos.c os-dpx.c os-dyn.c \ + os-gen.c os-hpp.c os-isc.c os-lnx.c \ + os-lyn.c os-mnt.c os-neb.c os-nxt.c \ + os-os2.c os-osf.c os-osx.c os-pt1.c os-ptx.c \ + os-s40.c os-sco.c os-sgi.c os-sun.c \ + os-sv4.c os-ult.c os-win.c os-wnt.c \ + os-3b1.c os-att.c os-sc5.c os-nto.c + +.SUFFIXES: .ic + +.ic.c: + ./includer < $*.ic > $*.c + +all: includer $(ALL) + +includer: includer.c + $(CC) -o includer includer.c + +clean: + $(RM) $(ALL) includer + +# You don't have to run this unless you change a .ic file. +depend: + ./makedep + +# Makedep only catches 1-level deep includes. If something depends on a +# 2nd-level include, put it here. + +os-3b1.c: header raw.io read.sel spell.unx term.cap unix os-3b1.ic +os-a32.c: header raw.ios read.sel spell.unx term.cap unix os-a32.ic +os-a41.c: header raw.ios read.sel spell.unx term.inf unix os-a41.ic +os-aix.c: header raw.brk read.sel spell.unx term.cap unix os-aix.ic +os-att.c: header raw.io read.sel spell.unx term.cap unix os-att.ic +os-aux.c: header raw.io read.sel spell.unx term.cap unix os-aux.ic +os-bs2.c: header raw.ios read.sel spell.unx term.cap unix os-bs2.ic +os-bsd.c: getcwd header raw.brk read.sel spell.unx term.cap unix os-bsd.ic +os-bsf.c: header raw.ios read.sel spell.unx term.cap unix os-bsf.ic +os-bsi.c: header raw.brk read.sel spell.unx term.cap unix os-bsi.ic +os-bso.c: header raw.ios read.sel spell.unx term.cap unix os-bso.ic +os-cvx.c: header raw.ios read.sel spell.unx term.cap unix os-cvx.ic +os-dos.c: dos dosgen header term.dos os-dos.ic +os-dpx.c: header raw.ios read.sel spell.unx term.cap unix os-dpx.ic +os-dyn.c: getcwd header raw.brk read.sel spell.unx term.cap unix os-dyn.ic +os-gen.c: header raw.ios read.sel spell.unx term.cap unix os-gen.ic +os-hpp.c: header raw.io read.sel spell.unx term.cap unix os-hpp.ic +os-isc.c: header raw.io read.sel spell.unx term.cap truncate unix os-isc.ic +os-lnx.c: header raw.ios read.sel spell.unx term.inf unix os-lnx.ic +os-lyn.c: getcwd header raw.ios read.sel spell.unx term.cap unix os-lyn.ic +os-mnt.c: header raw.brk read.sel spell.unx term.cap unix os-mnt.ic +os-neb.c: header raw.ios read.sel spell.unx term.cap unix os-neb.ic +os-nto.c: header raw.ios read.sel spell.unx term.cap unix os-nto.ic +os-nxt.c: getcwd header raw.brk read.sel spell.unx term.cap unix os-nxt.ic +os-os2.c: header os2 spell.os2 term.dos os-os2.ic +os-osf.c: header raw.ios read.sel spell.unx term.cap unix os-osf.ic +os-osx.c: header raw.brk read.sel spell.unx term.cap unix os-osx.ic +os-pt1.c: header raw.io read.pol spell.unx term.inf unix os-pt1.ic +os-ptx.c: header raw.io read.pol spell.unx term.inf unix os-ptx.ic +os-s40.c: header raw.brk read.sel spell.unx term.cap unix os-s40.ic +os-sc5.c: header raw.ios read.sel spell.unx term.inf unix os-sc5.ic +os-sco.c: fsync.non header raw.io read.sel spell.unx term.inf truncate unix os-sco.ic +os-sgi.c: header raw.ios read.sel spell.unx term.inf unix os-sgi.ic +os-sun.c: header raw.brk read.sel spell.unx term.cap unix os-sun.ic +os-sv4.c: header raw.ios read.pol spell.unx term.inf unix os-sv4.ic +os-ult.c: header raw.brk read.sel spell.unx term.cap unix os-ult.ic +os-win.c: dosgen header spell.ms win os-win.ic +os-wnt.c: dosgen header spell.ms win os-wnt.ic diff --git a/osdep/makefile.bas b/osdep/makefile.bas new file mode 100644 index 0000000..c013e66 --- /dev/null +++ b/osdep/makefile.bas @@ -0,0 +1,35 @@ +# Don't edit makefile, edit makefile.bas instead. +# + +RM= rm -f + +ALL= os-a32.c os-a41.c os-aix.c \ + os-aux.c os-bs2.c os-bsd.c os-bsf.c os-bsi.c os-bso.c \ + os-cvx.c os-dos.c os-dpx.c os-dyn.c \ + os-gen.c os-hpp.c os-isc.c os-lnx.c \ + os-lyn.c os-mnt.c os-neb.c os-nxt.c \ + os-os2.c os-osf.c os-osx.c os-pt1.c os-ptx.c \ + os-s40.c os-sco.c os-sgi.c os-sun.c \ + os-sv4.c os-ult.c os-win.c os-wnt.c \ + os-3b1.c os-att.c os-sc5.c os-nto.c + +.SUFFIXES: .ic + +.ic.c: + ./includer < $*.ic > $*.c + +all: includer $(ALL) + +includer: includer.c + $(CC) -o includer includer.c + +clean: + $(RM) $(ALL) includer + +# You don't have to run this unless you change a .ic file. +depend: + ./makedep + +# Makedep only catches 1-level deep includes. If something depends on a +# 2nd-level include, put it here. + diff --git a/osdep/makefile.dl b/osdep/makefile.dl new file mode 100644 index 0000000..b8d4037 --- /dev/null +++ b/osdep/makefile.dl @@ -0,0 +1,73 @@ +# Don't edit makefile, edit makefile.bas instead. +# + +RM= rm -f + +ALL= os-a32.c os-a41.c os-aix.c \ + os-aux.c os-bs2.c os-bsd.c os-bsf.c os-bsi.c os-bso.c \ + os-cvx.c os-dos.c os-dpx.c os-dyn.c \ + os-gen.c os-hpp.c os-isc.c os-lnx.c \ + os-lyn.c os-mnt.c os-neb.c os-nxt.c \ + os-os2.c os-osf.c os-osx.c os-pt1.c os-ptx.c \ + os-s40.c os-sco.c os-sgi.c os-sun.c \ + os-sv4.c os-ult.c os-win.c os-wnt.c \ + os-3b1.c os-att.c os-sc5.c os-nto.c + +.SUFFIXES: .ic + +.ic.c: + ./includer < $*.ic > $*.c + +all: includer $(ALL) + +includer: includer.c + $(CC) -o includer includer.c -ldl + +clean: + $(RM) $(ALL) includer + +# You don't have to run this unless you change a .ic file. +depend: + ./makedep + +# Makedep only catches 1-level deep includes. If something depends on a +# 2nd-level include, put it here. + +os-3b1.c: header raw.io read.sel spell.unx term.cap unix os-3b1.ic +os-a32.c: header raw.ios read.sel spell.unx term.cap unix os-a32.ic +os-a41.c: header raw.ios read.sel spell.unx term.inf unix os-a41.ic +os-aix.c: header raw.brk read.sel spell.unx term.cap unix os-aix.ic +os-att.c: header raw.io read.sel spell.unx term.cap unix os-att.ic +os-aux.c: header raw.io read.sel spell.unx term.cap unix os-aux.ic +os-bs2.c: header raw.ios read.sel spell.unx term.cap unix os-bs2.ic +os-bsd.c: getcwd header raw.brk read.sel spell.unx term.cap unix os-bsd.ic +os-bsf.c: header raw.ios read.sel spell.unx term.cap unix os-bsf.ic +os-bsi.c: header raw.brk read.sel spell.unx term.cap unix os-bsi.ic +os-bso.c: header raw.ios read.sel spell.unx term.cap unix os-bso.ic +os-cvx.c: header raw.ios read.sel spell.unx term.cap unix os-cvx.ic +os-dos.c: dos dosgen header term.dos os-dos.ic +os-dpx.c: header raw.ios read.sel spell.unx term.cap unix os-dpx.ic +os-dyn.c: getcwd header raw.brk read.sel spell.unx term.cap unix os-dyn.ic +os-gen.c: header raw.ios read.sel spell.unx term.cap unix os-gen.ic +os-hpp.c: header raw.io read.sel spell.unx term.cap unix os-hpp.ic +os-isc.c: header raw.io read.sel spell.unx term.cap truncate unix os-isc.ic +os-lnx.c: header raw.ios read.sel spell.unx term.inf unix os-lnx.ic +os-lyn.c: getcwd header raw.ios read.sel spell.unx term.cap unix os-lyn.ic +os-mnt.c: header raw.brk read.sel spell.unx term.cap unix os-mnt.ic +os-neb.c: header raw.ios read.sel spell.unx term.cap unix os-neb.ic +os-nto.c: header raw.ios read.sel spell.unx term.cap unix os-nto.ic +os-nxt.c: getcwd header raw.brk read.sel spell.unx term.cap unix os-nxt.ic +os-os2.c: header os2 spell.os2 term.dos os-os2.ic +os-osf.c: header raw.ios read.sel spell.unx term.cap unix os-osf.ic +os-osx.c: header raw.brk read.sel spell.unx term.cap unix os-osx.ic +os-pt1.c: header raw.io read.pol spell.unx term.inf unix os-pt1.ic +os-ptx.c: header raw.io read.pol spell.unx term.inf unix os-ptx.ic +os-s40.c: header raw.brk read.sel spell.unx term.cap unix os-s40.ic +os-sc5.c: header raw.ios read.sel spell.unx term.inf unix os-sc5.ic +os-sco.c: fsync.non header raw.io read.sel spell.unx term.inf truncate unix os-sco.ic +os-sgi.c: header raw.ios read.sel spell.unx term.inf unix os-sgi.ic +os-sun.c: header raw.brk read.sel spell.unx term.cap unix os-sun.ic +os-sv4.c: header raw.ios read.pol spell.unx term.inf unix os-sv4.ic +os-ult.c: header raw.brk read.sel spell.unx term.cap unix os-ult.ic +os-win.c: dosgen header spell.ms win os-win.ic +os-wnt.c: dosgen header spell.ms win os-wnt.ic diff --git a/osdep/makefile.dos b/osdep/makefile.dos new file mode 100644 index 0000000..60851c6 --- /dev/null +++ b/osdep/makefile.dos @@ -0,0 +1,27 @@ +# Don't edit makefile, edit makefile.bas instead. +# + +RM= del + +ALL = os-dos.c os-win.c os-wnt.c + +.SUFFIXES: .ic + +.ic.c: + .\includer < $*.ic > $*.c + +all: includer.exe $(ALL) + +includer.exe: includer.c + $(CC) /F 4000 -o includer.exe includer.c + +clean: + $(RM) $(ALL) includer.exe + +# You don't have to run this unless you change a .ic file. +depend: + echo Dependencies must be built under Unix + +os-win.c: os-win.ic header dosgen win spell.ms +os-wnt.c: os-win.ic header dosgen win spell.ms +os-dos.c: os-dos.ic header dosgen dos term.dos diff --git a/osdep/os-3b1.h b/osdep/os-3b1.h new file mode 100644 index 0000000..b2259d6 --- /dev/null +++ b/osdep/os-3b1.h @@ -0,0 +1,191 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, Convergent Tech 3b1 version. See also the os-3b1.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + +/* + * 3b1 definition requirements + */ +#define opendir(dn) fopen(dn, "r") +#define closedir(dirp) fclose(dirp) +typedef struct + { + int dd_fd; /* file descriptor */ + int dd_loc; /* offset in block */ + int dd_size; /* amount of valid data */ + char *dd_buf; /* directory block */ + } DIR; /* stream data from opendir() */ + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include *//* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include *//* only one or the other */ + +/* #define SigType void */ /* value returned by sig handlers is void */ +#define SigType int /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS *//* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType int /* qsort arg is of type void * */ +/* #define QSType void */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +#define HAVE_TERMIO /* this is for pure System V */ +#include /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* + * Make sys_errlist visible + */ +extern char *sys_errlist[]; +extern int sys_nerr; + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-3b1.ic b/osdep/os-3b1.ic new file mode 100644 index 0000000..0e25341 --- /dev/null +++ b/osdep/os-3b1.ic @@ -0,0 +1,15 @@ +; +; Convergent Tech 3b1 os-3b1.ic file for building os-3b1.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.io) + +include(term.cap) diff --git a/osdep/os-a32.h b/osdep/os-a32.h new file mode 100644 index 0000000..2836852 --- /dev/null +++ b/osdep/os-a32.h @@ -0,0 +1,189 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, AIX 3.2 version. See also the os-a32.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#define USE_DIRENT +#include +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strcoll + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +/* #include */ /* sometimes both required, sometimes */ +#include /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIGNALHASARG 1 +#define SIG_PROTO(args) args + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#include /* this is needed for struct winsize on aix */ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*------------ AIX 3.2 needs this for types passed select() ------------*/ +#include + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + + +/* memmove() is a built-in for AIX 3.2 xlc. */ +#define bcopy(a,b,s) memmove (b, a, s) + +/* + * Make sys_errlist visible + */ +extern char *sys_errlist[]; +extern int sys_nerr; + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-a32.ic b/osdep/os-a32.ic new file mode 100644 index 0000000..54248ac --- /dev/null +++ b/osdep/os-a32.ic @@ -0,0 +1,15 @@ +; +; AIX 3.2 os-a32.ic file for building os-a32.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.cap) diff --git a/osdep/os-a41.h b/osdep/os-a41.h new file mode 100644 index 0000000..95cedc2 --- /dev/null +++ b/osdep/os-a41.h @@ -0,0 +1,184 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, AIX 4.1 version. See also the os-a41.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#define USE_DIRENT +#include +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strcoll + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +/* #include */ /* sometimes both required, sometimes */ +#include /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIGNALHASARG 1 +#define SIG_PROTO(args) args + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ /* qsort arg is of type char * */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#include /* this is needed for struct winsize on aix */ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +#define USE_TERMINFO /* use terminfo instead of termcap */ +/* #define USE_TERMCAP */ /* use termcap */ + + + +/*------------ AIX 4.1 needs this for types passed select() ------------*/ +#include +#define setpgrp setpgid + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + + +/* memmove() is a built-in for AIX 3.2 xlc. */ +#define bcopy(a,b,s) memmove (b, a, s) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-a41.ic b/osdep/os-a41.ic new file mode 100644 index 0000000..d9734a3 --- /dev/null +++ b/osdep/os-a41.ic @@ -0,0 +1,15 @@ +; +; AIX 4.1 os-a41.ic file for building os-a41.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.inf) diff --git a/osdep/os-aix.h b/osdep/os-aix.h new file mode 100644 index 0000000..cf0817b --- /dev/null +++ b/osdep/os-aix.h @@ -0,0 +1,181 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, AIX 370 version. See also the os-aix.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include +#include + +#define USE_DIRENT +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS *//* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +#include /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +#define HAVE_WAIT_UNION /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* + * Make sys_errlist visible + */ +extern char *sys_errlist[]; +extern int sys_nerr; + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-aix.ic b/osdep/os-aix.ic new file mode 100644 index 0000000..326940f --- /dev/null +++ b/osdep/os-aix.ic @@ -0,0 +1,15 @@ +; +; AIX 370 os-aix.ic file for building os-aix.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.brk) + +include(term.cap) diff --git a/osdep/os-att.h b/osdep/os-att.h new file mode 100644 index 0000000..aca9ac5 --- /dev/null +++ b/osdep/os-att.h @@ -0,0 +1,181 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, ?? version. See also the os-att.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include + +#define USE_DIRENT +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType int +/* #define QSType void */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +#define HAVE_TERMIO /* this is for pure System V */ +#include /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* + * Make sys_errlist visible + */ +extern char *sys_errlist[]; +extern int sys_nerr; + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-att.ic b/osdep/os-att.ic new file mode 100644 index 0000000..2814ed9 --- /dev/null +++ b/osdep/os-att.ic @@ -0,0 +1,15 @@ +; +; ?? os-att.ic file for building os-att.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.io) + +include(term.cap) diff --git a/osdep/os-aux.h b/osdep/os-aux.h new file mode 100644 index 0000000..26af5a5 --- /dev/null +++ b/osdep/os-aux.h @@ -0,0 +1,189 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, A/UX version. See also the os-aux.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include + +#define USE_DIRENT +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +#include /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +#define HAVE_TERMIO /* this is for pure System V */ +#include /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + + +/* memcpy() is no good for overlapping blocks. If that's a problem, use + * the memmove() in ../c-client + */ +#define bcopy(a,b,s) memcpy (b, a, s) + +/* + * Make sys_errlist visible + */ +extern char *sys_errlist[]; +extern int sys_nerr; + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-aux.ic b/osdep/os-aux.ic new file mode 100644 index 0000000..1d17570 --- /dev/null +++ b/osdep/os-aux.ic @@ -0,0 +1,15 @@ +; +; A/UX os-aux.ic file for building os-aux.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.io) + +include(term.cap) diff --git a/osdep/os-bs2.h b/osdep/os-bs2.h new file mode 100644 index 0000000..20ee09f --- /dev/null +++ b/osdep/os-bs2.h @@ -0,0 +1,178 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, BSDI V2-V4 version. See also the os-bs2.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +/* #include */ /* sometimes both required, sometimes */ +#include /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +#define NON_BLOCKING_IO FNDELAY /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +#define HAVE_WAIT_UNION /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/var/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* + * Make sys_errlist visible + */ +/* extern char *sys_errlist[]; */ +/* extern int sys_nerr; */ + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-bs2.ic b/osdep/os-bs2.ic new file mode 100644 index 0000000..92a8326 --- /dev/null +++ b/osdep/os-bs2.ic @@ -0,0 +1,15 @@ +; +; BSDI V2-V4 os-bs2.ic file for building os-bs2.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.cap) diff --git a/osdep/os-bsd.h b/osdep/os-bsd.h new file mode 100644 index 0000000..ed77d68 --- /dev/null +++ b/osdep/os-bsd.h @@ -0,0 +1,184 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, BSD 4.3 version. See also the os-bsd.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +char *getenv(); +FILE *tmpfile(); +extern int stat(); +extern int errno; +typedef long fpos_t; + +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +/* #include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +/* #define SigType void */ /* value returned by sig handlers is void */ +#define SigType int /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +/* #define QSType void */ +#define QSType char /* qsort arg is of type char * */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +#define NON_BLOCKING_IO FNDELAY /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +#include /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +#define HAVE_WAIT_UNION /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* + * Make sys_errlist visible + */ +extern char *sys_errlist[]; +extern int sys_nerr; + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-bsd.ic b/osdep/os-bsd.ic new file mode 100644 index 0000000..645a0f5 --- /dev/null +++ b/osdep/os-bsd.ic @@ -0,0 +1,17 @@ +; +; BSD 4.3 os-bsd.ic file for building os-bsd.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.brk) + +include(term.cap) + +include(getcwd) diff --git a/osdep/os-bsf.h b/osdep/os-bsf.h new file mode 100644 index 0000000..578aa13 --- /dev/null +++ b/osdep/os-bsf.h @@ -0,0 +1,182 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, FreeBSD version. See also the os-bsf.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include +#include +#include + +#define USE_DIRENT +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/* #define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* + * Make sys_errlist visible + */ +/* extern char *sys_errlist[]; */ +/* extern int sys_nerr; */ + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-bsf.ic b/osdep/os-bsf.ic new file mode 100644 index 0000000..0a700de --- /dev/null +++ b/osdep/os-bsf.ic @@ -0,0 +1,15 @@ +; +; FreeBSD os-bsf.ic file for building os-bsf.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.cap) diff --git a/osdep/os-bsi.h b/osdep/os-bsi.h new file mode 100644 index 0000000..7511fb0 --- /dev/null +++ b/osdep/os-bsi.h @@ -0,0 +1,179 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, BSDI V1 version. See also the os-bsi.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +/* #include */ /* sometimes both required, sometimes */ +#include /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +#define NON_BLOCKING_IO FNDELAY /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +#include /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +#define HAVE_WAIT_UNION /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/var/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* + * Make sys_errlist visible + */ +/* extern char *sys_errlist[]; */ +/* extern int sys_nerr; */ + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-bsi.ic b/osdep/os-bsi.ic new file mode 100644 index 0000000..cd64dc7 --- /dev/null +++ b/osdep/os-bsi.ic @@ -0,0 +1,15 @@ +; +; BSCI V1 os-bsi.ic file for building os-bsi.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.brk) + +include(term.cap) diff --git a/osdep/os-bso.h b/osdep/os-bso.h new file mode 100644 index 0000000..63066e8 --- /dev/null +++ b/osdep/os-bso.h @@ -0,0 +1,180 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, OpenBSD version. See also the os-bso.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#define USE_DIRENT +#include +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/* #define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/var/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/local/bin/ispell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* + * Make sys_errlist visible + */ +/* extern char *sys_errlist[]; */ +/* extern int sys_nerr; */ + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-bso.ic b/osdep/os-bso.ic new file mode 100644 index 0000000..8128068 --- /dev/null +++ b/osdep/os-bso.ic @@ -0,0 +1,15 @@ +; +; OpenBSD os-bso.ic file for building os-bso.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.cap) diff --git a/osdep/os-cvx.h b/osdep/os-cvx.h new file mode 100644 index 0000000..4996f84 --- /dev/null +++ b/osdep/os-cvx.h @@ -0,0 +1,181 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, Convex version. See also the os-cvx.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include + +#define USE_DIRENT +#include + +char *getenv(); +FILE *tmpfile(); +extern int errno; +int fgetpos(); int fsetpos(); +typedef long fpos_t; + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +/* #include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +/* #define SigType void */ /* value returned by sig handlers is void */ +#define SigType int /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +/* #define QSType void */ +#define QSType char /* qsort arg is of type char * */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +#define HAVE_WAIT_UNION /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-cvx.ic b/osdep/os-cvx.ic new file mode 100644 index 0000000..0c59f66 --- /dev/null +++ b/osdep/os-cvx.ic @@ -0,0 +1,15 @@ +; +; Convex os-cvx.ic file for building os-cvx.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.cap) diff --git a/osdep/os-cyg.h b/osdep/os-cyg.h new file mode 100644 index 0000000..4f098af --- /dev/null +++ b/osdep/os-cyg.h @@ -0,0 +1,192 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, Cygwin b20.1 version. See also the os-cyg.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + Port maintainer: Eduardo Chappa + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include +#include +#include + +#define USE_DIRENT +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strcoll + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/*#include */ /* only one or the other */ + +#ifndef SIGSYS +#define SIGSYS SIGUNUSED +#endif + +#ifndef SIGEMT +#define SIGEMT SIGUNUSED +#endif + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#undef vfork +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + +#define LPASS8 0x0800 + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/var/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* If stat is strictly POSIX and stat'ing a directory returns a meaningless + st_size value, define this. */ +#define STAT_STRICT_POSIX 1 + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-cyg.ic b/osdep/os-cyg.ic new file mode 100644 index 0000000..0aa7218 --- /dev/null +++ b/osdep/os-cyg.ic @@ -0,0 +1,15 @@ +; +; Cygwin B2.01 os-cyg.ic file for building os-cyg.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.cap) diff --git a/osdep/os-dos.h b/osdep/os-dos.h new file mode 100644 index 0000000..4129603 --- /dev/null +++ b/osdep/os-dos.h @@ -0,0 +1,195 @@ +#line 2 "osdep\os-dos.h" +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, DOS version. See also the os-dos.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + +/*-------- Standard ANSI functions usually defined in stdlib.h ---------*/ +#include +#include +#include +#include +#include +#undef CTRL +#include +#include + +#include +#include +#ifdef PCTCP +#include <4bsddefs.h> /* PC/TCP Include Files */ +#include +#undef signal /* override their stupid def */ +#define sleep _sleep /* use pico's sleep function */ +#undef write /* make way:c-client def's write */ +#undef SIGCHLD +#else +#ifdef LWP +#include /* LanWorkplace Include Files */ +#include +#include +#else +#ifdef PCNFS +#include +#include +#define ENAMETOOLONG 0 /* unsupported errno value */ +#else +#include /* WATTCP Include File */ +#define ENAMETOOLONG 0 /* unsupported errno value */ +#define word p_word /* compensate for bad args labels */ +#endif +#endif +#endif +#include +#include +#include +#include +#include + +#undef ERROR + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) args + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned long usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +/* #define USE_TERMCAP */ /* use termcap */ + + + +/*-------- Is window resizing available? -------------------------------*/ +/* #define RESIZING */ /* SIGWINCH and friends */ + /* Actually, under windows it is, but RESIZING compiles in UNIX + * signals code for determining when the window resized. Window's + * works differently. */ + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (25) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '\\' +#define S_FILESEP "\\" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#undef SPELLER + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (S_IREAD | S_IWRITE) + +#define IBMPC 1 + +#ifdef PCTCP +#define sleep _sleep +#define _O_RDONLY O_RDONLY +#endif + +/* + * IBM PC ROM BIOS Services used + */ +#define BIOS_VIDEO 0x10 +#define BIOS_KEYBRD 0x16 +#define BIOS_MOUSE 0x33 +#define DOS_MULTIPLEX 0x2f + +#ifdef maindef +/* possible names and paths of help files under different OSs */ + +char *pathname[] = { + "picorc", + "pico.hlp", + "\\usr\\local\\", + "\\usr\\lib\\", + "" +}; + +#define NPNAMES (sizeof(pathname)/sizeof(char *)) + +/* + * Make sys_errlist visible + */ +extern char *sys_errlist[]; +extern int sys_nerr; + +jmp_buf got_hup; + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-dos.ic b/osdep/os-dos.ic new file mode 100644 index 0000000..a598d69 --- /dev/null +++ b/osdep/os-dos.ic @@ -0,0 +1,11 @@ +; +; DOS os-dos.ic file for building os-dos.c. +; +; Boilerplate header. +include(header) + +include(dos) + +include(dosgen) + +include(term.dos) diff --git a/osdep/os-dpx.h b/osdep/os-dpx.h new file mode 100644 index 0000000..a809f3a --- /dev/null +++ b/osdep/os-dpx.h @@ -0,0 +1,180 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, Bull DPX/2 B.O.S. version. See also the os-dpx.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +FILE *tmpfile(); +#include +#include +#include + +#define USE_DIRENT +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +#define SYSV_SIGNALS /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +/* #define QSType void */ +#define QSType char /* qsort arg is of type char * */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*------------ DPX needs this for types passed select() ------------*/ +#include + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-dpx.ic b/osdep/os-dpx.ic new file mode 100644 index 0000000..5fe4fe9 --- /dev/null +++ b/osdep/os-dpx.ic @@ -0,0 +1,15 @@ +; +; Bull DPX/2 B.O.S os-dpx.ic file for building os-dpx.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.cap) diff --git a/osdep/os-dyn.h b/osdep/os-dyn.h new file mode 100644 index 0000000..91403ad --- /dev/null +++ b/osdep/os-dyn.h @@ -0,0 +1,190 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, Dynix version. See also the os-dyn.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include + +char *getenv(); +extern char *getcwd(); +void *memset(); +void *malloc(); +void free(); +void *realloc(); +extern int errno; +typedef long fpos_t; +typedef unsigned long size_t; +#define strchr index +#define strrchr rindex + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +/* #define SigType void */ /* value returned by sig handlers is void */ +#define SigType int /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +#include /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +#define HAVE_WAIT_UNION /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* + * Make sys_errlist visible + */ +extern char *sys_errlist[]; +extern int sys_nerr; + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-dyn.ic b/osdep/os-dyn.ic new file mode 100644 index 0000000..b4c9b19 --- /dev/null +++ b/osdep/os-dyn.ic @@ -0,0 +1,17 @@ +; +; Sequent Dynix (not ptx) os-dyn.ic file for building os-dyn.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.brk) + +include(term.cap) + +include(getcwd) diff --git a/osdep/os-gen.h b/osdep/os-gen.h new file mode 100644 index 0000000..9675314 --- /dev/null +++ b/osdep/os-gen.h @@ -0,0 +1,173 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, generic version. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +/* These three may vary widely from port to port. */ +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strcoll + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIGNALHASARG 1 +#define SIG_PROTO(args) args + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +#define HAVE_WAIT_UNION /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-gen.ic b/osdep/os-gen.ic new file mode 100644 index 0000000..e62b004 --- /dev/null +++ b/osdep/os-gen.ic @@ -0,0 +1,15 @@ +; +; Generic os-gen.ic file for building os-gen.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.cap) diff --git a/osdep/os-gso.h b/osdep/os-gso.h new file mode 100644 index 0000000..5b64efc --- /dev/null +++ b/osdep/os-gso.h @@ -0,0 +1,178 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, Sun Solaris (with gcc) version. See also the os-sol.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +FILE *tmpfile(); +#include + +#define USE_DIRENT +#include +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strcoll + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +#define USE_POLL /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +#define USE_TERMINFO /* use terminfo instead of termcap */ +/* #define USE_TERMCAP */ /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +#define bcopy(a,b,s) memcpy (b, a, s) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-gsu.h b/osdep/os-gsu.h new file mode 100644 index 0000000..ef9f59b --- /dev/null +++ b/osdep/os-gsu.h @@ -0,0 +1,174 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, SunOS 4.1 version. See also the os-sun.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +char *getenv(); +typedef long fpos_t; + +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strcoll + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +#define NON_BLOCKING_IO FNDELAY /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +#include /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +#define HAVE_WAIT_UNION /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-hpp.h b/osdep/os-hpp.h new file mode 100644 index 0000000..32d8cd4 --- /dev/null +++ b/osdep/os-hpp.h @@ -0,0 +1,175 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, HP/UX version. See also the os-hpp.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include +#include + +#define USE_DIRENT +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strcoll + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +#define HAVE_TERMIO /* this is for pure System V */ +#include /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-hpp.ic b/osdep/os-hpp.ic new file mode 100644 index 0000000..ca29e26 --- /dev/null +++ b/osdep/os-hpp.ic @@ -0,0 +1,15 @@ +; +; HP/UX os-hpp.ic file for building os-hpp.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.io) + +include(term.cap) diff --git a/osdep/os-isc.h b/osdep/os-isc.h new file mode 100644 index 0000000..33bb607 --- /dev/null +++ b/osdep/os-isc.h @@ -0,0 +1,193 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, ISC version. See also the os-isc.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +char *getenv(); + +#include +#include +#include + +#define USE_DIRENT +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +#define HAVE_TERMIO /* this is for pure System V */ +#include /* Sys V */ +#include +#include +#include /* for ptem.h */ +#include /* for struct winsize */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + + +/* memcpy() is no good for overlapping blocks. If that's a problem, use + * the memmove() in ../c-client + */ +#define bcopy(a,b,s) memcpy (b, a, s) + +/* + * Make sys_errlist visible + */ +extern char *sys_errlist[]; +extern int sys_nerr; + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-isc.ic b/osdep/os-isc.ic new file mode 100644 index 0000000..6d9562d --- /dev/null +++ b/osdep/os-isc.ic @@ -0,0 +1,17 @@ +; +; ISC os-isc.ic file for building os-isc.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.io) + +include(term.cap) + +include(truncate) diff --git a/osdep/os-lnx.h b/osdep/os-lnx.h new file mode 100644 index 0000000..343c33d --- /dev/null +++ b/osdep/os-lnx.h @@ -0,0 +1,194 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, Linux 0.99.10 version. See also the os-lnx.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include +#include + +#define USE_DIRENT +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strcoll + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#ifndef SIGSYS +#define SIGSYS SIGUNUSED +#endif + +#ifndef SIGEMT +#define SIGEMT SIGUNUSED +#endif + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIGNALHASARG 1 +#define SIG_PROTO(args) args + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +#define USE_TERMINFO /* use terminfo instead of termcap */ +/* #define USE_TERMCAP */ /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + +#define LPASS8 0x0800 + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/var/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* + * Make sys_errlist visible + */ +/* extern char *sys_errlist[]; */ +/* extern int sys_nerr; */ + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-lnx.ic b/osdep/os-lnx.ic new file mode 100644 index 0000000..04e2f55 --- /dev/null +++ b/osdep/os-lnx.ic @@ -0,0 +1,15 @@ +; +; Linux 0.99.10 os-lnx.ic file for building os-lnx.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.inf) diff --git a/osdep/os-lyn.h b/osdep/os-lyn.h new file mode 100644 index 0000000..448ad16 --- /dev/null +++ b/osdep/os-lyn.h @@ -0,0 +1,175 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, Lynxos version. See also the os-lyn.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +extern int stat(); +extern char *getcwd(char *, int); +extern int errno; +#include +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +/* #include */ /* sometimes both required, sometimes */ +#include /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +#define NON_BLOCKING_IO FNDELAY /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +#define HAVE_WAIT_UNION /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-lyn.ic b/osdep/os-lyn.ic new file mode 100644 index 0000000..3ceeb87 --- /dev/null +++ b/osdep/os-lyn.ic @@ -0,0 +1,17 @@ +; +; Lynxos os-lyn.ic file for building os-lyn.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.cap) + +include(getcwd) diff --git a/osdep/os-mct.h b/osdep/os-mct.h new file mode 100644 index 0000000..413ec1e --- /dev/null +++ b/osdep/os-mct.h @@ -0,0 +1,173 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, Machten version. See also the os-mct.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIGNALHASARG 1 +#define SIG_PROTO(args) args + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +#define NON_BLOCKING_IO FNDELAY /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +#include /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +#define HAVE_WAIT_UNION /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/var/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-mnt.h b/osdep/os-mnt.h new file mode 100644 index 0000000..ba5ad68 --- /dev/null +++ b/osdep/os-mnt.h @@ -0,0 +1,188 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, MiNT version. See also the os-mnt.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include +#include + +#define USE_DIRENT +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strcoll + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#ifndef SIGSYS +#define SIGSYS SIGUNUSED +#endif + +#ifndef SIGEMT +#define SIGEMT SIGUNUSED +#endif + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ /* qsort arg is of type char * */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NDELAY +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + +/*-------------- MiNT needs also this -----------------------------------*/ +#define EAGAIN EWOULDBLOCK + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +#include /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +#define HAVE_WAIT_UNION /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + +#define LPASS8 0x0800 + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/var/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-mnt.ic b/osdep/os-mnt.ic new file mode 100644 index 0000000..d468ece --- /dev/null +++ b/osdep/os-mnt.ic @@ -0,0 +1,15 @@ +; +; MiNT os-mnt.ic file for building os-mnt.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.brk) + +include(term.cap) diff --git a/osdep/os-neb.h b/osdep/os-neb.h new file mode 100644 index 0000000..32ed762 --- /dev/null +++ b/osdep/os-neb.h @@ -0,0 +1,183 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, NetBSD version. See also the os-neb.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include +#include + +#define USE_DIRENT +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strcasecmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef u_int32_t usign32_t; +typedef u_int16_t usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/var/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* + * Make sys_errlist visible + */ +/* extern char *sys_errlist[]; */ +/* extern int sys_nerr; */ + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-neb.ic b/osdep/os-neb.ic new file mode 100644 index 0000000..1b1a9ee --- /dev/null +++ b/osdep/os-neb.ic @@ -0,0 +1,15 @@ +; +; NetBSD os-neb.ic file for building os-neb.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.cap) diff --git a/osdep/os-nto.h b/osdep/os-nto.h new file mode 100644 index 0000000..e549f1e --- /dev/null +++ b/osdep/os-nto.h @@ -0,0 +1,179 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, QNX Neutrino version. + (Kris Eric Warkentin ) + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +/* These three may vary widely from port to port. */ +#include +#include +#include + +#define USE_DIRENT +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strcoll + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIGNALHASARG 1 +#define SIG_PROTO(args) args + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/var/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-nto.ic b/osdep/os-nto.ic new file mode 100644 index 0000000..4766541 --- /dev/null +++ b/osdep/os-nto.ic @@ -0,0 +1,15 @@ +; +; QNX Neutrino os-nto.ic file for building os-nto.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.cap) diff --git a/osdep/os-nxt.h b/osdep/os-nxt.h new file mode 100644 index 0000000..dcd5738 --- /dev/null +++ b/osdep/os-nxt.h @@ -0,0 +1,172 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, NeXT version. See also the os-nxt.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIGNALHASARG 1 +#define SIG_PROTO(args) args + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +#define NON_BLOCKING_IO FNDELAY /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +#include /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +#define HAVE_WAIT_UNION /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-nxt.ic b/osdep/os-nxt.ic new file mode 100644 index 0000000..213c206 --- /dev/null +++ b/osdep/os-nxt.ic @@ -0,0 +1,17 @@ +; +; NeXT os-nxt.ic file for building os-nxt.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.brk) + +include(term.cap) + +include(getcwd) diff --git a/osdep/os-os2.h b/osdep/os-os2.h new file mode 100644 index 0000000..e63ecd5 --- /dev/null +++ b/osdep/os-os2.h @@ -0,0 +1,186 @@ +#line 2 "osdep\os-os2.h" +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, OS/2 version. See also the os-os2.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + +/*-------- Standard ANSI functions usually defined in stdlib.h ---------*/ +#include +#include +#include +#include + +#define USE_DIRENT +#include +#define INCL_BASE +#define INCL_NOPM +#define INCL_VIO +#define INCL_KBD +#define INCL_MOU +#define INCL_DOS +#define + +#include +#include +#include +#include +#include +#include +#include + +#undef ERROR + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#undef SIGCHLD /* clear unsupp'd signal def */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned long usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + +#define QcompType const void + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +/* #define USE_TERMCAP */ /* use termcap */ + + + +/*-------- Is window resizing available? -------------------------------*/ +/* #define RESIZING */ + /* Actually, under windows it is, but RESIZING compiles in UNIX + * signals code for determining when the window resized. Window's + * works differently. */ + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (25) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '\\' +#define S_FILESEP "\\" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "ispell" + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (S_IREAD | S_IWRITE) + +#define IBMPC 1 + +#define _O_RDONLY O_RDONLY + +#ifdef maindef +/* possible names and paths of help files under different OSs */ + +char *pathname[] = { + "picorc", + "pico.hlp", + "\\usr\\local\\", + "\\usr\\lib\\", + "" +}; + +#define NPNAMES (sizeof(pathname)/sizeof(char *)) + +jmp_buf got_hup; + +struct KBSTREE *kpadseqs = NULL; + +int os2_fflush(FILE *f); + +#ifndef fflush +#define fflush os2_fflush +#endif + +#endif + +int kbd_ready(); +int kbd_getkey(); +int kbd_peek(); +void kbd_flush(); + +/* + * Make sys_errlist visible + */ +extern char *sys_errlist[]; +extern int sys_nerr; + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-os2.ic b/osdep/os-os2.ic new file mode 100644 index 0000000..7926235 --- /dev/null +++ b/osdep/os-os2.ic @@ -0,0 +1,11 @@ +; +; OS/2 os-os2.ic file for building os-os2.c. +; +; Boilerplate header. +include(header) + +include(os2) + +include(term.dos) + +include(spell.os2) diff --git a/osdep/os-osf.h b/osdep/os-osf.h new file mode 100644 index 0000000..2caa0a0 --- /dev/null +++ b/osdep/os-osf.h @@ -0,0 +1,187 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, OSF/1 version. See also the os-osf.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + +char *getenv(); /* often declared in stdlib.h */ +FILE *tmpfile(); +extern int errno; +typedef long fpos_t; + +#define USE_DIRENT +#include +#include +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strcoll + + + +/*----------------- time.h ---------------------------------------------*/ +/* #include */ +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +/* #define QSType void */ /* qsort arg is of type void * */ +/* #define QSType char */ +#define QSType size_t + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* + * Make sys_errlist visible + */ +/* extern char *sys_errlist[]; */ +/* extern int sys_nerr; */ + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-osf.ic b/osdep/os-osf.ic new file mode 100644 index 0000000..1bc346a --- /dev/null +++ b/osdep/os-osf.ic @@ -0,0 +1,15 @@ +; +; OSF/1 os-osf.ic file for building os-osf.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.cap) diff --git a/osdep/os-osx.h b/osdep/os-osx.h new file mode 100644 index 0000000..793adb0 --- /dev/null +++ b/osdep/os-osx.h @@ -0,0 +1,194 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, Mac OS X version. See also the os-osx.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +char *getenv(); +FILE *tmpfile(); +extern int stat(); +extern int errno; + +#include +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + +/*------- Mac OS X specific includes -----------------------------------*/ +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +/* #include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +/* #define QSType void */ +#define QSType char /* qsort arg is of type char * */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +#define NON_BLOCKING_IO FNDELAY /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +#include /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +#define HAVE_WAIT_UNION /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* + * There is a vfork on MacOS X but it clashes with our use. We set + * SIGCHLD to default action in the child in open_system_pipe and that + * turns out to affect the parent as well. So just use fork. + */ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* + * Make sys_errlist visible + */ +/* extern int sys_nerr; */ + +/* the following is so there won't be collisions is OSX */ +#define normal pico_normal + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-osx.ic b/osdep/os-osx.ic new file mode 100644 index 0000000..57d90c7 --- /dev/null +++ b/osdep/os-osx.ic @@ -0,0 +1,15 @@ +; +; Mac OS X os-osx.ic file for building os-osx.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.brk) + +include(term.cap) diff --git a/osdep/os-pt1.h b/osdep/os-pt1.h new file mode 100644 index 0000000..6a5564a --- /dev/null +++ b/osdep/os-pt1.h @@ -0,0 +1,188 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, Sequent Dynix/PTX 1.4 version. See also the os-pt1.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +#define u_int pid_t + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include + +#define USE_DIRENT +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +#define SYSV_SIGNALS /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + +/* DYNIX/ptx signal semantics are AT&T/POSIX; the sigset() call sets + the handler permanently, more like BSD signal(). */ +#define signal(s,f) sigset (s, f) + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +#define HAVE_TERMIO /* this is for pure System V */ +#include /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +#define USE_POLL /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +#define USE_TERMINFO /* use terminfo instead of termcap */ +/* #define USE_TERMCAP */ /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + + +/* memcpy() is no good for overlapping blocks. If that's a problem, use + * the memmove() in ../c-client + */ +#define bcopy(a,b,s) memcpy (b, a, s) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-pt1.ic b/osdep/os-pt1.ic new file mode 100644 index 0000000..405c7f3 --- /dev/null +++ b/osdep/os-pt1.ic @@ -0,0 +1,15 @@ +; +; Sequent Dynix/PTX 1.4 os-pt1.ic file for building os-pt1.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.pol) + +include(raw.io) + +include(term.inf) diff --git a/osdep/os-ptx.h b/osdep/os-ptx.h new file mode 100644 index 0000000..382011d --- /dev/null +++ b/osdep/os-ptx.h @@ -0,0 +1,185 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, Sequent Dynix/PTX version. See also the os-ptx.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +#define u_int pid_t + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include + +#define USE_DIRENT +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +#define HAVE_TERMIO /* this is for pure System V */ +#include /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +#define USE_POLL /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +#define USE_TERMINFO /* use terminfo instead of termcap */ +/* #define USE_TERMCAP */ /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + + +/* memcpy() is no good for overlapping blocks. If that's a problem, use + * the memmove() in ../c-client + */ +#define bcopy(a,b,s) memcpy (b, a, s) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-ptx.ic b/osdep/os-ptx.ic new file mode 100644 index 0000000..e33813e --- /dev/null +++ b/osdep/os-ptx.ic @@ -0,0 +1,15 @@ +; +; Sequent Dynix/PTX os-ptx.ic file for building os-ptx.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.pol) + +include(raw.io) + +include(term.inf) diff --git a/osdep/os-s40.h b/osdep/os-s40.h new file mode 100644 index 0000000..d086745 --- /dev/null +++ b/osdep/os-s40.h @@ -0,0 +1,183 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, SunOS 4.0 version. See also the os-s40.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +typedef long fpos_t; +void *malloc(); +void free(); +void *realloc(); + +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +/* #include */ +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +/* #define QSType void */ +#define QSType char /* qsort arg is of type char * */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +#define NON_BLOCKING_IO FNDELAY /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +#include /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* + * Make sys_errlist visible + */ +extern char *sys_errlist[]; +extern int sys_nerr; + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-s40.ic b/osdep/os-s40.ic new file mode 100644 index 0000000..edde85e --- /dev/null +++ b/osdep/os-s40.ic @@ -0,0 +1,15 @@ +; +; SunOS 4.0 os-s40.ic file for building os-s40.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.brk) + +include(term.cap) diff --git a/osdep/os-sc5.h b/osdep/os-sc5.h new file mode 100644 index 0000000..c1c382c --- /dev/null +++ b/osdep/os-sc5.h @@ -0,0 +1,187 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, SCO Open Server 5.x version. See also the os-sc5.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include +#include + +#define USE_DIRENT +#include +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* signal handling is broken in the delivered SCO shells, so punt on + suspending the current session */ +#if defined(SIGTSTP) +#undef SIGTSTP +#endif + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +#define USE_TERMINFO /* use terminfo instead of termcap */ +/* #define USE_TERMCAP */ /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (25) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + + +/* memcpy() is no good for overlapping blocks. If that's a problem, use + * the memmove() in ../c-client + */ +#define bcopy(a,b,s) memcpy (b, a, s) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-sc5.ic b/osdep/os-sc5.ic new file mode 100644 index 0000000..6a54e23 --- /dev/null +++ b/osdep/os-sc5.ic @@ -0,0 +1,15 @@ +; +; SCO os-sc5.ic file for building os-sc5.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.inf) diff --git a/osdep/os-sco.h b/osdep/os-sco.h new file mode 100644 index 0000000..a8ff389 --- /dev/null +++ b/osdep/os-sco.h @@ -0,0 +1,195 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, SCO version. See also the os-sco.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include +#include + +#define USE_DIRENT +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* signal handling is broken in the delivered SCO shells, so punt on + suspending the current session */ +#if defined(SIGTSTP) +#undef SIGTSTP +#endif + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +#define SYSV_SIGNALS /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +#define HAVE_TERMIO /* this is for pure System V */ +#include /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +#define USE_TERMINFO /* use terminfo instead of termcap */ +/* #define USE_TERMCAP */ /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +/* NOTE: Current reports are that ioctl(TIOCGWINSZ) either fails or */ +/* reports constant values, so there is no utility in having */ +/* RESIZING enabled for SCO Unix. */ +/* #if defined(TIOCGWINSZ) && defined(SIGWINCH) */ +/* #define RESIZING */ +/* #endif */ + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + + +/* memcpy() is no good for overlapping blocks. If that's a problem, use + * the memmove() in ../c-client + */ +#define bcopy(a,b,s) memcpy (b, a, s) + +/* + * ftruncate is missing on SCO UNIX (availabe from OpenServer 5 on) + */ +#define ftruncate chsize + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-sco.ic b/osdep/os-sco.ic new file mode 100644 index 0000000..f61d909 --- /dev/null +++ b/osdep/os-sco.ic @@ -0,0 +1,19 @@ +; +; SCO os-sco.ic file for building os-sco.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.io) + +include(term.inf) + +include(truncate) + +include(fsync.non) diff --git a/osdep/os-sgi.h b/osdep/os-sgi.h new file mode 100644 index 0000000..e4d6e39 --- /dev/null +++ b/osdep/os-sgi.h @@ -0,0 +1,183 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, SGI version. See also the os-sgi.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +#define ANSI /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + +#include +#include +#include +#include + +#define USE_DIRENT +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +#define SYSV_SIGNALS /* use System-V signal semantics (ttyin.c) */ + +#define SIGNALHASARG 1 +#define SIG_PROTO(args) args + +/* + * Special for sgi, these aren't declared if -ansi flag used. + * We don't understand why that is. + */ +extern SigType (*sigset(int, SigType(*)SIG_PROTO((int))))(int); +extern FILE *popen(const char *, const char *); +extern FILE *fdopen(int, const char *); + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +#define USE_TERMINFO /* use terminfo instead of termcap */ +/* #define USE_TERMCAP */ /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-sgi.ic b/osdep/os-sgi.ic new file mode 100644 index 0000000..1197735 --- /dev/null +++ b/osdep/os-sgi.ic @@ -0,0 +1,15 @@ +; +; SGI os-sgi.ic file for building os-sgi.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.ios) + +include(term.inf) diff --git a/osdep/os-sol.h b/osdep/os-sol.h new file mode 100644 index 0000000..c4311de --- /dev/null +++ b/osdep/os-sol.h @@ -0,0 +1,178 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, Sun Solaris version. See also the os-sol.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +FILE *tmpfile(); +#include + +#define USE_DIRENT +#include +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strcoll + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +#define USE_POLL /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +#define USE_TERMINFO /* use terminfo instead of termcap */ +/* #define USE_TERMCAP */ /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +#define bcopy(a,b,s) memcpy (b, a, s) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-sun.h b/osdep/os-sun.h new file mode 100644 index 0000000..361dca6 --- /dev/null +++ b/osdep/os-sun.h @@ -0,0 +1,181 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, SunOS 4.1 version. See also the os-sun.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +char *getenv(); +typedef long fpos_t; + +#include +#include +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ /* qsort arg is of type char * */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +/*#define NON_BLOCKING_IO O_NONBLOCK */ /* POSIX style */ +#define NON_BLOCKING_IO FNDELAY /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +#include /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +#define HAVE_WAIT_UNION /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +/* + * Make sys_errlist visible + */ +extern char *sys_errlist[]; +extern int sys_nerr; + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-sun.ic b/osdep/os-sun.ic new file mode 100644 index 0000000..636a1a0 --- /dev/null +++ b/osdep/os-sun.ic @@ -0,0 +1,15 @@ +; +; SunOS 4.1 os-sun.ic file for building os-sun.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.brk) + +include(term.cap) diff --git a/osdep/os-sv4.h b/osdep/os-sv4.h new file mode 100644 index 0000000..f1bd7b5 --- /dev/null +++ b/osdep/os-sv4.h @@ -0,0 +1,183 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, System V R4 version. See also the os-sv4.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +FILE *tmpfile(); + +#include +#include +#include +#include + +#define USE_DIRENT +#include + + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +/* #include */ /* To make matching and sorting work right */ +#define collator strucmp + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +#include /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +/* #define POSIX_SIGNALS */ /* use POSIX signal semantics (ttyin.c) */ +#define SYSV_SIGNALS /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + +/* The sigset() call sets the handler permanently, more like BSD signal(). */ +#define signal(s,f) sigset (s, f) + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +/* #define QSType void */ +#define QSType char /* qsort arg is of type char * */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +/* #include */ /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +#define HAVE_TERMIOS /* this is an alternative */ +#include /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +#define USE_POLL /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +#define USE_TERMINFO /* use terminfo instead of termcap */ +/* #define USE_TERMCAP */ /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +/* #define HAVE_WAIT_UNION */ /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +#define vfork fork /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + + +#define bcopy(a,b,s) memcpy (b, a, s) + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-sv4.ic b/osdep/os-sv4.ic new file mode 100644 index 0000000..0ea4e13 --- /dev/null +++ b/osdep/os-sv4.ic @@ -0,0 +1,15 @@ +; +; Sun Solaris os-sol.ic file for building os-sol.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.pol) + +include(raw.ios) + +include(term.inf) diff --git a/osdep/os-ult.h b/osdep/os-ult.h new file mode 100644 index 0000000..ed674f2 --- /dev/null +++ b/osdep/os-ult.h @@ -0,0 +1,173 @@ +#ifndef _PICO_OS_INCLUDED +#define _PICO_OS_INCLUDED + + +/*---------------------------------------------------------------------- + + OS dependencies, Ultrix 4.2 version. See also the os-ult.c file. + The following stuff may need to be changed for a new port, but once + the port is done, it won't change. At the bottom of the file are a few + constants that you may want to configure differently than they + are configured, but probably not. + + ----*/ + + + +/*----------------- Are we ANSI? ---------------------------------------*/ +/* #define ANSI */ /* this is an ANSI compiler */ + +/*------ If our compiler doesn't understand type void ------------------*/ +/* #define void char */ /* no void in compiler */ + + +#include +#include +#include + +/*------- Some more includes that should usually be correct ------------*/ +#include +#include +#include +#include +#include + + + +/*----------------- locale.h -------------------------------------------*/ +#include /* To make matching and sorting work right */ +#define collator strcoll + + + +/*----------------- time.h ---------------------------------------------*/ +#include +/* plain time.h isn't enough on some systems */ +/* #include */ /* For struct timeval usually in time.h */ + + + +/*--------------- signal.h ---------------------------------------------*/ +#include /* sometimes both required, sometimes */ +/* #include */ /* only one or the other */ + +#define SigType void /* value returned by sig handlers is void */ +/* #define SigType int */ /* value returned by sig handlers is int */ + +#define POSIX_SIGNALS /* use POSIX signal semantics (ttyin.c) */ +/* #define SYSV_SIGNALS */ /* use System-V signal semantics (ttyin.c) */ + +#define SIG_PROTO(args) () + + + +/*-------------- A couple typedef's for integer sizes ------------------*/ +typedef unsigned int usign32_t; +typedef unsigned short usign16_t; + + + +/*-------------- qsort argument type -----------------------------------*/ +#define QSType void /* qsort arg is of type void * */ +/* #define QSType char */ + + + +/*-------------- fcntl flag to set non-blocking IO ---------------------*/ +#define NON_BLOCKING_IO O_NONBLOCK /* POSIX style */ +/*#define NON_BLOCKING_IO FNDELAY */ /* good ol' bsd style */ + + + +/* + * Choose one of the following three terminal drivers + */ + +/*--------- Good 'ol BSD -----------------------------------------------*/ +#include /* BSD-based systems */ + +/*--------- System V terminal driver -----------------------------------*/ +/* #define HAVE_TERMIO */ /* this is for pure System V */ +/* #include */ /* Sys V */ + +/*--------- POSIX terminal driver --------------------------------------*/ +/* #define HAVE_TERMIOS */ /* this is an alternative */ +/* #include */ /* POSIX */ + + + +/* Don't need to define this but do need to use either read.sel or read.pol + * in osdep. */ +/*-------- Use poll system call instead of select ----------------------*/ +/* #define USE_POLL */ /* use the poll() system call instead of select() */ + + + +/*-------- Use terminfo database instead of termcap --------------------*/ +/* #define USE_TERMINFO */ /* use terminfo instead of termcap */ +#define USE_TERMCAP /* use termcap */ + + + +/*-- What argument does wait(2) take? Define this if it is a union -----*/ +#define HAVE_WAIT_UNION /* the arg to wait is a union wait * */ + + + +/*-------- Is window resizing available? -------------------------------*/ +#if defined(TIOCGWINSZ) && defined(SIGWINCH) +#define RESIZING /* SIGWINCH and friends */ +#endif + + + +/*-------- If no vfork, use regular fork -------------------------------*/ +/* #define vfork fork */ /* vfork is just a lightweight fork, so can use fork */ + + + +/*---- When no screen size can be discovered this is the size used -----*/ +#define DEFAULT_LINES_ON_TERMINAL (24) +#define DEFAULT_COLUMNS_ON_TERMINAL (80) +#define NROW DEFAULT_LINES_ON_TERMINAL +#define NCOL DEFAULT_COLUMNS_ON_TERMINAL + + +/*---------------------------------------------------------------------- + + Pico OS dependencies. + + ----*/ + + +/* + * File name separator, as a char and string + */ +#define C_FILESEP '/' +#define S_FILESEP "/" + +/* + * Place where mail gets delivered (for pico's new mail checking) + */ +#define MAILDIR "/usr/spool/mail" + +/* + * What and where the tool that checks spelling is located. If this is + * undefined, then the spelling checker is not compiled into pico. + */ +#define SPELLER "/usr/bin/spell" + +#ifdef MOUSE +#define XTERM_MOUSE_ON "\033[?1000h" /* DECSET with parm 1000 */ +#define XTERM_MOUSE_OFF "\033[?1000l" /* DECRST with parm 1000 */ +#endif + +/* + * Mode passed chmod() to make tmp files exclusively user read/write-able + */ +#define MODE_READONLY (0600) + +extern char *getpass(); + + +#endif /* _PICO_OS_INCLUDED */ diff --git a/osdep/os-ult.ic b/osdep/os-ult.ic new file mode 100644 index 0000000..76814b5 --- /dev/null +++ b/osdep/os-ult.ic @@ -0,0 +1,15 @@ +; +; Ultrix 4.2 os-ult.ic file for building os-ult.c. +; +; Boilerplate header. +include(header) + +include(unix) + +include(spell.unx) + +include(read.sel) + +include(raw.brk) + +include(term.cap) diff --git a/osdep/os2 b/osdep/os2 new file mode 100644 index 0000000..1fbff6f --- /dev/null +++ b/osdep/os2 @@ -0,0 +1,1712 @@ +/* + * $Id: os2 13636 2004-05-05 22:01:21Z hubert $ + * + * Program: Operating system dependent routines - OS/2 Text mode + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2001 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + * + * Notes: + * - mouse support added (mss, 921215) + * + * Portions of this code derived from MicroEMACS 3.10: + * + * OS2.C: Operating specific I/O and Spawning functions + * under the OS/2 operating system + * for MicroEMACS 3.10 + * (C)opyright 1988 by Daniel M. Lawrence + * + */ + + +#include + + +/* + * Internal functions... + */ +int checkmouse PROTO((unsigned *, int, int, int)); +void invert_label PROTO((int, MENUITEM *)); +int enhanced_keybrd PROTO((void)); +int dont_interrupt PROTO((void)); +int interrupt_ok PROTO((void)); +int kbseq PROTO((int *)); +int specialkey PROTO((unsigned int)); +void do_alarm_signal PROTO((void)); +void do_hup_signal PROTO((int sig)); +char *pfnexpand PROTO((char *, size_t)); +int ssleep PROTO((long)); +void mouseon PROTO((void)); +void mouseoff PROTO((void)); +void turnmouseoff PROTO((void)); + +/* + * Useful global def's + */ + +int timeo = 0; +time_t time_of_last_input; +int (*pcollator)(); +static int oldbut; /* Previous state of mouse buttons */ +static int enhncd; /* Enhanced keyboard */ +static KBDINFO initialKbdInfo; + +#ifdef MOUSE +/* + * Useful definitions... + */ +static int mexist = 0; /* is the mouse driver installed? */ +static int nbuttons; /* number of buttons on the mouse */ +static unsigned mnoop; +static unsigned char okinfname[32] = { + 0, 0, /* ^@ - ^G, ^H - ^O */ + 0, 0, /* ^P - ^W, ^X - ^_ */ + 0, 0x17, /* SP - ' , ( - / */ + 0xff, 0xe4, /* 0 - 7 , 8 - ? */ + 0x7f, 0xff, /* @ - G , H - O */ + 0xff, 0xe9, /* P - W , X - _ */ + 0x7f, 0xff, /* ` - g , h - o */ + 0xff, 0xf6, /* p - w , x - DEL */ + 0, 0, /* > DEL */ + 0, 0, /* > DEL */ + 0, 0, /* > DEL */ + 0, 0, /* > DEL */ + 0, 0 /* > DEL */ +}; +#endif + + +static void set_kbd(int state) +{ + KBDINFO kbdInfo = initialKbdInfo; + if (state) + { + kbdInfo.fsMask &= ~(0x0001|0x0008|0x0100); /* echo,cooked */ + kbdInfo.fsMask |= (0x0002|0x0004|0x0100); /* noecho,raw,shift-rpt on */ + } + KbdSetStatus(&kbdInfo, 0); +} + +/* + * DISable ctrl-break interruption + */ +dont_interrupt() +{ + signal (SIGINT, SIG_IGN); + signal (SIGBREAK, SIG_IGN); + set_kbd(1); +} + +/* + * re-enable ctrl-break interruption + */ +interrupt_ok() +{ + set_kbd(0); + signal (SIGINT, SIG_DFL); + signal (SIGBREAK, SIG_DFL); +} + + +/* + * return true if an enhanced keyboard is present + */ +enhanced_keybrd() +{ + return(1); +} + + +/* + * This function is called once to set up the terminal device streams. + */ +ttopen() +{ + initialKbdInfo.cb = sizeof(initialKbdInfo); + KbdGetStatus(&initialKbdInfo, 0); + dont_interrupt(); /* don't allow interrupt */ + enhncd = enhanced_keybrd(); /* check for extra keys */ +#if MOUSE + init_mouse(); +#else /* !MOUSE */ + mexist = 0; +#endif /* MOUSE */ + return(1); +} + +#ifdef MOUSE +HMOU Mouse_Handle =(HMOU)-1; +#ifdef FASTVIO +int mouse_state =0; +#endif + +/* + * init_mouse - check for and initialize mouse driver... + */ +init_mouse() +{ + if (Mouse_Handle==(HMOU)-1) { + int rc = MouOpen(NULL, &Mouse_Handle); + mexist=0; + if (rc) + return(FALSE); + mexist=1; + nbuttons=2; + MouFlushQue(Mouse_Handle); + turnmouseoff(); + } + return(TRUE); +} + +static int mouchk() +{ + if (mexist) + return (Mouse_Handle==(HMOU)-1) ? init_mouse() : TRUE; + return FALSE; +} + +deinit_mouse() +{ + turnmouseoff(); +} + + +/* + * mouseon - call made available for programs calling pico to turn ON the + * mouse cursor. + */ +void +mouseon() +{ + /* Show Cursor */ + if (mouchk() && !mouse_state) { +#ifdef FASTVIO + mouse_state=TRUE; + vidUpdate(); +#else + MouDrawPtr(Mouse_Handle); +#endif + } +} + +void +turnmouseoff() +{ + static NOPTRRECT r = { 0, 0, (USHORT)-1, (USHORT)-1 }; + if (r.cRow == (USHORT)-1) { + VIOMODEINFO mi; + mi.cb = sizeof mi; + VioGetMode(&mi, 0); + r.cRow = mi.row-1; + r.cCol = mi.col-1; + } + /* Hide Cursor */ + MouRemovePtr(&r, Mouse_Handle); + mouse_state=FALSE; +} + +/* + * mouseon - call made available for programs calling pico to turn OFF the + * mouse cursor. + */ +void +mouseoff() +{ +#ifdef FASTVIO + /* This is ignored if in FASTVIO mode */ +#else + if (mouchk()) { + turnmouseoff(); + } +#endif +} +#endif + + +/* + * This function gets called just before we go back home to the command + * interpreter. + */ +ttclose() +{ + if(!Pmaster) + interrupt_ok(); +#ifdef MOUSE + deinit_mouse(); +#endif + return(1); +} + + +/* + * Flush terminal buffer. Does real work where the terminal output is buffered + * up. A no-operation on systems where byte at a time terminal I/O is done. + */ +ttflush() +{ + return(1); +} + + +/* + * specialkey - return special key definition + */ +specialkey(kc) +unsigned kc; +{ + switch(kc){ + case 0x3b00 : return(F1); + case 0x3c00 : return(F2); + case 0x3d00 : return(F3); + case 0x3e00 : return(F4); + case 0x3f00 : return(F5); + case 0x4000 : return(F6); + case 0x4100 : return(F7); + case 0x4200 : return(F8); + case 0x4300 : return(F9); + case 0x4400 : return(F10); + case 0x8500 : return(F11); + case 0x8600 : return(F12); + case 0x4800 : return(KEY_UP); + case 0x5000 : return(KEY_DOWN); + case 0x4b00 : return(KEY_LEFT); + case 0x4d00 : return(KEY_RIGHT); + case 0x4700 : return(KEY_HOME); + case 0x4f00 : return(KEY_END); + case 0x4900 : return(KEY_PGUP); + case 0x5100 : return(KEY_PGDN); + case 0x5300 : return(KEY_DEL); + case 0x48e0 : return(KEY_UP); /* grey key version */ + case 0x50e0 : return(KEY_DOWN); /* grey key version */ + case 0x4be0 : return(KEY_LEFT); /* grey key version */ + case 0x4de0 : return(KEY_RIGHT); /* grey key version */ + case 0x47e0 : return(KEY_HOME); /* grey key version */ + case 0x4fe0 : return(KEY_END); /* grey key version */ + case 0x49e0 : return(KEY_PGUP); /* grey key version */ + case 0x51e0 : return(KEY_PGDN); /* grey key version */ + case 0x53e0 : return(KEY_DEL); /* grey key version */ + default : return(NODATA); + } +} + + +/* + * Read a character from the terminal, performing no editing and doing no echo + * at all. Also mouse events are forced into the input stream here. + */ +ttgetc(return_on_intr, recorder, bail_handler) + int return_on_intr; + int (*recorder)(); + int (*bail_handler)(); +{ + int key = kbd_getkey(); + return key ? key : NODATA; +} + + +/* + * ctrlkey - used to check if the key hit was a control key. + */ +ctrlkey() +{ + return !!(kbd_shift() & KBDSTF_CONTROL); +} + + +/* + * win_multiplex - give OS/2 a shot at the CPU + */ +win_multiplex() +{ + DosSleep(32); +} + + +/* + * Read in a key. + * Do the standard keyboard preprocessing. Convert the keys to the internal + * character set. Resolves escape sequences and returns no-op if global + * timeout value exceeded. + */ +GetKey() +{ + unsigned ch = 0, lch, intrupt = 0; + long timein; + + vidUpdate(); + if(mexist || timeo) { + timein = time(0L); +#ifdef MOUSE + mouseon(); /* Show Cursor */ +#endif + while(!kbd_ready()) { +#if MOUSE + if(timeo && time(0L) >= timein+timeo){ + mouseoff(); /* Hide Cursor */ + return(NODATA); + } + + if(checkmouse(&ch,0,0,0)){ /* something happen ?? */ + mouseoff(); /* Hide Cursor */ + curwp->w_flag |= WFHARD; + return(ch); + } +#else + if(time(0L) >= timein+timeo) { + mouseoff(); /* Hide Cursor */ + return(NODATA); + } +#endif /* MOUSE */ + + /* + * Surrender the CPU... + */ + win_multiplex(); + } +#ifdef MOUSE + mouseoff(); /* Hide Cursor */ +#endif /* MOUSE */ + } + + ch = (*term.t_getchar)(0, NULL, NULL); + lch = (ch&0xff); + + if(lch & 0x80 && Pmaster && Pmaster->hibit_entered) + *Pmaster->hibit_entered = 1; + + return((lch && (lch != 0xe0 || !(ch & 0xff00))) + ? (lch < ' ') ? (CTRL|(lch + '@')) + : (lch == ' ' && ctrlkey()) ? (CTRL|'@') : lch + : specialkey(ch)); +} + + +#if MOUSE +/* + * checkmouse - look for mouse events in key menu and return + * appropriate value. + */ +int +checkmouse(ch, down, xxx, yyy) +unsigned *ch; +int down, xxx, yyy; +{ + MOUQUEINFO qi; + + if(!mouchk()) + return(FALSE); + + if (MouGetNumQueEl(&qi, Mouse_Handle)==0 && qi.cEvents) + { + MOUEVENTINFO m; + USHORT w = MOU_NOWAIT; + + /* check to see if any mouse buttons are different */ + if (MouReadEventQue(&m, &w, Mouse_Handle)==0) + { + int k; + int rv = 0; + int button = M_BUTTON_LEFT; + int newbut = ((m.fs & 4)?1:0) | ((m.fs & 16)?2:0) | ((m.fs & 64)?4:0); + + /* only notice button changes */ + if (oldbut == newbut) + return(FALSE); + + for (k=1; k != (1 << nbuttons); k <<= 1) { + /* For each button on the mouse */ + if ((oldbut&k) != (newbut&k)) { + if(k == 1){ + static int oindex; + int i = 0; + MENUITEM *mp; + + if(newbut&k) /* button down */ + oindex = -1; + + for(mp = mfunc; mp; mp = mp->next) + if(mp->action && M_ACTIVE(m.row, m.col, mp)) + break; + + if(mp){ + unsigned long r; + + r = (*mp->action)((newbut&k) ? M_EVENT_DOWN : M_EVENT_UP, + m.row, m.col, button, 0); + if(r & 0xffff){ + *ch = (unsigned)((r>>16)&0xffff); + rv = TRUE; + } + } + else{ + while(1){ /* see if we understand event */ + if(i >= 12){ + i = -1; + break; + } + + if(M_ACTIVE(m.row, m.col, &menuitems[i])) + break; + + i++; + } + + if(newbut&k){ /* button down */ + oindex = i; /* remember where */ + if(i != -1) { /* invert label */ + invert_label(1, &menuitems[i]); + } + } + else{ /* button up */ + if(oindex != -1){ + if(i == oindex){ + *ch = menuitems[i].val; + rv = 1; + } + } + } + } + + if(!(newbut&k) && oindex != -1) { + invert_label(0, &menuitems[oindex]); /* restore label */ + } + } + + oldbut = newbut; + return(rv); + } + ++button; + } + } + } + return(FALSE); +} + + +/* + * invert_label - highlight the label of the given menu item. + */ +void +invert_label(state, m) +int state; +MENUITEM *m; +{ + USHORT r, c; + VIOCURSORINFO oldInfo, newInfo; + int i, j, p; + char *lp; + int old_state = getrevstate(); + + if(m->val == mnoop) + return; + + VioGetCurPos(&r, &c, 0); + VioGetCurType(&oldInfo, 0); + newInfo = oldInfo; + newInfo.attr = (USHORT)-1; + VioSetCurType(&newInfo, 0); /* Hide Cursor */ + (*term.t_move)(m->tl.r, m->tl.c); + (*term.t_rev)(state); + for(i = m->tl.r; i <= m->br.r; i++) + for(j = m->tl.c; j <= m->br.c; j++) + if(i == m->lbl.r && j == m->lbl.c){ /* show label?? */ + lp = m->label; + while(*lp && j++ < m->br.c) + (*term.t_putchar)(*lp++); + continue; + } + else (*term.t_putchar)(' '); + + (*term.t_rev)(old_state); + VioSetCurPos(r, c, 0); /* restore old position */ + VioSetCurType(&oldInfo, 0); /* Show Cursor */ + vidUpdate(); +} +#endif /* MOUSE */ + + +/* + * alt_editor - fork off an alternate editor for mail message composition + */ +#define MAXARGS 10 +alt_editor(f, n) + int f, n; +{ + char *fn; /* tmp holder for file name */ + char *cp; + int child, rc, i, done = 0; + long l; + int stat; + FILE *p; + + char *args[MAXARGS]; /* ptrs into edit command */ + char eb[NLINE]; + + if(Pmaster == NULL) + return(-1); + + if(gmode&MDSCUR){ + emlwrite("Alternate editor not available in restricted mode", NULL); + return(-1); + } + + if(Pmaster->alt_ed == NULL){ + if (!(gmode&MDADVN)) { + emlwrite("\007Unknown Command",NULL); + return(-1); + } + + if((cp=getenv("VISUAL"))!=0 || (cp=getenv("EDITOR"))!=0) + strcpy(eb, (char *)getenv("EDITOR")); + else *eb = '\0'; + + while(!done) { + rc = mlreplyd("Which alternate editor ? ",eb,NLINE,QDEFLT,NULL); + + switch(rc) { + case ABORT: + return(-1); + case HELPCH: + emlwrite("no alternate editor help yet", NULL); + + /* take sleep and break out after there's help */ + sleep(3); + break; + case (CTRL|'L'): + sgarbf = TRUE; + update(); + break; + case TRUE: + case FALSE: /* does editor exist ? */ + if(*eb == '\0'){ /* leave silently? */ + mlerase(); + curwp->w_flag |= WFMODE; + return(-1); + } + + done++; + break; + default: + break; + } + } + } + else + strcpy(eb, Pmaster->alt_ed); + + if((fn=writetmp(1, NULL)) == NULL){ /* get temp file */ + emlwrite("Problem writing temp file for alt editor", NULL); + return(-1); + } + + strcat(eb, " "); + strcat(eb, fn); + + cp = eb; + for(i=0; *cp != '\0';i++) { /* build args array */ + if(i < MAXARGS) { + args[i] = NULL; /* in case we break out */ + } + else{ + emlwrite("Too many args for command!", NULL); + return(-1); + } + + while(isspace((unsigned char)(*cp))) + if(*cp != '\0') + cp++; + else break; + + args[i] = cp; + while(!isspace((unsigned char)(*cp))) + if(*cp != '\0') + cp++; + else + break; + + if(*cp != '\0') + *cp++ = '\0'; + } + + args[i] = NULL; + + (*Pmaster->tty_fix)(0); + + emlwrite("Invoking alternate editor...", NULL); + + { + void (*ohup)() = signal(SIGHUP, SIG_IGN); /* ignore signals for now */ + void (*oint)() = signal(SIGINT, SIG_IGN); + cp=args[0]; + rc = spawnvp(P_WAIT, cp, args); + signal(SIGHUP, ohup); /* restore signals */ + signal(SIGINT, oint); + } + + (*Pmaster->tty_fix)(1); + + /* + * Editor may have set a hibit, we don't know. Assume it did. + */ + if(!f && Pmaster && Pmaster->hibit_entered) + *Pmaster->hibit_entered = 1; + + dont_interrupt(); + + if (rc==-1) { /* Can't run it */ + emlwrite("error attempting to run alt editor", NULL); + } + /* + * replace edited text with new text + */ + else{ + rc = 0; + curbp->b_flag &= ~BFCHG; /* make sure old text gets blasted */ + readin(fn, 0, 0); /* read new text overwriting old */ + curbp->b_flag |= BFCHG; /* mark dirty for packbuf() */ + } + unlink(fn); /* blast temp file */ + + ttopen(); /* reset the signals */ + pico_refresh(0, 1); /* redraw */ + return(rc); +} + + +/* + * bktoshell - suspend and wait to be woken up + */ +int +bktoshell() /* suspend MicroEMACS and wait to wake up */ +{ + int i; + static char * shell = NULL; + + if (shell == NULL) { + char *p; + shell=getenv("SHELL"); + if (!shell && !(shell=getenv("COMSPEC"))) + shell="CMD.EXE"; + if ((p = strdup(shell)) > 0) { + for (shell = p; (p = strchr(shell, '/')) != 0; ) + *p = '\\'; + } + } + + (*term.t_move)(term.t_nrow, 0); + (*term.t_eeol)(); + exit_text_mode(NULL); + interrupt_ok(); + if (system(shell) == -1) + emlwrite("Error loading %s", shell); + else pico_refresh(0, 1); /* redraw */ + enter_text_mode(NULL); + dont_interrupt(); + return(1); +} + + +/* + * P_open - run the given command in a sub-shell returning a file pointer + * from which to read the output + * + * note: + * For OS's other than unix, you will have to rewrite this function. + * Hopefully it'll be easy to exec the command into a temporary file, + * and return a file pointer to that opened file or something. + */ +FILE *P_open(c) +char *c; +{ + return(popen(c,"r")); +} + + + +/* + * P_close - close the given descriptor + * + */ +void +P_close(fp) +FILE *fp; +{ + (void)pclose(fp); +} + +/* + * A replacement for fflush + * relies on #define fflush os2_fflush + */ +#undef fflush +int +os2_fflush (FILE *f) +{ + if (f == stdout) { + vidUpdate(); + } + else + fflush (f); +} + +/* + * ttresize - recompute the screen dimensions if necessary, and then + * adjust pico's internal buffers accordingly + */ +void +ttresize () +{ + return; +} + +/* + * picosigs - Install any handlers for the signals we're interested + * in catching. + */ +void +picosigs() +{ + signal(SIGHUP, do_hup_signal); /* deal with SIGHUP */ + signal(SIGTERM, do_hup_signal); /* deal with SIGTERM */ +} + +/* + * do_hup_signal - jump back in the stack to where we can handle this + */ +void +do_hup_signal(int sig) +{ + sig=sig; + signal(SIGHUP, SIG_IGN); /* ignore further SIGHUP's */ + signal(SIGTERM, SIG_IGN); /* ignore further SIGTERM's */ + if(Pmaster){ + extern jmp_buf finstate; + + longjmp(finstate, COMP_GOTHUP); + } + else{ + /* + * if we've been interrupted and the buffer is changed, + * save it... + */ + if(anycb() == TRUE){ /* time to save */ + if(curbp->b_fname[0] == '\0'){ /* name it */ + strcpy(curbp->b_fname, "pico.sav"); + } + else{ + strcat(curbp->b_fname, ".sav"); + } + writeout(curbp->b_fname, TRUE); + } + vttidy(); + exit(1); + } +} + + + +#ifdef MOUSE + +/* + * end_mouse - a no-op on DOS/Windows + */ +void +end_mouse() +{ +} + + +/* + * mouseexist - function to let outsiders know if mouse is turned on + * or not. + */ +mouseexist() +{ + return(mexist); +} +#endif /* MOUSE */ + + +/* + * fallowc - returns TRUE if c is allowable in filenames, FALSE otw + */ +fallowc(c) +int c; +{ + return(okinfname[c>>3] & 0x80>>(c&7)); +} + + +/* + * fexist - returns TRUE if the file exists, FALSE otherwise + */ +fexist(file, m, l) +char *file, *m; +off_t *l; +{ + struct stat sbuf; + + if(l != NULL) + *l = (off_t)0; + + if(stat(file, &sbuf) < 0){ + if(ENOENT) /* File not found */ + return(FIOFNF); + else + return(FIOERR); + } + + if(l != NULL) + *l = (off_t)sbuf.st_size; + + if(sbuf.st_mode & S_IFDIR) + return(FIODIR); + + if(m[0] == 'r') /* read access? */ + return((S_IREAD & sbuf.st_mode) ? FIOSUC : FIONRD); + else if(m[0] == 'w') /* write access? */ + return((S_IWRITE & sbuf.st_mode) ? FIOSUC : FIONWT); + else if(m[0] == 'x') /* execute access? */ + return((S_IEXEC & sbuf.st_mode) ? FIOSUC : FIONEX); + return(FIOERR); /* what? */ +} + + +/* + * isdir - returns true if fn is a readable directory, false otherwise + * silent on errors (we'll let someone else notice the problem;)). + */ +isdir(fn, l, d) +char *fn; +long *l; +time_t *d; +{ + struct stat sbuf; + + if(l) + *l = 0; + + if(stat(fn, &sbuf) < 0) + return(0); + + if(l) + *l = sbuf.st_size; + + if(d) + *d = sbuf.st_mtime; + + return(sbuf.st_mode & S_IFDIR); +} + + +/* + * gethomedir - returns the users home directory + * Note: home is malloc'd for life of pico + */ +char *gethomedir(l) +int *l; +{ + static char *home = NULL; + static short hlen = 0; + + if(home == NULL){ + char *p, buf[NLINE]; + + if (home=getenv("PINEHOME")) /* Overrides all others */ + strcpy(buf, home); + else if (home=getenv("HOME")) /* Convenient group placement */ + strcpy(buf, home); + else if (home=getenv("ETC")) /* IBM TCPIP */ + strcpy(buf, home); + else sprintf(buf, "%c:\\", _getdrive()); + hlen = strlen(buf); + if ((home=(char *)malloc(hlen + 1)) == NULL) { + emlwrite("Problem allocating space for home dir", NULL); + return(0); + } + strcpy(home, buf); + while ((p=strchr(home,'/')) != NULL) /* Normalise, just in case */ + *p = '\\'; + } + + if(l) + *l = hlen; + + return(home); +} + + +/* + * homeless - returns true if given file does not reside in the current + * user's home directory tree. + */ +homeless(f) +char *f; +{ + char *home; + int len; + + home = gethomedir(&len); + return(strncmp(home, f, len)); +} + + + +/* + * errstr - return system error string corresponding to given errno + * Note: strerror() is not provided on all systems, so it's + * done here once and for all. + */ +char *errstr(err) +int err; +{ + return((err >= 0 && err < sys_nerr) ? (char*)sys_errlist[err] : NULL); +} + + +/* + * getfnames - return all file names in the given directory in a single + * malloc'd string. n contains the number of names + */ +char *getfnames(dn, pat, n, e) +char *dn, *pat, *e; +int *n; +{ + int status; + long l; + size_t avail, alloced, incr = 1024; + char *names, *np, *p; + char buf[NLINE]; + struct stat sbuf; + ULONG count=1; + FILEFINDBUF3 findbuf; + HDIR hdir=HDIR_CREATE; + + *n = 0; + + while ((p = strchr(dn, '/')) != NULL) + *p = '\\'; + + if(stat(dn, &sbuf) < 0){ + if(e) + sprintf(e, "\007Dir \"%s\": %s", dn, strerror(errno)); + + return(NULL); + } + else{ +#define MAX(x,y) ((x) > (y) ? (x) : (y)) + avail = alloced = MAX(sbuf.st_size, incr); + if(!(sbuf.st_mode & S_IFDIR)){ + if(e) + sprintf(e, "\007Not a directory: \"%s\"", dn); + + return(NULL); + } + } + + if((names=(char *)malloc(alloced * sizeof(char))) == NULL){ + if(e) + sprintf(e, "\007Can't malloc space for file names"); + + return(NULL); + } + + np = names; + + strcpy(buf, dn); + if (*buf && buf[strlen(buf)-1] != '\\') + strcat(buf, "\\"); + if (pat && *pat) + strcat(buf, pat); + if (!pat || !*pat || strchr(pat, '.')==NULL) + strcat(buf, "*"); + + if (DosFindFirst(buf, &hdir, FILE_NORMAL|FILE_DIRECTORY, &findbuf, + sizeof findbuf, &count, FIL_STANDARD) != 0) { + if(e) + sprintf(e, "Can't find first file in \"%s\"", dn); + + free((char *) names); + return(NULL); + } + + do{ + (*n)++; + p = findbuf.achName; + l = strlen(p); + while(avail < l+1){ + char *oldnames; + + alloced += incr; + avail += incr; + oldnames = names; + if((names = (char *)realloc((void *)names, alloced * sizeof(char))) + == NULL){ + if(e) + sprintf(e, "\007Can't malloc enough space for file names"); + + return(NULL); + } + + np = names + (np-oldnames); + } + + avail -= (l+1); + + while((*np++ = *p++) != '\0') + ; + } + while(DosFindNext(hdir, &findbuf, sizeof findbuf, &count) == 0); + + return(names); +} + + +/* + * fioperr - given the error number and file name, display error + */ +void +fioperr(e, f) +int e; +char *f; +{ + switch(e){ + case FIOFNF: /* File not found */ + emlwrite("\007File \"%s\" not found", f); + break; + case FIOEOF: /* end of file */ + emlwrite("\007End of file \"%s\" reached", f); + break; + case FIOLNG: /* name too long */ + emlwrite("\007File name \"%s\" too long", f); + break; + case FIODIR: /* file is a directory */ + emlwrite("\007File \"%s\" is a directory", f); + break; + case FIONWT: + emlwrite("\007Write permission denied: %s", f); + break; + case FIONRD: + emlwrite("\007Read permission denied: %s", f); + break; + case FIONEX: + emlwrite("\007Execute permission denied: %s", f); + break; + default: + emlwrite("\007File I/O error: %s", f); + } +} + + +/* + * pfnexpand - pico's function to expand the given file name if there is + * a leading '~' + */ +char *pfnexpand(fn, len) + char *fn; + size_t len; +{ + register char *x, *y, *z; + char *home = gethomedir(NULL); + char name[20]; + + if(*fn == '~') { + for(x = fn+1, y = name; + *x != '/' && *x != '\\' && *x != '\0' && y-name < sizeof(name)-1; + *y++ = *x++); + *y = '\0'; + if(strlen(home) + strlen(fn) >= len) { + return(NULL); + } + /* make room for expanded path */ + for(z=x+strlen(x),y=fn+strlen(x)+strlen(home); + z >= x; + *y-- = *z--); + /* and insert the expanded address */ + for(x=fn,y=home; *y != '\0'; *x++ = *y++); + } + + return(fn); +} + +getcurdir(drv, buf) +int drv; +char *buf; +{ + LONG ml = _MAX_PATH; + drv = drv ? toupper(drv) : _getdrive(); + buf[0] = (char)drv; + buf[1] = ':'; + buf[2] = '\\'; + return DosQueryCurrentDir(drv-'A'+1, buf + 3, &ml) == 0; +} + +/* + * fixpath - make the given pathname into an absolute path + */ +void +fixpath(name, len) + char *name; + size_t len; +{ + char *p; + char file[_MAX_PATH]; + int dr; + + if(!len) + return; + + /* normalize: xlate any '/' into '\\' */ + while ((p=strchr(name,'/'))!=NULL) + *p='\\'; + + /* return the full path of given file */ + if(isalpha((unsigned char)name[0]) && name[1] == ':'){ /* have drive spec? */ + if(name[2] == '\\') /* including path? */ + return; + if (!getcurdir(name[0], file)) + return; + name += 2; + } + else if(name[0] == '.' && (!name[1] || name[1] == '\\')) { + getcurdir(0, file); + name += (1 + name[1] == '\\'); + } + else if(name[0] == '\\') { /* no drive spec! */ + file[0] = (char)_getdrive(); + file[1] = ':'; + file[2] = '\0'; + } + else getcurdir(0, file); /* no qualification */ + + if(*name) { /* if name, append it */ + p = NULL; + if (name[0] == '.' && name[1] == '.' && (!name[2] || name[2] == '\\')) { + if ((p = strrchr(name,'\\'))!=NULL) { + *p++ = '\0'; + if (!*p && (p=strrchr(name,'\\'))!=NULL) + *p = '\0'; + } + name += (2 & name[2] == '\\'); + } + if (*name) { + if (name[0] == '.' && (!name[1] || name[1] == '\\')) + name += (1 + name[1] == '\\'); + if (*name) { + if (*file && file[strlen(file)-1] != '\\' && *name != '\\') + strcat(file, "\\"); + strcat(file, name); + } + } + } + + strncpy(name, file, len-1); /* copy back to real buffer */ + name[len-1] = '\0'; /* tie off just in case */ +} + + +/* + * compresspath - given a base path and an additional directory, collapse + * ".." and "." elements and return absolute path (appending + * base if necessary). + * + * returns 1 if OK, + * 0 if there's a problem + * new path, by side effect, if things went OK + */ +compresspath(base, path, len) +char *base, *path; +int len; +{ + register int i; + int depth = 0; + char *p; + char *stack[32]; + char pathbuf[NLINE]; + +#define PUSHD(X) (stack[depth++] = X) +#define POPD() ((depth > 0) ? stack[--depth] : "") + + strcpy(pathbuf, path); + fixpath(pathbuf, len); + + p = pathbuf; + for(i=0; pathbuf[i] != '\0'; i++){ /* pass thru path name */ + if(pathbuf[i] == C_FILESEP){ + if(p != pathbuf) + PUSHD(p); /* push dir entry */ + p = &pathbuf[i+1]; /* advance p */ + pathbuf[i] = '\0'; /* cap old p off */ + continue; + } + + if(pathbuf[i] == '.'){ /* special cases! */ + if(pathbuf[i+1] == '.' /* parent */ + && (pathbuf[i+2] == C_FILESEP || pathbuf[i+2] == '\0')){ + if(!strcmp(POPD(),"")) /* bad news! */ + return(0); + + i += 2; + p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1]; + } + else if(pathbuf[i+1] == C_FILESEP || pathbuf[i+1] == '\0'){ + i++; + p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1]; + } + } + } + + if(*p != '\0') + PUSHD(p); /* get last element */ + + path[0] = '\0'; + for(i = 0; i < depth; i++){ + strcat(path, S_FILESEP); + strcat(path, stack[i]); + } + + return(1); /* everything's ok */ +} + + +/* + * tmpname - return a temporary file name in the given buffer + */ +void +tmpname(dir, name) +char *dir; +char *name; +{ + static int counter = 0; + static char *tmpdir = NULL; + char * p; + + if(dir && *dir) + tmpdir = dir; + + if(!tmpdir && (tmpdir=getenv("TEMP"))==NULL && (tmpdir = getenv("TMP"))==NULL) + tmpdir="."; + p = strchr(strcpy(name, tmpdir), '/'); + while (p != NULL) + { + *p++ = '\\'; + p = strchr(p, '/'); + } + p = strrchr(name, '\\'); + if (p == 0) + p = name + strlen(name); + else if (*++p != 0) + { + p = name + strlen(name); + *p++ = '\\'; + } + sprintf(p, "pn%d%d", getpid(), ++counter); + + if(dir && *dir) + tmpdir = NULL; +} + + +/* + * Take a file name, and from it + * fabricate a buffer name. This routine knows + * about the syntax of file names on the target system. + * I suppose that this information could be put in + * a better place than a line of code. + */ +void +makename(bname, fname) +char bname[]; +char fname[]; +{ + register char *cp1; + register char *cp2; + + cp1 = &fname[0]; + while (*cp1 != 0) + ++cp1; + + while (cp1!=&fname[0] && cp1[-1]!='\\') + --cp1; + cp2 = &bname[0]; + while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';') + *cp2++ = *cp1++; + *cp2 = 0; +} + + +/* + * copy - copy contents of file 'a' into a file named 'b'. Return error + * if either isn't accessible or is a directory + */ +copy(a, b) +char *a, *b; +{ + int n, rv = 0; + struct stat tsb, fsb; + + if(stat(a, &fsb) < 0){ /* get source file info */ + emlwrite("Can't Copy: %s", errstr(errno)); + return(-1); + } + + if(!(fsb.st_mode&S_IREAD)){ /* can we read it? */ + emlwrite("\007Read permission denied: %s", a); + return(-1); + } + + if((fsb.st_mode&S_IFMT) == S_IFDIR){ /* is it a directory? */ + emlwrite("\007Can't copy: %s is a directory", a); + return(-1); + } + + if(stat(b, &tsb) < 0){ /* get dest file's mode */ + switch(errno){ + case ENOENT: + break; /* these are OK */ + default: + emlwrite("\007Can't Copy: %s", errstr(errno)); + return(-1); + } + } + else{ + if(!(tsb.st_mode&S_IWRITE)){ /* can we write it? */ + emlwrite("\007Write permission denied: %s", b); + return(-1); + } + + if((tsb.st_mode&S_IFMT) == S_IFDIR){ /* is it directory? */ + emlwrite("\007Can't copy: %s is a directory", b); + return(-1); + } + + if(fsb.st_dev == tsb.st_dev && fsb.st_ino == tsb.st_ino){ + emlwrite("\007Identical files. File not copied", NULL); + return(-1); + } + } + + rv=DosCopy(a, b, DCPY_EXISTING); + + if(rv != 0 < 0){ + emlwrite("Copy Failed: DosCopy() error %d", rv); + return(-1); + } + return(rv); +} + + +/* + * Open a file for writing. Return TRUE if all is well, and FALSE on error + * (cannot create). + */ +ffwopen(fn, readonly) +char *fn; +int readonly; +{ + extern FIOINFO g_pico_fio; + + g_pico_fio.flags = FIOINFO_WRITE; + if ((g_pico_fio.fp = fopen(gf_pico_fio.name = fn, "w")) == NULL) { + emlwrite("Cannot open file for writing", NULL); + return (FIOERR); + } + + if(readonly) + chmod(fn, MODE_READONLY); /* fix access rights */ + + return (FIOSUC); +} + + +/* + * Close a file. Should look at the status in all systems. + */ +ffclose() +{ + extern FIOINFO g_pico_fio; + + if (fclose(g_pico_fio.fp) != FALSE) { + emlwrite("Error closing file", NULL); + return(FIOERR); + } + + return(FIOSUC); +} + + +/* + * ffelbowroom - make sure the destination's got enough room to receive + * what we're about to write... + */ +ffelbowroom(fn, readonly) +char *fn; +int readonly; +{ + return(TRUE); +} + + +/* + * worthit - generic sort of test to roughly gage usefulness of using + * optimized scrolling. + * + * note: + * returns the line on the screen, l, that the dot is currently on + */ +worthit(l) +int *l; +{ + int i; /* l is current line */ + unsigned below; /* below is avg # of ch/line under . */ + + *l = doton(&i, &below); + below = (i > 0) ? below/(unsigned)i : 0; + + return(below > 3); +} + + +/* + * o_insert - optimize screen insert of char c + */ +o_insert(c) +char c; +{ + return(0); +} + + +/* + * o_delete - optimized character deletion + */ +o_delete() +{ + return(0); +} + + +/* + * pico_new_mail - just checks mtime and atime of mail file and notifies user + * if it's possible that they have new mail. + */ +pico_new_mail() +{ + return(0); +} + + + +/* + * time_to_check - checks the current time against the last time called + * and returns true if the elapsed time is > below. + * Newmail won't necessarily check, but we want to give it + * a chance to check or do a keepalive. + */ +time_to_check() +{ + static time_t lasttime = 0L; + + if(!timeo) + return(FALSE); + + if(time((time_t *) 0) - lasttime > (Pmaster ? (time_t)(FUDGE-10) : timeo)){ + lasttime = time((time_t *) 0); + return(TRUE); + } + else + return(FALSE); +} + + +/* + * sstrcasecmp - compare two pointers to strings case independently + */ +sstrcasecmp(s1, s2) +QcompType *s1, *s2; +{ + return((*pcollator)(*(char **)s1, *(char **)s2)); +} + + +int +strucmp(o, r) + char *o, *r; +{ + return(o ? (r ? stricmp(o, r) : 1) : (r ? -1 : 0)); +} + + +int +struncmp(o, r, n) + char *o, *r; + int n; +{ + return(o ? (r ? strnicmp(o, r, n) : 1) : (r ? -1 : 0)); +} + + +/* + * sleep the given number of microseconds + */ +ssleep(s) + clock_t s; +{ + s += clock(); + while(s > clock()) + ; +} + + +/* + * chkptinit -- initialize anything we need to support composer + * checkpointing + */ +void +chkptinit(file, n) + char *file; + int n; +{ + if(!file[0]){ + long gmode_save = gmode; + + if(gmode&MDCURDIR) + gmode &= ~MDCURDIR; /* so fixpath will use home dir */ + + strcpy(file, "#picoTM0.txt"); + fixpath(file, NLINE); + gmode = gmode_save; + } + else{ + int l = strlen(file); + + if(file[l-1] != '\\'){ + file[l++] = '\\'; + file[l] = '\0'; + } + + strcpy(file + l, "#picoTM0.txt"); + } + + if(fexist(file, "r", (off_t *)NULL) == FIOSUC){ /* does file exist? */ + char copy[NLINE]; + + strcpy(copy, "#picoTM1.txt"); + fixpath(copy, NLINE); + rename(file, copy); /* save so we don't overwrite it */ + } + + unlink(file); +} + + +void +set_collation(collation, ctype) + int collation; + int ctype; +{ + extern int collator(); /* strcoll isn't declared on all systems */ +#ifdef LC_COLLATE + char *status = NULL; +#endif + + pcollator = strucmp; + +#ifdef LC_COLLATE + if(collation){ + /* + * This may not have the desired effect, if collator is not + * defined to be strcoll in os.h and strcmp and friends + * don't know about locales. If your system does have strcoll + * but we haven't defined collator to be strcoll in os.h, let us know. + */ + status = setlocale(LC_COLLATE, ""); + + /* + * If there is an error or if the locale is the "C" locale, then we + * don't want to use strcoll because in the default "C" locale strcoll + * uses strcmp ordering and we want strucmp ordering. + * + * The test for "C" isn't really correct, since status does not have to + * be "C" even if we're in the "C" locale. But this works on some systems. + */ + if(status && !(status[0] == 'C' && status[1] == '\0')) + pcollator = collator; + } +#endif +#ifdef LC_CTYPE + if(ctype){ + (void)setlocale(LC_CTYPE, ""); + } +#endif +} + + +static USHORT myShift = 0; + +int kbd_ready() +{ + KBDKEYINFO ki; + + if (KbdPeek(&ki, 0)==0) + { + if (ki.fbStatus & 0x40) { + int key = (USHORT)((ki.chScan << 8) | ki.chChar); + myShift = ki.fsState; + if (!key && ki.fbStatus & 0x01) { + KbdCharIn(&ki, IO_WAIT, 0); + } + return key; + } + } + return 0; +} + +int kbd_getkey() +{ + KBDKEYINFO ki; + + while (KbdCharIn(&ki, IO_WAIT, 0)==0) { + if (ki.fbStatus & 0x40) { + myShift = ki.fsState; + return (USHORT)((ki.chScan << 8) | ki.chChar); + } + if (ki.fbStatus & 0x01) { + myShift = ki.fsState; + } + } + + return NODATA; +} + +void kbd_flush() +{ + KbdFlushBuffer(0); +} + +int kbd_shift() +{ + return myShift; +} + + diff --git a/osdep/raw.brk b/osdep/raw.brk new file mode 100644 index 0000000..4b446ff --- /dev/null +++ b/osdep/raw.brk @@ -0,0 +1,216 @@ +/* + * TTY setup routines. These are the BSD-style routines. + */ + +static struct sgttyb _raw_tty, _original_tty; +static struct ltchars _raw_ltchars, _original_ltchars; +static struct tchars _raw_tchars, _original_tchars; +static int _raw_lmode, _original_lmode; + +/* + * current raw state + */ +static short _inraw = 0; + +/* + * Set up the tty driver + * + * Args: state -- which state to put it in. 1 means go into raw (cbreak), + * 0 out of raw. + * + * Result: returns 0 if successful and -1 if not. + */ +int +Raw(state) +int state; +{ + /** state is either ON or OFF, as indicated by call **/ + /* Check return code only on first call. If it fails we're done for and + if it goes OK the others will probably go OK too. */ + + if(state == 0 && _inraw){ + /*----- restore state to original -----*/ + if(ioctl(STDIN_FD, TIOCSETP, &_original_tty) < 0) + return(-1); + + (void)ioctl(STDIN_FD, TIOCSLTC, &_original_ltchars); + (void)ioctl(STDIN_FD, TIOCSETC, &_original_tchars); + (void)ioctl(STDIN_FD, TIOCLSET, &_original_lmode); + _inraw = 0; + } + else if(state == 1 && ! _inraw){ + /*----- Go into raw mode (cbreak actually) ----*/ + if(ioctl(STDIN_FD, TIOCGETP, &_original_tty) < 0) + return(-1); + + (void)ioctl(STDIN_FD, TIOCGETP, &_raw_tty); + (void)ioctl(STDIN_FD, TIOCGETC, &_original_tchars); + (void)ioctl(STDIN_FD, TIOCGETC, &_raw_tchars); + (void)ioctl(STDIN_FD, TIOCGLTC, &_original_ltchars); + (void)ioctl(STDIN_FD, TIOCGLTC, &_raw_ltchars); + (void)ioctl(STDIN_FD, TIOCLGET, &_original_lmode); + (void)ioctl(STDIN_FD, TIOCLGET, &_raw_lmode); + + _raw_tty.sg_flags &= ~(ECHO); /* echo off */ + _raw_tty.sg_flags |= CBREAK; /* raw on */ + _raw_tty.sg_flags &= ~CRMOD; /* Turn off CR -> LF mapping */ + + _raw_tchars.t_intrc = -1; /* Turn off ^C and ^D */ + _raw_tchars.t_eofc = -1; + + _raw_ltchars.t_lnextc = -1; /* Turn off ^V so we can use it */ + _raw_ltchars.t_dsuspc = -1; /* Turn off ^Y so we can use it */ + _raw_ltchars.t_suspc = -1; /* Turn off ^Z; we just read 'em */ + _raw_ltchars.t_werasc = -1; /* Turn off ^w word erase */ + _raw_ltchars.t_rprntc = -1; /* Turn off ^R reprint line */ + _raw_ltchars.t_flushc = -1; /* Turn off ^O output flush */ + + (void)ioctl(STDIN_FD, TIOCSETP, &_raw_tty); + (void)ioctl(STDIN_FD, TIOCSLTC, &_raw_ltchars); + (void)ioctl(STDIN_FD, TIOCSETC, &_raw_tchars); + (void)ioctl(STDIN_FD, TIOCLSET, &_raw_lmode); + _inraw = 1; + } + + return(0); +} + + +/* + * Set up the tty driver to use XON/XOFF flow control + * + * Args: state -- True to make sure XON/XOFF turned on, FALSE off. + * + * Result: none. + */ +void +xonxoff_proc(state) +int state; +{ + if(_inraw){ + if(state){ + if(_raw_tchars.t_startc == -1 || _raw_tchars.t_stopc == -1){ + _raw_tchars.t_startc = 'Q' - '@'; /* Turn ON ^S/^Q */ + _raw_tchars.t_stopc = 'S' - '@'; + (void)ioctl(STDIN_FD, TIOCSETC, &_raw_tchars); + } + } + else{ + if(!(_raw_tchars.t_startc == -1 && _raw_tchars.t_stopc == -1)){ + _raw_tchars.t_startc = -1; /* Turn off ^S/^Q */ + _raw_tchars.t_stopc = -1; + (void)ioctl(STDIN_FD, TIOCSETC, &_raw_tchars); + } + } + } +} + + +/* + * Set up the tty driver to do LF->CR translation + * + * Args: state -- True to turn on translation, false to write raw LF's + * + * Result: none. + */ +void +crlf_proc(state) +int state; +{ + if(_inraw){ + if(state){ /* turn ON NL->CR on output */ + if(!(_raw_tty.sg_flags & CRMOD)){ + _raw_tty.sg_flags |= CRMOD; + (void)ioctl(STDIN_FD, TIOCSETP, &_raw_tty); + } + } + else{ /* turn OFF NL-CR on output */ + if(_raw_tty.sg_flags & CRMOD){ + _raw_tty.sg_flags &= ~CRMOD; + (void)ioctl(STDIN_FD, TIOCSETP, &_raw_tty); + } + } + } +} + + +/* + * Set up the tty driver to hanle interrupt char + * + * Args: state -- True to turn on interrupt char, false to not + * + * Result: tty driver that'll send us SIGINT or not + */ +void +intr_proc(state) +int state; +{ + if(_inraw){ + if(state){ + _raw_tchars.t_intrc = ctrl('C'); + (void)ioctl(STDIN_FD, TIOCSETC, &_raw_tchars); + } + else{ + _raw_tchars.t_intrc = -1; + (void)ioctl(STDIN_FD, TIOCSETC, &_raw_tchars); + } + } +} + + +/* + * Discard any pending input characters + * + * Args: none + * + * Result: pending input buffer flushed + */ +void +flush_input() +{ +#ifdef TIOCFLUSH +#ifdef FREAD + int i = FREAD; +#else + int i = 1; +#endif + ioctl(STDIN_FD, TIOCFLUSH, &i); +#endif /* TIOCFLUSH */ +} + + +/* + * Turn off hi bit stripping + */ +void +bit_strip_off() +{ + _raw_lmode |= LPASS8; +#ifdef NXT + _raw_lmode |= LPASS8OUT; +#endif + (void)ioctl(STDIN_FD, TIOCLSET, &_raw_lmode); +} + + +/* + * Turn off quit character (^\) if possible + */ +void +quit_char_off() +{ + _raw_tchars.t_quitc = -1; + (void)ioctl(STDIN_FD, TIOCSETC, &_raw_tchars); +} + + +/* + * Returns TRUE if tty is < 4800, 0 otherwise. + */ +int +ttisslow() +{ + return((int)_raw_tty.sg_ispeed < B4800); +} + + diff --git a/osdep/raw.io b/osdep/raw.io new file mode 100644 index 0000000..c318f70 --- /dev/null +++ b/osdep/raw.io @@ -0,0 +1,178 @@ +/* + * TTY setup routines. These are the TERMIO-style (System V) routines. + */ + +static struct termio _raw_tty, _original_tty; + +/* + * current raw state + */ +static short _inraw = 0; + +/* + * Set up the tty driver + * + * Args: state -- which state to put it in. 1 means go into raw (cbreak), + * 0 out of raw. + * + * Result: returns 0 if successful and -1 if not. + */ +int +Raw(state) +int state; +{ + /** state is either ON or OFF, as indicated by call **/ + /* Check return code only on first call. If it fails we're done for and + if it goes OK the others will probably go OK too. */ + + if(state == 0 && _inraw){ + /*----- restore state to original -----*/ + if(ioctl(STDIN_FD, TCSETAW, &_original_tty) < 0) + return(-1); + + _inraw = 0; + } + else if(state == 1 && ! _inraw){ + /*----- Go into raw mode (cbreak actually) ----*/ + if(ioctl(STDIN_FD, TCGETA, &_original_tty) < 0) + return(-1); + + (void)ioctl(STDIN_FD, TCGETA, &_raw_tty); /** again! **/ + _raw_tty.c_lflag &= ~(ICANON | ECHO); /* noecho raw mode */ + _raw_tty.c_lflag &= ~ISIG; /* disable signals */ + _raw_tty.c_iflag &= ~ICRNL; /* turn off CR->NL on input */ + _raw_tty.c_oflag &= ~ONLCR; /* turn off NL->CR on output */ + _raw_tty.c_cc[VMIN] = 1; /* min # of chars to queue */ + _raw_tty.c_cc[VTIME] = 0; /* min time to wait for input*/ + _raw_tty.c_cc[VINTR] = ctrl('C'); /* make it our special char */ + _raw_tty.c_cc[VQUIT] = 0; + (void)ioctl(STDIN_FD, TCSETAW, &_raw_tty); + _inraw = 1; + } + + return(0); +} + + +/* + * Set up the tty driver to use XON/XOFF flow control + * + * Args: state -- True to make sure XON/XOFF turned on, FALSE off. + * + * Result: none. + */ +void +xonxoff_proc(state) +int state; +{ + if(_inraw){ + if(state){ + if(!(_raw_tty.c_iflag & IXON)){ + _raw_tty.c_iflag |= IXON; /* turn ON ^S/^Q on input */ + (void)ioctl(STDIN_FD, TCSETAW, &_raw_tty); + } + } + else{ + if(_raw_tty.c_iflag & IXON){ + _raw_tty.c_iflag &= ~IXON; /* turn off ^S/^Q on input */ + (void)ioctl(STDIN_FD, TCSETAW, &_raw_tty); + } + } + } +} + + +/* + * Set up the tty driver to do LF->CR translation + * + * Args: state -- True to turn on translation, false to write raw LF's + * + * Result: none. + */ +void +crlf_proc(state) +int state; +{ + if(_inraw){ + if(state){ /* turn ON NL->CR on output */ + if(!(_raw_tty.c_oflag & ONLCR)){ + _raw_tty.c_oflag |= ONLCR; + (void)ioctl(STDIN_FD, TCSETAW, &_raw_tty); + } + } + else{ /* turn OFF NL-CR on output */ + if(_raw_tty.c_oflag & ONLCR){ + _raw_tty.c_oflag &= ~ONLCR; + (void)ioctl(STDIN_FD, TCSETAW, &_raw_tty); + } + } + } +} + + +/* + * Set up the tty driver to hanle interrupt char + * + * Args: state -- True to turn on interrupt char, false to not + * + * Result: tty driver that'll send us SIGINT or not + */ +void +intr_proc(state) +int state; +{ + if(_inraw){ + if(state){ + _raw_tty.c_lflag |= ISIG; /* enable signals */ + (void)ioctl(STDIN_FD, TCSETAW, &_raw_tty); + } + else{ + _raw_tty.c_lflag &= ~ISIG; /* disable signals */ + (void)ioctl(STDIN_FD, TCSETAW, &_raw_tty); + } + } +} + + +/* + * Discard any pending input characters + * + * Args: none + * + * Result: pending input buffer flushed + */ +void +flush_input() +{ + ioctl(STDIN_FD, TCFLSH, 0); +} + + +/* + * Turn off hi bit stripping + */ +void +bit_strip_off() +{ +} + + +/* + * Turn off quit character (^\) if possible + */ +void +quit_char_off() +{ +} + + +/* + * Returns TRUE if tty is < 4800, 0 otherwise. + */ +int +ttisslow() +{ + return((_raw_tty.c_cflag&CBAUD) < (unsigned int)B4800); +} + + diff --git a/osdep/raw.ios b/osdep/raw.ios new file mode 100644 index 0000000..0ae0ff6 --- /dev/null +++ b/osdep/raw.ios @@ -0,0 +1,182 @@ +/* + * TTY setup routines. These are the TERMIOS-style (POSIX) routines. + */ + +static struct termios _raw_tty, _original_tty; + +/* + * current raw state + */ +static short _inraw = 0; + +/* + * Set up the tty driver + * + * Args: state -- which state to put it in. 1 means go into raw (cbreak), + * 0 out of raw. + * + * Result: returns 0 if successful and -1 if not. + */ +int +Raw(state) +int state; +{ + /** state is either ON or OFF, as indicated by call **/ + /* Check return code only on first call. If it fails we're done for and + if it goes OK the others will probably go OK too. */ + + if(state == 0 && _inraw){ + /*----- restore state to original -----*/ + if(tcsetattr(STDIN_FD, TCSADRAIN, &_original_tty) < 0) + return -1; + + _inraw = 0; + } + else if(state == 1 && ! _inraw){ + /*----- Go into raw mode (cbreak actually) ----*/ + if(tcgetattr(STDIN_FD, &_original_tty) < 0) + return -1; + + tcgetattr(STDIN_FD, &_raw_tty); + _raw_tty.c_lflag &= ~(ICANON | ECHO | IEXTEN); /* noecho raw mode */ + _raw_tty.c_lflag &= ~ISIG; /* disable signals */ + _raw_tty.c_iflag &= ~ICRNL; /* turn off CR->NL on input */ + _raw_tty.c_oflag &= ~ONLCR; /* turn off NL->CR on output */ + + _raw_tty.c_cc[VMIN] = '\01'; /* min # of chars to queue */ + _raw_tty.c_cc[VTIME] = '\0'; /* min time to wait for input*/ + _raw_tty.c_cc[VINTR] = ctrl('C'); /* make it our special char */ + _raw_tty.c_cc[VQUIT] = 0; + _raw_tty.c_cc[VSUSP] = 0; + tcsetattr(STDIN_FD, TCSADRAIN, &_raw_tty); + _inraw = 1; + } + + return(0); +} + + +/* + * Set up the tty driver to use XON/XOFF flow control + * + * Args: state -- True to make sure XON/XOFF turned on, FALSE off. + * + * Result: none. + */ +void +xonxoff_proc(state) +int state; +{ + if(_inraw){ + if(state){ + if(!(_raw_tty.c_iflag & IXON)){ + _raw_tty.c_iflag |= IXON; + tcsetattr (STDIN_FD, TCSADRAIN, &_raw_tty); + } + } + else{ + if(_raw_tty.c_iflag & IXON){ + _raw_tty.c_iflag &= ~IXON; /* turn off ^S/^Q on input */ + tcsetattr (STDIN_FD, TCSADRAIN, &_raw_tty); + } + } + } +} + + +/* + * Set up the tty driver to do LF->CR translation + * + * Args: state -- True to turn on translation, false to write raw LF's + * + * Result: none. + */ +void +crlf_proc(state) +int state; +{ + if(_inraw){ + if(state){ /* turn ON NL->CR on output */ + if(!(_raw_tty.c_oflag & ONLCR)){ + _raw_tty.c_oflag |= ONLCR; + tcsetattr (STDIN_FD, TCSADRAIN, &_raw_tty); + } + } + else{ /* turn OFF NL-CR on output */ + if(_raw_tty.c_oflag & ONLCR){ + _raw_tty.c_oflag &= ~ONLCR; + tcsetattr (STDIN_FD, TCSADRAIN, &_raw_tty); + } + } + } +} + + +/* + * Set up the tty driver to hanle interrupt char + * + * Args: state -- True to turn on interrupt char, false to not + * + * Result: tty driver that'll send us SIGINT or not + */ +void +intr_proc(state) +int state; +{ + if(_inraw){ + if(state){ + _raw_tty.c_lflag |= ISIG; /* enable signals */ + tcsetattr(STDIN_FD, TCSADRAIN, &_raw_tty); + } + else{ + _raw_tty.c_lflag &= ~ISIG; /* disable signals */ + tcsetattr(STDIN_FD, TCSADRAIN, &_raw_tty); + } + } +} + + +/* + * Discard any pending input characters + * + * Args: none + * + * Result: pending input buffer flushed + */ +void +flush_input() +{ + tcflush(STDIN_FD, TCIFLUSH); +} + + +/* + * Turn off hi bit stripping + */ +void +bit_strip_off() +{ + _raw_tty.c_iflag &= ~ISTRIP; + tcsetattr(STDIN_FD, TCSADRAIN, &_raw_tty); +} + + +/* + * Turn off quit character (^\) if possible + */ +void +quit_char_off() +{ +} + + +/* + * Returns TRUE if tty is < 4800, 0 otherwise. + */ +int +ttisslow() +{ + return(cfgetospeed(&_raw_tty) < B4800); +} + + diff --git a/osdep/read.pol b/osdep/read.pol new file mode 100644 index 0000000..1b94701 --- /dev/null +++ b/osdep/read.pol @@ -0,0 +1,95 @@ +#include +#include + +/* + * Check whether or not a character is ready to be read, or time out. + * This version uses a poll call. + * + * Args: time_out -- number of seconds before it will time out. + * + * Result: NO_OP_IDLE: timed out before any chars ready, time_out > 25 + * NO_OP_COMMAND: timed out before any chars ready, time_out <= 25 + * READ_INTR: read was interrupted + * READY_TO_READ: input is available + * BAIL_OUT: reading input failed, time to bail gracefully + * PANIC_NOW: system call error, die now + */ +int +input_ready(time_out) + int time_out; +{ + struct pollfd pollfd; + int res; + + fflush(stdout); + + if(time_out > 0){ + /* Check to see if there are bytes to read with a timeout */ + pollfd.fd = STDIN_FD; + pollfd.events = POLLIN; + res = poll (&pollfd, 1, time_out * 1000); + if(res >= 0){ /* status bits OK? */ + if(pollfd.revents & (POLLERR | POLLNVAL)) + res = -1; /* bad news, exit below! */ + else if(pollfd.revents & POLLHUP) + return(BAIL_OUT); + } + + if(res < 0){ + if(errno == EINTR || errno == EAGAIN) + return(READ_INTR); + + return(PANIC_NOW); + } + + if(res == 0){ /* the select timed out */ + if(getppid() == 1){ + /* Parent is init! */ + return(BAIL_OUT); + } + + /* + * "15" is the minimum allowed mail check interval. + * Anything less, and we're being told to cycle thru + * the command loop because some task is pending... + */ + return(time_out < IDLE_TIMEOUT ? NO_OP_COMMAND : NO_OP_IDLE); + } + } + + time_of_last_input = time((time_t *) 0); + return(READY_TO_READ); +} + + +/* + * Read one character from STDIN. + * + * Result: -- the single character read + * READ_INTR -- read was interrupted + * BAIL_OUT -- read error of some sort + */ +int +read_one_char() +{ + int res; + unsigned char c; + + res = read(STDIN_FD, &c, 1); + + if(res <= 0){ + /* + * Error reading from terminal! + * The only acceptable failure is being interrupted. If so, + * return a value indicating such... + */ + if(res < 0 && errno == EINTR) + return(READ_INTR); + else + return(BAIL_OUT); + } + + return((int)c); +} + + diff --git a/osdep/read.sel b/osdep/read.sel new file mode 100644 index 0000000..189ab28 --- /dev/null +++ b/osdep/read.sel @@ -0,0 +1,90 @@ +/* + * Check whether or not a character is ready to be read, or time out. + * This version uses a select call. + * + * Args: time_out -- number of seconds before it will time out. + * + * Result: NO_OP_IDLE: timed out before any chars ready, time_out > 25 + * NO_OP_COMMAND: timed out before any chars ready, time_out <= 25 + * READ_INTR: read was interrupted + * READY_TO_READ: input is available + * BAIL_OUT: reading input failed, time to bail gracefully + * PANIC_NOW: system call error, die now + */ +int +input_ready(time_out) + int time_out; +{ + struct timeval tmo; + fd_set readfds, errfds; + int res; + + fflush(stdout); + + if(time_out > 0){ + /* Check to see if there are bytes to read with a timeout */ + FD_ZERO(&readfds); + FD_ZERO(&errfds); + FD_SET(STDIN_FD, &readfds); + FD_SET(STDIN_FD, &errfds); + tmo.tv_sec = time_out; + tmo.tv_usec = 0; + res = select(STDIN_FD+1, &readfds, 0, &errfds, &tmo); + if(res < 0){ + if(errno == EINTR || errno == EAGAIN) + return(READ_INTR); + + return(BAIL_OUT); + } + + if(res == 0){ /* the select timed out */ + if(getppid() == 1){ + /* Parent is init! */ + return(BAIL_OUT); + } + + /* + * "15" is the minimum allowed mail check interval. + * Anything less, and we're being told to cycle thru + * the command loop because some task is pending... + */ + return(time_out < IDLE_TIMEOUT ? NO_OP_COMMAND : NO_OP_IDLE); + } + } + + time_of_last_input = time((time_t *) 0); + return(READY_TO_READ); +} + + +/* + * Read one character from STDIN. + * + * Result: -- the single character read + * READ_INTR -- read was interrupted + * BAIL_OUT -- read error of some sort + */ +int +read_one_char() +{ + int res; + unsigned char c; + + res = read(STDIN_FD, &c, 1); + + if(res <= 0){ + /* + * Error reading from terminal! + * The only acceptable failure is being interrupted. If so, + * return a value indicating such... + */ + if(res < 0 && errno == EINTR) + return(READ_INTR); + else + return(BAIL_OUT); + } + + return((int)c); +} + + diff --git a/osdep/spell.ms b/osdep/spell.ms new file mode 100644 index 0000000..f622e3b --- /dev/null +++ b/osdep/spell.ms @@ -0,0 +1,246 @@ +#line 2 "osdep/spell.ms" +/* + * Program: msspell.c + * + * + * Thomas Unger and Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: pine@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2002 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + */ + +#include "headers.h" + +#ifdef SPELLER +#include "../spell/spell.h" + + +extern FILE *gfDebugFile = NULL; + + + +int movetoword PROTO((char *)); + + +#define NSHLINES 12 + +static char *spellhelp[] = { + "Spell Check Help", + " ", + "\tThe spell checker examines all words in the text. It then", + "\toffers each misspelled word for correction while simultaneously", + "\thighlighting it in the text. To leave a word unchanged simply", + "~\thit ~R~e~t~u~r~n at the edit prompt. If a word has been corrected,", + "\teach occurrence of the incorrect word is offered for replacement.", + " ", + "~\tSpell checking can be cancelled at any time by typing ~^~C (~F~3)", + "\tafter exiting help.", + " ", + "End of Spell Check Help", + " ", + NULL +}; + + +static char *pinespellhelp[] = { + "Spell Check Help", + " ", + "\tThe spell checker examines all words in the text. It then", + "\toffers each misspelled word for correction while simultaneously", + "\thighlighting it in the text. To leave a word unchanged simply", + "\thit Return at the edit prompt. If a word has been corrected,", + "\teach occurrence of the incorrect word is offered for replacement.", + " ", + "\tSpell checking can be cancelled at any time by typing ^C (F3)", + "\tafter exiting help.", + " ", + "End of Spell Check Help", + " ", + NULL +}; + + +extern HWND ghTTYWnd; + + + +/* + * spell() - check for potentially missspelled words and offer them for + * correction + */ +spell(f, n) + int f, n; +{ + int wlen, bsize, ret, begi, endi, offset, i, qlen; + char wbuf[NLINE], *lbuf; + FILE *p; + LINE *lbp; /* pointer to line before current line */ + struct StrStResult result; + + setimark(0, 1); + gotobob(0, 1); + emlwrite("Checking spelling...",NULL); /* greetings */ + + ret = 1; + + StResetUserDict((char *) getenv("USER_DICTIONARY"), NULL); + + qlen = (Pmaster && Pmaster->quote_str) ? strlen(Pmaster->quote_str) : 0; + lbuf = (char *) malloc(sizeof(char)); + bsize = 0; + for(lbp = curbp->b_linep; lbp != curbp->b_linep->l_bp; lbp = lforw(lbp)){ + /* + * before, we were accessing the current line, but since that can + * potentially be free()'d (like in chword()), we should only access + * the line from the line before (hence all the lforw(lbp)'s). + */ + if(qlen){ /* quoted line? */ + i = 0; + if(qlen <= llength(lforw(lbp))) + while(i < qlen && Pmaster->quote_str[i] == lgetc(lforw(lbp), i).c) + i++; + + if(i == qlen) + continue; + } + + if(bsize < llength(lforw(lbp)) + 2){ /* resize line buffer? */ + bsize = llength(lforw(lbp)); + if(!(lbuf = (char *)realloc(lbuf, (bsize + 1) * sizeof(char)))){ + emlwrite("Can't reallocate internal buffer!", NULL); + ret = 0; /* FAILURE ! */ + break; + } + } + + for(i = 0; i < llength(lforw(lbp)); i++) /* copy line to buffer */ + lbuf[i] = lgetc(lforw(lbp), i).c; + + lbuf[i] = '\0'; /* initialize */ + begi = endi = offset = 0; + while(wlen = StParseLine(lbuf, wbuf, &begi, &endi, i)) + if(!SpellWord(wbuf, 0, ghTTYWnd, &result)){ + + if(movetoword(wbuf) != TRUE) + break; + + update(); + (*term.t_rev)(1); + pputs(wbuf, 1); /* and highlight it */ + (*term.t_rev)(0); + + SpellWord(wbuf, ST_INTERACTIVE, ghTTYWnd, &result); + + curwp->w_flag |= WFMOVE; /* put cursor back */ + sgarbk = 0; /* fake no-keymenu-change! */ + update(); + pputs(wbuf, 0); /* un-highlight */ + + if(result.code & (ST_EXIT | ST_ERROR)){ + if(result.code & ST_EXIT) + emlwrite("Spell Checking Cancelled", NULL); + + lbp = NULL; /* stop looking */ + ret = 0; + break; + } + else if(result.replace[0]){ + chword(wbuf, result.replace); /* correct word */ + offset += strlen(result.replace) - wlen; + update(); /* place cursor */ + } + } + + if(!lbp) /* more to come? */ + break; + } + + StResetUserDict(NULL, NULL); + StClearHist(); + swapimark(0, 1); + curwp->w_flag |= WFHARD|WFMODE; + sgarbk = TRUE; + + if(ret) + emlwrite("Done checking spelling", NULL); + + return(ret); +} + + +/* + * movetoword() - move to the first occurance of the word w + * + * returns: + * TRUE upon success + * FALSE otherwise + * + * BUG - since it only moves to the first occurence, there is + * no possibility to ignore the first misspelling and + * change the second. + */ +movetoword(w) + char *w; +{ + int i; + int ret = FALSE; + int olddoto; + LINE *olddotp; + register int off; /* curwp offset */ + register LINE *lp; /* curwp line */ + + olddoto = curwp->w_doto; /* save where we are */ + olddotp = curwp->w_dotp; + + curwp->w_bufp->b_mode |= MDEXACT; /* case sensitive */ + while(forscan(&i, w, NULL, 0, 1) == TRUE){ + if(i) + break; /* wrap NOT allowed! */ + + lp = curwp->w_dotp; /* for convenience */ + off = curwp->w_doto; + + /* + * We want to minimize the number of substrings that we report + * as matching a misspelled word... + */ + if(off == 0 || !isalpha((unsigned char)lgetc(lp, off - 1).c)){ + off += strlen(w); + if((!isalpha((unsigned char)lgetc(lp, off).c) || off == llength(lp)) + && lgetc(lp, 0).c != '>'){ + ret = TRUE; + break; + } + } + + forwchar(0, 1); /* move on... */ + + } + curwp->w_bufp->b_mode ^= MDEXACT; /* case insensitive */ + + if(ret == FALSE){ + curwp->w_dotp = olddotp; + curwp->w_doto = olddoto; + } + else + curwp->w_flag |= WFHARD; + + return(ret); +} +#endif /* SPELLER */ diff --git a/osdep/spell.os2 b/osdep/spell.os2 new file mode 100644 index 0000000..6daea02 --- /dev/null +++ b/osdep/spell.os2 @@ -0,0 +1,117 @@ +/* + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-1998 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + */ + +#ifdef SPELLER + +/* + * spell - fork off an spell checker + * this is different for OS/2 with ispell; here, the document + * correction and interface is provided by ispell itself + */ +#define MAXARGS 10 +spell(f, n) + int f, n; +{ + char sp[NLINE]; /* buf holding spell command */ + char *fn; /* tmp holder for file name */ + char *cp; + char *args[MAXARGS]; /* ptrs into edit command */ + int child, rc, i, done = 0; + long l; + int stat; + FILE *p; + + if(Pmaster == NULL) + return(-1); + + if((fn = writetmp(0, NULL)) == NULL){ + emlwrite("Can't write temp file for spell checker"); + return(-1); + } + if((cp = (char *)getenv("SPELL")) == NULL) + cp = SPELLER; + strcpy(sp,cp); + + if((fn=writetmp(1, NULL)) == NULL){ /* get temp file */ + emlwrite("Problem writing temp file for spell checker", NULL); + return(-1); + } + + strcat(sp, " "); + strcat(sp, fn); + + cp = sp; + for(i=0; *cp != '\0';i++) { /* build args array */ + if(i < MAXARGS) { + args[i] = NULL; /* in case we break out */ + } + else{ + emlwrite("Too many args for command!", NULL); + return(-1); + } + + while(isspace((unsigned char)(*cp))) + if(*cp != '\0') + cp++; + else break; + + args[i] = cp; + while(!isspace((unsigned char)(*cp))) + if(*cp != '\0') + cp++; + else + break; + + if(*cp != '\0') + *cp++ = '\0'; + } + + args[i] = NULL; + + (*Pmaster->tty_fix)(0); + + emlwrite("Invoking spell checker...", NULL); + + { + void (*ohup)() = signal(SIGHUP, SIG_IGN); /* ignore signals for now */ + void (*oint)() = signal(SIGINT, SIG_IGN); + cp=args[0]; + rc = spawnvp(P_WAIT, cp, args); + signal(SIGHUP, ohup); /* restore signals */ + signal(SIGINT, oint); + } + + (*Pmaster->tty_fix)(1); + dont_interrupt(); + + if (rc==-1) { /* Can't run it */ + emlwrite("error attempting to run speller", NULL); + } + /* + * replace edited text with new text + */ + else{ + rc = 0; + curbp->b_flag &= ~BFCHG; /* make sure old text gets blasted */ + readin(fn, 0, 0); /* read new text overwriting old */ + curbp->b_flag |= BFCHG; /* mark dirty for packbuf() */ + } + unlink(fn); /* blast temp file */ + + ttopen(); /* reset the signals */ + pico_refresh(0, 1); /* redraw */ + return(rc); +} + +#endif /* SPELLER */ + + diff --git a/osdep/spell.unx b/osdep/spell.unx new file mode 100644 index 0000000..9144d34 --- /dev/null +++ b/osdep/spell.unx @@ -0,0 +1,255 @@ +/* + * Program: spell.c + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2002 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ + +#ifdef SPELLER + +int movetoword PROTO((char *)); + +#define NSHLINES 12 + +static char *spellhelp[] = { + "Spell Check Help", + " ", + "\tThe spell checker examines all words in the text. It then", + "\toffers each misspelled word for correction while simultaneously", + "\thighlighting it in the text. To leave a word unchanged simply", + "~\thit ~R~e~t~u~r~n at the edit prompt. If a word has been corrected,", + "\teach occurrence of the incorrect word is offered for replacement.", + " ", + "~\tSpell checking can be cancelled at any time by typing ~^~C (~F~3)", + "\tafter exiting help.", + " ", + "End of Spell Check Help", + " ", + NULL +}; + + +static char *pinespellhelp[] = { + "Spell Check Help", + " ", + "\tThe spell checker examines all words in the text. It then", + "\toffers each misspelled word for correction while simultaneously", + "\thighlighting it in the text. To leave a word unchanged simply", + "\thit Return at the edit prompt. If a word has been corrected,", + "\teach occurrence of the incorrect word is offered for replacement.", + " ", + "\tSpell checking can be cancelled at any time by typing ^C (F3)", + "\tafter exiting help.", + " ", + "End of Spell Check Help", + " ", + NULL +}; + + + +/* + * spell() - check for potentially missspelled words and offer them for + * correction + */ +spell(f, n) + int f, n; +{ + int status, next, ret; + FILE *p; + char *b, *sp, *fn; + char wb[NLINE], cb[NLINE]; + FILE *P_open(); + + setimark(0, 1); + emlwrite("Checking spelling...", NULL); /* greetings */ + + if(alt_speller) + return(alt_editor(1, 0)); /* f == 1 means fork speller */ + + if((fn = writetmp(0, NULL)) == NULL){ + emlwrite("Can't write temp file for spell checker", NULL); + return(-1); + } + + if((sp = (char *)getenv("SPELL")) == NULL) + sp = SPELLER; + + if(fexist(sp, "x", (off_t *)NULL) != FIOSUC){ + emlwrite("\007Spell-checking file \"%s\" not found", sp); + return(-1); + } + + sprintf(cb, "( %s ) < %s", sp, fn); /* pre-use buffer! */ + if((p = P_open(cb)) == NULL){ /* read output from command */ + unlink(fn); + emlwrite("Can't fork spell checker", NULL); + return(-1); + } + + ret = 1; + while(fgets(wb, NLINE, p) != NULL && ret){ + if((b = (char *)strchr(wb,'\n')) != NULL) + *b = '\0'; + strcpy(cb, wb); + + gotobob(0, 1); + + status = TRUE; + next = 1; + + while(status){ + if(next++) + if(movetoword(wb) != TRUE) + break; + + update(); + (*term.t_rev)(1); + pputs(wb, 1); /* highlight word */ + (*term.t_rev)(0); + + if(strcmp(cb, wb)){ + char prompt[2*NLINE + 32]; + sprintf(prompt, "Replace \"%s\" with \"%s\"", wb, cb); + status=mlyesno(prompt, TRUE); + } + else + status=mlreplyd("Edit a replacement: ", cb, NLINE, QDEFLT, NULL); + + + curwp->w_flag |= WFMOVE; /* put cursor back */ + sgarbk = 0; /* fake no-keymenu-change! */ + update(); + pputs(wb, 0); /* un-highlight */ + + switch(status){ + case TRUE: + chword(wb, cb); /* correct word */ + case FALSE: + update(); /* place cursor */ + break; + case ABORT: + emlwrite("Spell Checking Cancelled", NULL); + ret = FALSE; + status = FALSE; + break; + case HELPCH: + if(Pmaster){ + VARS_TO_SAVE *saved_state; + + saved_state = save_pico_state(); + (*Pmaster->helper)(pinespellhelp, + "Help with Spelling Checker", 1); + if(saved_state){ + restore_pico_state(saved_state); + free_pico_state(saved_state); + } + } + else + pico_help(spellhelp, "Help with Spelling Checker", 1); + case (CTRL|'L'): + next = 0; /* don't get next word */ + sgarbf = TRUE; /* repaint full screen */ + update(); + status = TRUE; + continue; + default: + emlwrite("Huh?", NULL); /* shouldn't get here, but.. */ + status = TRUE; + sleep(1); + break; + } + forwword(0, 1); /* goto next word */ + } + } + P_close(p); /* clean up */ + unlink(fn); + swapimark(0, 1); + curwp->w_flag |= WFHARD|WFMODE; + sgarbk = TRUE; + + if(ret) + emlwrite("Done checking spelling", NULL); + return(ret); +} + + + +/* + * movetoword() - move to the first occurance of the word w + * + * returns: + * TRUE upon success + * FALSE otherwise + */ +movetoword(w) + char *w; +{ + int i; + int ret = FALSE; + int olddoto; + LINE *olddotp; + register int off; /* curwp offset */ + register LINE *lp; /* curwp line */ + + olddoto = curwp->w_doto; /* save where we are */ + olddotp = curwp->w_dotp; + + curwp->w_bufp->b_mode |= MDEXACT; /* case sensitive */ + while(forscan(&i, w, NULL, 0, 1) == TRUE){ + if(i) + break; /* wrap NOT allowed! */ + + lp = curwp->w_dotp; /* for convenience */ + off = curwp->w_doto; + + /* + * We want to minimize the number of substrings that we report + * as matching a misspelled word... + */ + if(off == 0 || !isalpha((unsigned char)lgetc(lp, off - 1).c)){ + off += strlen(w); + if((!isalpha((unsigned char)lgetc(lp, off).c) || off == llength(lp)) + && lgetc(lp, 0).c != '>'){ + ret = TRUE; + break; + } + } + + forwchar(0, 1); /* move on... */ + + } + curwp->w_bufp->b_mode ^= MDEXACT; /* case insensitive */ + + if(ret == FALSE){ + curwp->w_dotp = olddotp; + curwp->w_doto = olddoto; + } + else + curwp->w_flag |= WFHARD; + + return(ret); +} +#endif /* SPELLER */ + + diff --git a/osdep/term.ans b/osdep/term.ans new file mode 100644 index 0000000..55a464c --- /dev/null +++ b/osdep/term.ans @@ -0,0 +1,166 @@ +#if !defined(DOS) +static char rcsid[] = "$Id: term.ans 7884 1998-02-28 00:15:44Z hubert $"; +#endif +/* + * Program: ANSI terminal driver routines + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-1998 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* + * The routines in this file provide support for ANSI style terminals + * over a serial line. The serial I/O services are provided by routines in + * "termio.c". It compiles into nothing if not an ANSI device. + */ + +#define termdef 1 /* don't define "term" external */ + +#if ANSI_DRIVER + +#define MARGIN 8 /* size of minimim margin and */ +#define SCRSIZ 64 /* scroll size for extended lines */ +#define MROW 2 /* rows in menu */ +#define BEL 0x07 /* BEL character. */ +#define ESC 0x1B /* ESC character. */ + +extern int ttopen(); /* Forward references. */ +extern int ttgetc(); +extern int ttputc(); +extern int ttflush(); +extern int ttclose(); +extern int ansimove(); +extern int ansieeol(); +extern int ansieeop(); +extern int ansibeep(); +extern int ansiopen(); +extern int ansiterminalinfo(); +extern int ansirev(); +/* + * Standard terminal interface dispatch table. Most of the fields point into + * "termio" code. + */ +#if defined(VAX) && !defined(__ALPHA) +globaldef +#endif +TERM term = { + NROW-1, + NCOL, + MARGIN, + SCRSIZ, + MROW, + ansiopen, + ansiterminalinfo, + ttclose, + ttgetc, + ttputc, + ttflush, + ansimove, + ansieeol, + ansieeop, + ansibeep, + ansirev +}; + +ansimove(row, col) +{ + ttputc(ESC); + ttputc('['); + ansiparm(row+1); + ttputc(';'); + ansiparm(col+1); + ttputc('H'); +} + +ansieeol() +{ + ttputc(ESC); + ttputc('['); + ttputc('K'); +} + +ansieeop() +{ + ttputc(ESC); + ttputc('['); + ttputc('J'); +} + +ansirev(state) /* change reverse video state */ + +int state; /* TRUE = reverse, FALSE = normal */ + +{ + static int PrevState = 0; + + if(state != PrevState) { + PrevState = state ; + ttputc(ESC); + ttputc('['); + ttputc(state ? '7': '0'); + ttputc('m'); + } +} + +ansibeep() +{ + ttputc(BEL); + ttflush(); +} + +ansiparm(n) +register int n; +{ + register int q; + + q = n/10; + if (q != 0) + ansiparm(q); + ttputc((n%10) + '0'); +} + +#endif + +ansiterminalinfo(termcap_wins) + int termcap_wins; +{ +#if V7 + register char *cp; + char *getenv(); + + if ((cp = getenv("TERM")) == NULL) { + puts("Shell variable TERM not defined!"); + exit(1); + } + if (strcmp(cp, "vt100") != 0) { + puts("Terminal type not 'vt100'!"); + exit(1); + } +#endif + revexist = TRUE; +} + +ansiopen() +{ + ttopen(); +} + + diff --git a/osdep/term.cap b/osdep/term.cap new file mode 100644 index 0000000..a740492 --- /dev/null +++ b/osdep/term.cap @@ -0,0 +1,774 @@ +/* + * Program: Display routines + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2001 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* tcap: Unix V5, V7 and BS4.2 Termcap video driver + for MicroEMACS +*/ + +#define termdef 1 /* don't define "term" external */ + +#if defined(USE_TERMCAP) +#define MARGIN 8 +#define SCRSIZ 64 +#define MROW 2 + +static int tcapmove PROTO((int, int)); +static int tcapeeol PROTO((void)); +static int tcapeeop PROTO((void)); +static int tcapbeep PROTO((void)); +static int tcaprev PROTO((int)); +static int tcapopen PROTO((void)); +static int tcapterminalinfo PROTO((int)); +static int tcapclose PROTO((void)); +static void setup_dflt_esc_seq PROTO((void)); +static void tcapinsert PROTO((int)); +static void tcapdelete PROTO((void)); + +extern int tput(); +extern char *tgoto(); + +/* + * This number used to be 315. No doubt there was a reason for that but we + * don't know what it was. It's a bit of a hassle to make it dynamic, and most + * modern systems seem to be using terminfo, so we'll just change it to 800. + * We weren't stopping on overflow before, so we'll do that, too. + */ +#define TCAPSLEN 800 +char tcapbuf[TCAPSLEN]; +int _tlines, _tcolumns; +char *_clearscreen, *_moveto, *_up, *_down, *_right, *_left, + *_setinverse, *_clearinverse, + *_setunderline, *_clearunderline, + *_setbold, *_clearallattr, /* there is no clear only bold! */ + *_cleartoeoln, *_cleartoeos, + *_deleteline, /* delete line */ + *_insertline, /* insert line */ + *_scrollregion, /* define a scrolling region, vt100 */ + *_insertchar, /* insert character, preferable to : */ + *_startinsert, /* set insert mode and, */ + *_endinsert, /* end insert mode */ + *_deletechar, /* delete character */ + *_startdelete, /* set delete mode and, */ + *_enddelete, /* end delete mode */ + *_scrolldown, /* scroll down */ + *_scrollup, /* scroll up */ + *_termcap_init, /* string to start termcap */ + *_termcap_end, /* string to end termcap */ + *_op, *_oc, *_setaf, *_setab, *_setf, *_setb, *_scp; +int _colors, _pairs, _bce; +char term_name[40]; + +TERM term = { + NROW-1, + NCOL, + MARGIN, + SCRSIZ, + MROW, + tcapopen, + tcapterminalinfo, + tcapclose, + ttgetc, + ttputc, + ttflush, + tcapmove, + tcapeeol, + tcapeeop, + tcapbeep, + tcaprev +}; + + +/* + * Add default keypad sequences to the trie. + */ +static void +setup_dflt_esc_seq() +{ + /* + * this is sort of a hack, but it allows us to use + * the function keys on pc's running telnet + */ + + /* + * UW-NDC/UCS vt10[02] application mode. + */ + kpinsert("\033OP", F1, 1); + kpinsert("\033OQ", F2, 1); + kpinsert("\033OR", F3, 1); + kpinsert("\033OS", F4, 1); + kpinsert("\033Op", F5, 1); + kpinsert("\033Oq", F6, 1); + kpinsert("\033Or", F7, 1); + kpinsert("\033Os", F8, 1); + kpinsert("\033Ot", F9, 1); + kpinsert("\033Ou", F10, 1); + kpinsert("\033Ov", F11, 1); + kpinsert("\033Ow", F12, 1); + + /* + * DC vt100, ANSI and cursor key mode. + */ + kpinsert("\033OA", KEY_UP, 1); + kpinsert("\033OB", KEY_DOWN, 1); + kpinsert("\033OC", KEY_RIGHT, 1); + kpinsert("\033OD", KEY_LEFT, 1); + + /* + * special keypad functions + */ + kpinsert("\033[4J", KEY_PGUP, 1); + kpinsert("\033[3J", KEY_PGDN, 1); + kpinsert("\033[2J", KEY_HOME, 1); + kpinsert("\033[N", KEY_END, 1); + + /* + * vt220? + */ + kpinsert("\033[5~", KEY_PGUP, 1); + kpinsert("\033[6~", KEY_PGDN, 1); + kpinsert("\033[1~", KEY_HOME, 1); + kpinsert("\033[4~", KEY_END, 1); + + /* + * konsole, XTerm (XFree 4.x.x) keyboard setting + */ + kpinsert("\033[H", KEY_HOME, 1); + kpinsert("\033[F", KEY_END, 1); + + /* + * gnome-terminal 2.6.0, don't know why it + * changed from 2.2.1 + */ + kpinsert("\033OH", KEY_HOME, 1); + kpinsert("\033OF", KEY_END, 1); + + /* + * "\033[2~" was common for KEY_HOME in a quick survey + * of terminals (though typically the Insert key). + * Teraterm 2.33 sends the following escape sequences, + * which is quite incompatible with everything + * else: + * Home: "\033[2~" End: "\033[5~" PgUp: "\033[3~" + * PgDn: "\033[6~" + * The best thing to do would be to fix TeraTerm + * keymappings or to tweak terminfo. + */ + + /* + * ANSI mode. + */ + kpinsert("\033[=a", F1, 1); + kpinsert("\033[=b", F2, 1); + kpinsert("\033[=c", F3, 1); + kpinsert("\033[=d", F4, 1); + kpinsert("\033[=e", F5, 1); + kpinsert("\033[=f", F6, 1); + kpinsert("\033[=g", F7, 1); + kpinsert("\033[=h", F8, 1); + kpinsert("\033[=i", F9, 1); + kpinsert("\033[=j", F10, 1); + kpinsert("\033[=k", F11, 1); + kpinsert("\033[=l", F12, 1); + + /* + * DEC vt100, ANSI, cursor key mode reset. + */ + kpinsert("\033[A", KEY_UP, 1); + kpinsert("\033[B", KEY_DOWN, 1); + kpinsert("\033[C", KEY_RIGHT, 1); + kpinsert("\033[D", KEY_LEFT, 1); + + /* + * DEC vt52 mode. + */ + kpinsert("\033A", KEY_UP, 1); + kpinsert("\033B", KEY_DOWN, 1); + kpinsert("\033C", KEY_RIGHT, 1); + kpinsert("\033D", KEY_LEFT, 1); + + /* + * DEC vt52 application keys, and some Zenith 19. + */ + kpinsert("\033?r", KEY_DOWN, 1); + kpinsert("\033?t", KEY_LEFT, 1); + kpinsert("\033?v", KEY_RIGHT, 1); + kpinsert("\033?x", KEY_UP, 1); + + /* + * Sun Console sequences. + */ + kpinsert("\033[1", KEY_SWALLOW_Z, 1); + kpinsert("\033[215", KEY_SWAL_UP, 1); + kpinsert("\033[217", KEY_SWAL_LEFT, 1); + kpinsert("\033[219", KEY_SWAL_RIGHT, 1); + kpinsert("\033[221", KEY_SWAL_DOWN, 1); + + /* + * Kermit App Prog Cmd, gobble until ESC \ (kermit should intercept this) + */ + kpinsert("\033_", KEY_KERMIT, 1); + + /* + * Fake a control character. + */ + kpinsert("\033\033", KEY_DOUBLE_ESC, 1); +} + + +/* + * Read termcap and set some global variables. Initialize input trie to + * decode escape sequences. + */ +static int +tcapterminalinfo(termcap_wins) + int termcap_wins; +{ + char *p, *tgetstr(); + char tcbuf[2*1024]; + char *tv_stype; + char err_str[72]; + int err; + char *_ku, *_kd, *_kl, *_kr, + *_kppu, *_kppd, *_kphome, *_kpend, *_kpdel, + *_kf1, *_kf2, *_kf3, *_kf4, *_kf5, *_kf6, + *_kf7, *_kf8, *_kf9, *_kf10, *_kf11, *_kf12; + + if (!(tv_stype = getenv("TERM")) || !strcpy(term_name, tv_stype)){ + if(Pmaster){ + return(-1); + } + else{ + puts("Environment variable TERM not defined!"); + exit(1); + } + } + + if((err = tgetent(tcbuf, tv_stype)) != 1){ + if(Pmaster){ + return(err - 2); + } + else{ + sprintf(err_str, "Unknown terminal type %s!", tv_stype); + puts(err_str); + exit(1); + } + } + + p = tcapbuf; + + _clearscreen = tgetstr("cl", &p); + _moveto = tgetstr("cm", &p); + _up = tgetstr("up", &p); + _down = tgetstr("do", &p); + _right = tgetstr("nd", &p); + _left = tgetstr("bs", &p); + _setinverse = tgetstr("so", &p); + _clearinverse = tgetstr("se", &p); + _setunderline = tgetstr("us", &p); + _clearunderline = tgetstr("ue", &p); + _setbold = tgetstr("md", &p); + _clearallattr = tgetstr("me", &p); + _cleartoeoln = tgetstr("ce", &p); + _cleartoeos = tgetstr("cd", &p); + _deletechar = tgetstr("dc", &p); + _insertchar = tgetstr("ic", &p); + _startinsert = tgetstr("im", &p); + _endinsert = tgetstr("ei", &p); + _deleteline = tgetstr("dl", &p); + _insertline = tgetstr("al", &p); + _scrollregion = tgetstr("cs", &p); + _scrolldown = tgetstr("sf", &p); + _scrollup = tgetstr("sr", &p); + _termcap_init = tgetstr("ti", &p); + _termcap_end = tgetstr("te", &p); + _startdelete = tgetstr("dm", &p); + _enddelete = tgetstr("ed", &p); + _ku = tgetstr("ku", &p); + _kd = tgetstr("kd", &p); + _kl = tgetstr("kl", &p); + _kr = tgetstr("kr", &p); + _kppu = tgetstr("kP", &p); + _kppd = tgetstr("kN", &p); + _kphome = tgetstr("kh", &p); + _kpend = tgetstr("kH", &p); + _kpdel = tgetstr("kD", &p); + _kf1 = tgetstr("k1", &p); + _kf2 = tgetstr("k2", &p); + _kf3 = tgetstr("k3", &p); + _kf4 = tgetstr("k4", &p); + _kf5 = tgetstr("k5", &p); + _kf6 = tgetstr("k6", &p); + _kf7 = tgetstr("k7", &p); + _kf8 = tgetstr("k8", &p); + _kf9 = tgetstr("k9", &p); + if((_kf10 = tgetstr("k;", &p)) == NULL) + _kf10 = tgetstr("k0", &p); + _kf11 = tgetstr("F1", &p); + _kf12 = tgetstr("F2", &p); + + _colors = tgetnum("Co"); + _pairs = tgetnum("pa"); + _setaf = tgetstr("AF", &p); + _setab = tgetstr("AB", &p); + _setf = tgetstr("Sf", &p); + _setb = tgetstr("Sb", &p); + _scp = tgetstr("sp", &p); + _op = tgetstr("op", &p); + _oc = tgetstr("oc", &p); + _bce = tgetflag("ut"); + + if (p >= &tcapbuf[TCAPSLEN]){ + puts("Terminal description too big!\n"); + if(Pmaster) + return(-3); + else + exit(1); + } + + _tlines = tgetnum("li"); + if(_tlines == -1){ + char *er; + int rr; + + /* tgetnum failed, try $LINES */ + er = getenv("LINES"); + if(er && (rr = atoi(er)) > 0) + _tlines = rr; + } + + _tcolumns = tgetnum("co"); + if(_tcolumns == -1){ + char *ec; + int cc; + + /* tgetnum failed, try $COLUMNS */ + ec = getenv("COLUMNS"); + if(ec && (cc = atoi(ec)) > 0) + _tcolumns = cc; + } + + /* + * Add default keypad sequences to the trie. + * Since these come first, they will override any conflicting termcap + * or terminfo escape sequences defined below. An escape sequence is + * considered conflicting if one is a prefix of the other. + * So, without TERMCAP_WINS, there will likely be some termcap/terminfo + * escape sequences that don't work, because they conflict with default + * sequences defined here. + */ + if(!termcap_wins) + setup_dflt_esc_seq(); + + /* + * add termcap/info escape sequences to the trie... + */ + + if(_ku != NULL && _kd != NULL && _kl != NULL && _kr != NULL){ + kpinsert(_ku, KEY_UP, termcap_wins); + kpinsert(_kd, KEY_DOWN, termcap_wins); + kpinsert(_kl, KEY_LEFT, termcap_wins); + kpinsert(_kr, KEY_RIGHT, termcap_wins); + } + + if(_kppu != NULL && _kppd != NULL){ + kpinsert(_kppu, KEY_PGUP, termcap_wins); + kpinsert(_kppd, KEY_PGDN, termcap_wins); + } + + kpinsert(_kphome, KEY_HOME, termcap_wins); + kpinsert(_kpend, KEY_END, termcap_wins); + kpinsert(_kpdel, KEY_DEL, termcap_wins); + + kpinsert(_kf1, F1, termcap_wins); + kpinsert(_kf2, F2, termcap_wins); + kpinsert(_kf3, F3, termcap_wins); + kpinsert(_kf4, F4, termcap_wins); + kpinsert(_kf5, F5, termcap_wins); + kpinsert(_kf6, F6, termcap_wins); + kpinsert(_kf7, F7, termcap_wins); + kpinsert(_kf8, F8, termcap_wins); + kpinsert(_kf9, F9, termcap_wins); + kpinsert(_kf10, F10, termcap_wins); + kpinsert(_kf11, F11, termcap_wins); + kpinsert(_kf12, F12, termcap_wins); + + /* + * Add default keypad sequences to the trie. + * Since these come after the termcap/terminfo escape sequences above, + * the termcap/info sequences will override any conflicting default + * escape sequences defined here. + * So, with TERMCAP_WINS, some of the default sequences will be missing. + * This means that you'd better get all of your termcap/terminfo entries + * correct if you define TERMCAP_WINS. + */ + if(termcap_wins) + setup_dflt_esc_seq(); + + if(Pmaster) + return(0); + else + return(TRUE); +} + +static int +tcapopen() +{ + int row, col; + + /* + * determine the terminal's communication speed and decide + * if we need to do optimization ... + */ + optimize = ttisslow(); + + col = _tcolumns; + row = _tlines; + if(row >= 0) + row--; + + ttgetwinsz(&row, &col); + term.t_nrow = (short) row; + term.t_ncol = (short) col; + + eolexist = (_cleartoeoln != NULL); /* able to use clear to EOL? */ + revexist = (_setinverse != NULL); + if(_deletechar == NULL && (_startdelete == NULL || _enddelete == NULL)) + delchar = FALSE; + if(_insertchar == NULL && (_startinsert == NULL || _endinsert == NULL)) + inschar = FALSE; + if((_scrollregion == NULL || _scrolldown == NULL || _scrollup == NULL) + && (_deleteline == NULL || _insertline == NULL)) + scrollexist = FALSE; + + if(_clearscreen == NULL || _moveto == NULL || _up == NULL){ + if(Pmaster == NULL){ + puts("Incomplete termcap entry\n"); + exit(1); + } + } + + ttopen(); + + if(_termcap_init && !Pmaster) { + putpad(_termcap_init); /* any init termcap requires */ + if (_scrollregion) + putpad(tgoto(_scrollregion, term.t_nrow, 0)) ; + } + + /* + * Initialize UW-modified NCSA telnet to use it's functionkeys + */ + if(gmode&MDFKEY && Pmaster == NULL) + puts("\033[99h"); + + /* return ignored */ + return(0); +} + + +static int +tcapclose() +{ + if(!Pmaster){ + if(gmode&MDFKEY) + puts("\033[99l"); /* reset UW-NCSA telnet keys */ + + if(_termcap_end) /* any cleanup termcap requires */ + putpad(_termcap_end); + } + + ttclose(); + + /* return ignored */ + return(0); +} + + + +/* + * tcapinsert - insert a character at the current character position. + * _insertchar takes precedence. + */ +static void +tcapinsert(ch) +register int ch; +{ + if(_insertchar != NULL){ + putpad(_insertchar); + ttputc(ch); + } + else{ + putpad(_startinsert); + ttputc(ch); + putpad(_endinsert); + } +} + + +/* + * tcapdelete - delete a character at the current character position. + */ +static void +tcapdelete() +{ + if(_startdelete == NULL && _enddelete == NULL) + putpad(_deletechar); + else{ + putpad(_startdelete); + putpad(_deletechar); + putpad(_enddelete); + } +} + + +/* + * o_scrolldown - open a line at the given row position. + * use either region scrolling or deleteline/insertline + * to open a new line. + */ +o_scrolldown(row, n) +register int row; +register int n; +{ + register int i; + + if(_scrollregion != NULL){ + putpad(tgoto(_scrollregion, term.t_nrow - (term.t_mrow+1), row)); + tcapmove(row, 0); + for(i = 0; i < n; i++) + putpad( (_scrollup != NULL && *_scrollup != '\0') + ? _scrollup : "\n" ); + putpad(tgoto(_scrollregion, term.t_nrow, 0)); + tcapmove(row, 0); + } + else{ + /* + * this code causes a jiggly motion of the keymenu when scrolling + */ + for(i = 0; i < n; i++){ + tcapmove(term.t_nrow - (term.t_mrow+1), 0); + putpad(_deleteline); + tcapmove(row, 0); + putpad(_insertline); + } +#ifdef NOWIGGLYLINES + /* + * this code causes a sweeping motion up and down the display + */ + tcapmove(term.t_nrow - term.t_mrow - n, 0); + for(i = 0; i < n; i++) + putpad(_deleteline); + tcapmove(row, 0); + for(i = 0; i < n; i++) + putpad(_insertline); +#endif + } + + /* return ignored */ + return(0); +} + + +/* + * o_scrollup - open a line at the given row position. + * use either region scrolling or deleteline/insertline + * to open a new line. + */ +o_scrollup(row, n) +register int row; +register int n; +{ + register int i; + + if(_scrollregion != NULL){ + putpad(tgoto(_scrollregion, term.t_nrow - (term.t_mrow+1), row)); + /* setting scrolling region moves cursor to home */ + tcapmove(term.t_nrow-(term.t_mrow+1), 0); + for(i = 0;i < n; i++) + putpad((_scrolldown == NULL || _scrolldown[0] == '\0') + ? "\n" : _scrolldown); + putpad(tgoto(_scrollregion, term.t_nrow, 0)); + tcapmove(2, 0); + } + else{ + for(i = 0; i < n; i++){ + tcapmove(row, 0); + putpad(_deleteline); + tcapmove(term.t_nrow - (term.t_mrow+1), 0); + putpad(_insertline); + } +#ifdef NOWIGGLYLINES + /* see note above */ + tcapmove(row, 0); + for(i = 0; i < n; i++) + putpad(_deleteline); + tcapmove(term.t_nrow - term.t_mrow - n, 0); + for(i = 0;i < n; i++) + putpad(_insertline); +#endif + } + + /* return ignored */ + return(0); +} + + +/* + * o_insert - use termcap info to optimized character insert + * returns: true if it optimized output, false otherwise + */ +o_insert(c) +int c; +{ + if(inschar){ + tcapinsert(c); + return(1); /* no problems! */ + } + + return(0); /* can't do it. */ +} + + +/* + * o_delete - use termcap info to optimized character insert + * returns true if it optimized output, false otherwise + */ +o_delete() +{ + if(delchar){ + tcapdelete(); + return(1); /* deleted, no problem! */ + } + + return(0); /* no dice. */ +} + + +static int +tcapmove(row, col) +register int row, col; +{ + putpad(tgoto(_moveto, col, row)); + + /* return ignored */ + return(0); +} + + +static int +tcapeeol() +{ + int c, starting_col, starting_line; + char *last_bg_color; + + /* + * If the terminal doesn't have back color erase, then we have to + * erase manually to preserve the background color. + */ + if(pico_usingcolor() && (!_bce || !_cleartoeoln)){ + extern int ttcol, ttrow; + + starting_col = ttcol; + starting_line = ttrow; + last_bg_color = pico_get_last_bg_color(); + pico_set_nbg_color(); + for(c = ttcol; c < term.t_ncol; c++) + ttputc(' '); + + tcapmove(starting_line, starting_col); + if(last_bg_color){ + pico_set_bg_color(last_bg_color); + free(last_bg_color); + } + } + else if(_cleartoeoln) + putpad(_cleartoeoln); +} + + +static int +tcapeeop() +{ + int i, starting_col, starting_row; + + /* + * If the terminal doesn't have back color erase, then we have to + * erase manually to preserve the background color. + */ + if(pico_usingcolor() && (!_bce || !_cleartoeos)){ + extern int ttcol, ttrow; + + starting_col = ttcol; + starting_row = ttrow; + tcapeeol(); /* rest of this line */ + for(i = ttrow+1; i <= term.t_nrow; i++){ /* the remaining lines */ + tcapmove(i, 0); + tcapeeol(); + } + + tcapmove(starting_row, starting_col); + } + else if(_cleartoeos) + putpad(_cleartoeos); + + /* return ignored */ + return(0); +} + + +static int +tcaprev(state) /* change reverse video status */ +int state; /* FALSE = normal video, TRUE = reverse video */ +{ + if(state) + StartInverse(); + else + EndInverse(); + + return(1); +} + + +static int +tcapbeep() +{ + ttputc(BELL); + + /* return ignored */ + return(0); +} + + +static void +putpad(str) +char *str; +{ + tputs(str, 1, ttputc); +} + +#endif /* USE_TERMCAP */ + + diff --git a/osdep/term.dos b/osdep/term.dos new file mode 100644 index 0000000..2ec80d7 --- /dev/null +++ b/osdep/term.dos @@ -0,0 +1,648 @@ +/* + * + * $Id: term.dos 7884 1998-02-28 00:15:44Z hubert $ + * + * Program: IBM PC specific routine + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-1998 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ + +/* + * The routines in this file provide support for the IBM-PC and other + * compatible terminals. It goes directly to the graphics RAM to do + * screen output. It compiles into nothing if not an IBM-PC driver + */ + +#include +#if IBMPC +#define termdef 1 /* don't define "term" external */ + +int ibmmove PROTO((int, int)); +int ibmeeol PROTO((void)); +int ibmputc PROTO((int)); +int ibmoutc PROTO((char)); +int ibmeeop PROTO((void)); +int ibmrev PROTO((int)); +void beep PROTO((unsigned int, unsigned int)); +int cutebeep PROTO((void)); +int ibmbeep PROTO((void)); +int ibmopen PROTO((void)); +int ibmclose PROTO((void)); + + +#define MARGIN 8 /* size of minimim margin and */ +#define SCRSIZ 64 /* scroll size for extended lines */ +#define MROW 2 /* rows in menu */ + + +#define SET_COLOR(fore,back) ((((back) & 0xf) << 4) | ((fore) & 0xf)) + +int nfcolor = 7; /* current forground color */ +int nbcolor = 1; /* current background color */ +int rfcolor = 0; /* reverse forground color */ +int rbcolor = 3; /* reverse background color */ +unsigned cattr; /* current combined attribute */ + +/* + * Standard terminal interface dispatch table. Most of the fields point into + * "termio" code. + */ +TERM term = { + NROW-1, + NCOL, + MARGIN, + SCRSIZ, + MROW, + ibmopen, + NULL, + ibmclose, + ttgetc, + ibmputc, + ttflush, + ibmmove, + ibmeeol, + ibmeeop, + ibmbeep, + ibmrev +}; + + +#ifdef DOS +extern union REGS rg; +static unsigned display_mode; /* */ +#endif + + +static char *colist[] = { + "black", + "blue", + "green", + "cyan", + "red", + "magenta", + "yellow", + "white", + "BLACK", + "BLUE", + "GREEN", + "CYAN", + "RED", + "MAGENTA", + "YELLOW", + "WHITE" }; + +/* + * pico_setcolor - given the color name, return the color's value + */ +int +setcolor(s) +char *s; +{ + int i; + + for (i=0; i<16; i++) + if (!strcmp(colist[i],s)) + return(i); + + return(7); +} + + +/* + * pico_XXcolor() - each function sets a particular attribute + */ +pico_nfcolor(s) +char *s; +{ + nfcolor = setcolor(s); +} + +pico_nbcolor(s) +char *s; +{ + nbcolor = setcolor(s); +} + +pico_rfcolor(s) +char *s; +{ + rfcolor = setcolor(s); +} + +pico_rbcolor(s) +char *s; +{ + rbcolor = setcolor(s); +} + +#ifdef OS2 +static VIOMODEINFO display_mode; +static BYTE *oldscreen =NULL; +static USHORT origRow, origCol; +static USHORT origLen =0; +#ifdef FASTVIO +extern HMOU Mouse_Handle; +extern int mouse_state; +static int was_mouse_state=-1; +static int _moved=0, _line=0, _col=0; +static USHORT usVidbufLength =0; +static USHORT usRows =0, usCols =0; +static USHORT * pusVidBuffer =NULL; +static USHORT fCell=(USHORT)-1, + lCell=(USHORT)-1; + +static HEV hvUpdate =(HEV)0; +static HMTX hxUpdate =(HMTX)0; +static TID threadID; +static NOPTRRECT noptr = { 0, 0, (USHORT)-1, (USHORT)-1 }; + +static void update_thread(ULONG args) +{ + while (DosWaitEventSem(hvUpdate, -1)==0) { + DosResetEventSem(hvUpdate, &args); + if (fCell!=(USHORT)-1) { + DosRequestMutexSem(hxUpdate,-1); + if (was_mouse_state && Mouse_Handle!=(HMOU)-1) + MouRemovePtr(&noptr, Mouse_Handle); + /* Update the screen, if required */ + VioShowBuf(fCell*2,(lCell-fCell+1)*2, 0); + fCell=lCell=(USHORT)-1; + DosReleaseMutexSem(hxUpdate); + if (mouse_state && Mouse_Handle!=(HMOU)-1) + MouDrawPtr(Mouse_Handle); + } + else if (mouse_state != was_mouse_state && Mouse_Handle!=(HMOU)-1) { + if (mouse_state) + MouDrawPtr(Mouse_Handle); + else + MouRemovePtr(&noptr, Mouse_Handle); + } + was_mouse_state=mouse_state; + if (_moved) { + _moved=0; + VioSetCurPos((USHORT)_line,(USHORT)_col,0); + } + DosSleep(1); + } +} + +static void vidCell(USHORT row, USHORT col) +{ + USHORT cell=(row*usCols)+col; + + DosRequestMutexSem(hxUpdate,-1); + /* Always update first cell */ + if (fCell==(USHORT)-1) + fCell=lCell=cell; + else { + /* Otherwise stretch limits if necessary */ + if (celllCell) + lCell=cell; + } + DosReleaseMutexSem(hxUpdate); +} + +/* These seek to do minimal screen update + * by keeping track of the first and last + * cells written to the video buffer + */ + +void vidUpdate() +{ + if (hvUpdate == (HEV)0) { + VIOMODEINFO mi; + + DosCreateEventSem(NULL, &hvUpdate, 0, FALSE); + DosCreateMutexSem(NULL, &hxUpdate, 0, FALSE); + DosCreateThread(&threadID,update_thread,0,0,8192); + mi.cb = sizeof mi; + VioGetMode(&mi, 0); + noptr.cRow = mi.row-1; + noptr.cCol = mi.col-1; + } + DosPostEventSem(hvUpdate); +} + +static void vidArea(USHORT frow, USHORT fcol, USHORT lrow, USHORT lcol) +{ + vidCell(frow,fcol); + vidCell(lrow,lcol); +} +#endif +#endif + + +/* + * ibmmove - Use BIOS video services, function 2h to set cursor postion + */ +ibmmove(row, col) +int row, col; +{ +#ifdef OS2 +#ifdef FASTVIO + if (_line!=row || _col!=col) { + _line=row; + _col=col; + _moved=1; + } +#else + VioSetCurPos((USHORT)row, (USHORT)col, 0); +#endif +#else + rg.h.ah = 2; /* set cursor position function code */ + rg.h.bh = 0; /* set screen page number */ + rg.h.dl = col; + rg.h.dh = row; + int86(BIOS_VIDEO, &rg, &rg); +#endif +} + + +/* + * ibmeeol - erase to the end of the line + */ +ibmeeol() +{ +#ifdef OS2 + USHORT row, col; + BYTE chattr[2]; + chattr[0] = ' '; + chattr[1] = (BYTE)cattr; + +#ifdef FASTVIO + row=(USHORT)_line; + col=(USHORT)_col; + vidCell(row,col); + vidCell(row,usCols-1); + row=(row*usCols)+col; + col=usCols-col; + while(col--) + pusVidBuffer[row++] = *(USHORT *)chattr; +#else + /* find the current cursor position */ + VioGetCurPos(&row, &col, 0); + VioWrtNCell(chattr, NCOL-col, row, col, 0); +#endif +#else + int col, row, page; + + /* find the current cursor position */ + rg.h.ah = 3; /* read cursor position function code */ + int86(BIOS_VIDEO, &rg, &rg); + page = rg.h.bh; + col = rg.h.dl; /* record current column */ + row = rg.h.dh; /* and row */ + + rg.h.ah = 0x09; /* write char to screen with new attrs */ + rg.h.al = ' '; + rg.h.bl = cattr; + rg.h.bh = page; + rg.x.cx = NCOL-col; + int86(BIOS_VIDEO, &rg, &rg); +#endif +} + + +/* + * ibmputc - put a character at the current position in the + * current colors + */ +ibmputc(ch) +int ch; +{ +#ifdef OS2 + USHORT row, col; + + /* first, get current position */ +#ifdef FASTVIO + row=(USHORT)_line; + col=(USHORT)_col; +#else + VioGetCurPos(&row, &col, 0); +#endif + if (ch == '\b') { + if (col > 0) + ibmmove(row, --col); + } + else { + BYTE chattr[2]; + chattr[0]=(BYTE)ch; + chattr[1]=(BYTE)cattr; +#if FASTVIO + vidCell(row,col); + pusVidBuffer[(row*usCols)+col] = *(USHORT *)chattr; + if (col < usCols) +#else + VioWrtNCell(chattr, 1, row, col, 0); + if (col < NCOL) +#endif + ibmmove(row, ++col); + } +#else + int col, row, page; + + rg.h.ah = 0x03; /* first, get current position */ + int86(BIOS_VIDEO, &rg, &rg); + page = rg.h.bh; + row = rg.h.dh; + col = rg.h.dl; + + if(ch == '\b'){ + if(col > 0) /* advance the cursor */ + ibmmove(row, --col); + } + else{ + rg.h.ah = 0x09; /* write char to screen with new attrs */ + rg.h.al = ch; + rg.h.bl = cattr; /* inverting if needed */ + rg.h.bh = page; + rg.x.cx = 1; /* only once */ + int86(BIOS_VIDEO, &rg, &rg); + + if(col < 80) /* advance the cursor */ + ibmmove(row, ++col); + } +#endif +} + + +/* + * ibmgetc - output a single character with the right attributes, but + * don't advance the cursor + */ +ibmgetc(c) +char *c; +{ +#ifdef OS2 + /* first, get current position */ +#if FASTVIO + *c=(BYTE)pusVidBuffer[(_line*usCols)+_col]; +#else + USHORT row, col, n = 1; + + VioGetCurPos(&row, &col, 0); + VioReadCharStr(c, 1, &n, row, col, 0); +#endif +#else + rg.h.ah = 8; /* vid services, read char at cursor */ + rg.h.bh = 0; + int86(0x10, &rg, &rg); + *c = rg.h.al; +#endif +} + + +/* + * ibmeeop - clear from cursor to end of page + */ +ibmeeop() +{ +#ifdef OS2 +#if FASTVIO + USHORT atofs; +#endif + BYTE chattr[2]; + chattr[0] = ' '; + chattr[1] = (BYTE)cattr; + +#ifdef FASTVIO + vidArea(0,0,usRows-1,usCols-1); + for (atofs=0; atofs < usVidbufLength;++atofs) + pusVidBuffer[atofs] = *(USHORT *)chattr; +#else + VioScrollUp(0, 0, -1, -1, -1, chattr, 0); +#endif +#else + rg.h.ah = 6; /* scroll page up function code */ + rg.h.al = 0; /* # lines to scroll (clear it) */ + rg.x.cx = 0; /* upper left corner of scroll */ + rg.x.dx = (term.t_nrow << 8) | (term.t_ncol - 1); + rg.h.bh = cattr; + int86(BIOS_VIDEO, &rg, &rg); +#endif + ibmmove(0, 0); +} + + +/* + * ibmrev - change reverse video state + */ +ibmrev(state) +int state; +{ + cattr = (state) ? SET_COLOR(rfcolor, rbcolor) + : SET_COLOR(nfcolor, nbcolor); +} + + +/* + * getrevstate - return the current reverse state + */ +getrevstate() +{ + return(cattr == SET_COLOR(rfcolor, rbcolor)); +} + + +/* + * beep - make the speaker sing! + */ +void +beep(freq, dur) +unsigned freq, dur; +{ +#ifdef OS2 + if (freq) + DosBeep(freq, dur); +#else + unsigned oport; + + if(!freq) + return; + + freq = (unsigned)(1193180 / freq); + /* set up the timer */ + outp(0x43, 0xb6); /* set timer channel 2 registers */ + outp(0x42, (0xff&freq)); /* low order byte of count */ + outp(0x42, (freq>>8)); /* hi order byte of count */ + + /* make the sound */ + oport = inp(0x61); + outp(0x61, oport | 0x03); + ssleep((clock_t)((dur < 75) ? 75 : dur)); + outp(0x61, oport); +#endif +} + + +/* + * cutebeep - make the speeker sing the way we want! + */ +cutebeep() +{ + beep(575, 50); +#ifndef OS2 + ssleep((clock_t)25); +#endif + beep(485, 90); +} + + +/* + * ibmbeep - system beep... + */ +ibmbeep() +{ + cutebeep(); +} + + +/* + * enter_text_mode - get current video mode, saving to be restored + * later, then explicitly set 80 col text mode. + * + * NOTE: this gets kind of weird. Both pine and pico call this + * during initialization. To make sure it's only invoked once + * it only responds if passed NULL which pico only does if not + * called from in pine, and pine does all the time. make sense? + * thought not. + */ +void +enter_text_mode(p) +PICO *p; +{ +#ifdef OS2 + if (!p) { +#ifdef FASTVIO + ULONG pBuf; +#endif + display_mode.cb = sizeof display_mode; + VioGetMode(&display_mode, 0); + term.t_ncol = display_mode.col; + term.t_nrow = display_mode.row - 1; + origLen = display_mode.row * display_mode.col * sizeof(USHORT); + if (oldscreen) + free(oldscreen); + oldscreen = malloc(origLen); + if (oldscreen) + VioReadCellStr(oldscreen, &origLen, 0, 0, 0); + VioGetCurPos(&origRow, &origCol, 0); +#ifdef FASTVIO + _line=origRow; + _col=origCol; +#endif +#ifdef FASTVIO + usRows = display_mode.row; + usCols = display_mode.col; + VioGetBuf(&pBuf,&usVidbufLength,0); + pusVidBuffer = _emx_16to32((_far16ptr)pBuf); + /* OS2 2.1+ VIO bug (viobuf not initialised) workaround */ + memcpy(pusVidBuffer,oldscreen,usVidbufLength); + usVidbufLength /= 2; /* Cells, not bytes */ +#endif + } +#else + static int i = 0; + if(!p && !i++){ + rg.h.ah = 0x0f; /* save old mode */ + int86(BIOS_VIDEO, &rg, &rg); + display_mode = rg.h.al; + + rg.h.ah = 0; /* then set text mode */ + rg.h.al = 2; + int86(BIOS_VIDEO, &rg, &rg); /* video services */ + } +#endif +} + + +/* + * exit_text_mode - leave text mode by restoring saved original + * video mode. + */ +void +exit_text_mode(p) +PICO *p; +{ + +#ifdef OS2 + if (!p) { + turnmouseoff(); /* Make sure mouse is off while display is updated */ + VioSetMode(&display_mode, 0); + if (!oldscreen) + { + ibmeeop(); + VioSetCurPos(display_mode.row-1, 0, 0); + } + else + { + VioWrtCellStr(oldscreen, origLen, 0, 0, 0); + VioSetCurPos(origRow, origCol, 0); + } + } +#else + static int i = 0; + if(!p && !i++){ /* called many, invoke once! */ + rg.h.ah = 0; /* just restore old mode */ + rg.h.al = display_mode; + int86(BIOS_VIDEO, &rg, &rg); + } +#endif +} + + +/* + * ibmopen - setup text mode and setup key labels... + */ +ibmopen() +{ + + enter_text_mode(Pmaster); + + cattr = SET_COLOR(nfcolor, nbcolor); + revexist = TRUE; + inschar = delchar = 0; + + ttopen(); +} + + +ibmclose() +{ +#if COLOR + ibmfcol(7); + ibmbcol(0); +#endif +#ifdef MOUSE + mouseoff(); +#endif + exit_text_mode(Pmaster); + + ttclose(); +} +#endif + + diff --git a/osdep/term.inf b/osdep/term.inf new file mode 100644 index 0000000..2d90415 --- /dev/null +++ b/osdep/term.inf @@ -0,0 +1,751 @@ +/* + * Program: Display routines + * + * + * Donn Cave + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: donn@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2001 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* + * tinfo - substitute for tcap, on systems that have terminfo. + */ + +#define termdef 1 /* don't define "term" external */ + +#if defined(USE_TERMINFO) +extern char *tigetstr (); + +#define MARGIN 8 +#define SCRSIZ 64 +#define MROW 2 + +static int tinfomove PROTO((int, int)); +static int tinfoeeol PROTO((void)); +static int tinfoeeop PROTO((void)); +static int tinfobeep PROTO((void)); +static int tinforev PROTO((int)); +static int tinfoopen PROTO((void)); +static int tinfoterminalinfo PROTO((int)); +static int tinfoclose PROTO((void)); +static void setup_dflt_esc_seq PROTO((void)); +static void tinfoinsert PROTO((int)); +static void tinfodelete PROTO((void)); + +extern int tput(); + +/** + ** Note: The tgoto calls should really be replaced by tparm calls for + ** modern terminfo. tgoto(s, x, y) == tparm(s, y, x). + **/ + +int _tlines, _tcolumns; +char *_clearscreen, *_moveto, *_up, *_down, *_right, *_left, + *_setinverse, *_clearinverse, + *_setunderline, *_clearunderline, + *_setbold, *_clearallattr, /* there is no clear only bold! */ + *_cleartoeoln, *_cleartoeos, + *_deleteline, /* delete line */ + *_insertline, /* insert line */ + *_scrollregion, /* define a scrolling region, vt100 */ + *_insertchar, /* insert character, preferable to : */ + *_startinsert, /* set insert mode and, */ + *_endinsert, /* end insert mode */ + *_deletechar, /* delete character */ + *_startdelete, /* set delete mode and, */ + *_enddelete, /* end delete mode */ + *_scrolldown, /* scroll down */ + *_scrollup, /* scroll up */ + *_termcap_init, /* string to start termcap */ + *_termcap_end, /* string to end termcap */ + *_op, *_oc, *_setaf, *_setab, *_setf, *_setb, *_scp; +int _colors, _pairs, _bce; +char term_name[40]; + +TERM term = { + NROW-1, + NCOL, + MARGIN, + SCRSIZ, + MROW, + tinfoopen, + tinfoterminalinfo, + tinfoclose, + ttgetc, + ttputc, + ttflush, + tinfomove, + tinfoeeol, + tinfoeeop, + tinfobeep, + tinforev +}; + + +/* + * Add default keypad sequences to the trie. + */ +static void +setup_dflt_esc_seq() +{ + /* + * this is sort of a hack [no kidding], but it allows us to use + * the function keys on pc's running telnet + */ + + /* + * UW-NDC/UCS vt10[02] application mode. + */ + kpinsert("\033OP", F1, 1); + kpinsert("\033OQ", F2, 1); + kpinsert("\033OR", F3, 1); + kpinsert("\033OS", F4, 1); + kpinsert("\033Op", F5, 1); + kpinsert("\033Oq", F6, 1); + kpinsert("\033Or", F7, 1); + kpinsert("\033Os", F8, 1); + kpinsert("\033Ot", F9, 1); + kpinsert("\033Ou", F10, 1); + kpinsert("\033Ov", F11, 1); + kpinsert("\033Ow", F12, 1); + + /* + * DEC vt100, ANSI and cursor key mode. + */ + kpinsert("\033OA", KEY_UP, 1); + kpinsert("\033OB", KEY_DOWN, 1); + kpinsert("\033OC", KEY_RIGHT, 1); + kpinsert("\033OD", KEY_LEFT, 1); + + /* + * special keypad functions + */ + kpinsert("\033[4J", KEY_PGUP, 1); + kpinsert("\033[3J", KEY_PGDN, 1); + kpinsert("\033[2J", KEY_HOME, 1); + kpinsert("\033[N", KEY_END, 1); + + /* + * vt220? + */ + kpinsert("\033[5~", KEY_PGUP, 1); + kpinsert("\033[6~", KEY_PGDN, 1); + kpinsert("\033[1~", KEY_HOME, 1); + kpinsert("\033[4~", KEY_END, 1); + + /* + * konsole, XTerm (XFree 4.x.x) keyboard setting + */ + kpinsert("\033[H", KEY_HOME, 1); + kpinsert("\033[F", KEY_END, 1); + + /* + * gnome-terminal 2.6.0, don't know why it + * changed from 2.2.1 + */ + kpinsert("\033OH", KEY_HOME, 1); + kpinsert("\033OF", KEY_END, 1); + + /* + * "\033[2~" was common for KEY_HOME in a quick survey + * of terminals (though typically the Insert key). + * Teraterm 2.33 sends the following escape sequences, + * which is quite incompatible with everything + * else: + * Home: "\033[2~" End: "\033[5~" PgUp: "\033[3~" + * PgDn: "\033[6~" + * The best thing to do would be to fix TeraTerm + * keymappings or to tweak terminfo. + */ + + /* + * ANSI mode. + */ + kpinsert("\033[=a", F1, 1); + kpinsert("\033[=b", F2, 1); + kpinsert("\033[=c", F3, 1); + kpinsert("\033[=d", F4, 1); + kpinsert("\033[=e", F5, 1); + kpinsert("\033[=f", F6, 1); + kpinsert("\033[=g", F7, 1); + kpinsert("\033[=h", F8, 1); + kpinsert("\033[=i", F9, 1); + kpinsert("\033[=j", F10, 1); + kpinsert("\033[=k", F11, 1); + kpinsert("\033[=l", F12, 1); + + /* + * DEC vt100, ANSI and cursor key mode reset. + */ + kpinsert("\033[A", KEY_UP, 1); + kpinsert("\033[B", KEY_DOWN, 1); + kpinsert("\033[C", KEY_RIGHT, 1); + kpinsert("\033[D", KEY_LEFT, 1); + + /* + * DEC vt52 mode. + */ + kpinsert("\033A", KEY_UP, 1); + kpinsert("\033B", KEY_DOWN, 1); + kpinsert("\033C", KEY_RIGHT, 1); + kpinsert("\033D", KEY_LEFT, 1); + + /* + * DEC vt52 application keys, and some Zenith 19. + */ + kpinsert("\033?r", KEY_DOWN, 1); + kpinsert("\033?t", KEY_LEFT, 1); + kpinsert("\033?v", KEY_RIGHT, 1); + kpinsert("\033?x", KEY_UP, 1); + + /* + * Sun Console sequences. + */ + kpinsert("\033[1", KEY_SWALLOW_Z, 1); + kpinsert("\033[215", KEY_SWAL_UP, 1); + kpinsert("\033[217", KEY_SWAL_LEFT, 1); + kpinsert("\033[219", KEY_SWAL_RIGHT, 1); + kpinsert("\033[221", KEY_SWAL_DOWN, 1); + + /* + * Kermit App Prog Cmd, gobble until ESC \ (kermit should intercept this) + */ + kpinsert("\033_", KEY_KERMIT, 1); + + /* + * Fake a control character. + */ + kpinsert("\033\033", KEY_DOUBLE_ESC, 1); +} + + +static int +tinfoterminalinfo(termcap_wins) + int termcap_wins; +{ + char *_ku, *_kd, *_kl, *_kr, + *_kppu, *_kppd, *_kphome, *_kpend, *_kpdel, + *_kf1, *_kf2, *_kf3, *_kf4, *_kf5, *_kf6, + *_kf7, *_kf8, *_kf9, *_kf10, *_kf11, *_kf12; + char *ttnm; + + if (Pmaster) { + /* + * setupterm() automatically retrieves the value + * of the TERM variable. + */ + int err; + ttnm = getenv("TERM"); + if(!ttnm) + return(-1); + + strcpy(term_name, ttnm); + setupterm (0, 1, &err); + if (err != 1) return(err-2); + } + else { + /* + * setupterm() issues a message and exits, if the + * terminfo data base is gone or the term type is + * unknown, if arg2 is 0. + */ + setupterm (0, 1, 0); + } + + _clearscreen = tigetstr("clear"); + _moveto = tigetstr("cup"); + _up = tigetstr("cuu1"); + _down = tigetstr("cud1"); + _right = tigetstr("cuf1"); + _left = tigetstr("cub1"); + _setinverse = tigetstr("smso"); + _clearinverse = tigetstr("rmso"); + _setunderline = tigetstr("smul"); + _clearunderline = tigetstr("rmul"); + _setbold = tigetstr("bold"); + _clearallattr = tigetstr("sgr0"); + _cleartoeoln = tigetstr("el"); + _cleartoeos = tigetstr("ed"); + _deletechar = tigetstr("dch1"); + _insertchar = tigetstr("ich1"); + _startinsert = tigetstr("smir"); + _endinsert = tigetstr("rmir"); + _deleteline = tigetstr("dl1"); + _insertline = tigetstr("il1"); + _scrollregion = tigetstr("csr"); + _scrolldown = tigetstr("ind"); + _scrollup = tigetstr("ri"); + _termcap_init = tigetstr("smcup"); + _termcap_end = tigetstr("rmcup"); + _startdelete = tigetstr("smdc"); + _enddelete = tigetstr("rmdc"); + _ku = tigetstr("kcuu1"); + _kd = tigetstr("kcud1"); + _kl = tigetstr("kcub1"); + _kr = tigetstr("kcuf1"); + _kppu = tigetstr("kpp"); + _kppd = tigetstr("knp"); + _kphome = tigetstr("khome"); + _kpend = tigetstr("kend"); + _kpdel = tigetstr("kdch1"); + _kf1 = tigetstr("kf1"); + _kf2 = tigetstr("kf2"); + _kf3 = tigetstr("kf3"); + _kf4 = tigetstr("kf4"); + _kf5 = tigetstr("kf5"); + _kf6 = tigetstr("kf6"); + _kf7 = tigetstr("kf7"); + _kf8 = tigetstr("kf8"); + _kf9 = tigetstr("kf9"); + _kf10 = tigetstr("kf10"); + _kf11 = tigetstr("kf11"); + _kf12 = tigetstr("kf12"); + + _colors = tigetnum("colors"); + _pairs = tigetnum("pairs"); + _setaf = tigetstr("setaf"); + _setab = tigetstr("setab"); + _setf = tigetstr("setf"); + _setb = tigetstr("setb"); + _scp = tigetstr("scp"); + _op = tigetstr("op"); + _oc = tigetstr("oc"); + _bce = tigetflag("bce"); + + _tlines = tigetnum("lines"); + if(_tlines == -1){ + char *er; + int rr; + + /* tigetnum failed, try $LINES */ + er = getenv("LINES"); + if(er && (rr = atoi(er)) > 0) + _tlines = rr; + } + + _tcolumns = tigetnum("cols"); + if(_tcolumns == -1){ + char *ec; + int cc; + + /* tigetnum failed, try $COLUMNS */ + ec = getenv("COLUMNS"); + if(ec && (cc = atoi(ec)) > 0) + _tcolumns = cc; + } + + /* + * Add default keypad sequences to the trie. + * Since these come first, they will override any conflicting termcap + * or terminfo escape sequences defined below. An escape sequence is + * considered conflicting if one is a prefix of the other. + * So, without TERMCAP_WINS, there will likely be some termcap/terminfo + * escape sequences that don't work, because they conflict with default + * sequences defined here. + */ + if(!termcap_wins) + setup_dflt_esc_seq(); + + /* + * add termcap/info escape sequences to the trie... + */ + + if(_ku != NULL && _kd != NULL && _kl != NULL && _kr != NULL){ + kpinsert(_ku, KEY_UP, termcap_wins); + kpinsert(_kd, KEY_DOWN, termcap_wins); + kpinsert(_kl, KEY_LEFT, termcap_wins); + kpinsert(_kr, KEY_RIGHT, termcap_wins); + } + + if(_kppu != NULL && _kppd != NULL){ + kpinsert(_kppu, KEY_PGUP, termcap_wins); + kpinsert(_kppd, KEY_PGDN, termcap_wins); + } + + kpinsert(_kphome, KEY_HOME, termcap_wins); + kpinsert(_kpend, KEY_END, termcap_wins); + kpinsert(_kpdel, KEY_DEL, termcap_wins); + + kpinsert(_kf1, F1, termcap_wins); + kpinsert(_kf2, F2, termcap_wins); + kpinsert(_kf3, F3, termcap_wins); + kpinsert(_kf4, F4, termcap_wins); + kpinsert(_kf5, F5, termcap_wins); + kpinsert(_kf6, F6, termcap_wins); + kpinsert(_kf7, F7, termcap_wins); + kpinsert(_kf8, F8, termcap_wins); + kpinsert(_kf9, F9, termcap_wins); + kpinsert(_kf10, F10, termcap_wins); + kpinsert(_kf11, F11, termcap_wins); + kpinsert(_kf12, F12, termcap_wins); + + /* + * Add default keypad sequences to the trie. + * Since these come after the termcap/terminfo escape sequences above, + * the termcap/info sequences will override any conflicting default + * escape sequences defined here. + * So, with TERMCAP_WINS, some of the default sequences will be missing. + * This means that you'd better get all of your termcap/terminfo entries + * correct if you define TERMCAP_WINS. + */ + if(termcap_wins) + setup_dflt_esc_seq(); + + if(Pmaster) + return(0); + else + return(TRUE); +} + +static int +tinfoopen() +{ + int row, col; + + /* + * determine the terminal's communication speed and decide + * if we need to do optimization ... + */ + optimize = ttisslow(); + + col = _tcolumns; + row = _tlines; + if(row >= 0) + row--; + + ttgetwinsz(&row, &col); + term.t_nrow = (short) row; + term.t_ncol = (short) col; + + eolexist = (_cleartoeoln != NULL); /* able to use clear to EOL? */ + revexist = (_setinverse != NULL); + if(_deletechar == NULL && (_startdelete == NULL || _enddelete == NULL)) + delchar = FALSE; + if(_insertchar == NULL && (_startinsert == NULL || _endinsert == NULL)) + inschar = FALSE; + if((_scrollregion == NULL || _scrolldown == NULL || _scrollup == NULL) + && (_deleteline == NULL || _insertline == NULL)) + scrollexist = FALSE; + + if(_clearscreen == NULL || _moveto == NULL || _up == NULL){ + if(Pmaster == NULL){ + puts("Incomplete terminfo entry\n"); + exit(1); + } + } + + ttopen(); + + if(_termcap_init && !Pmaster) { + putpad(_termcap_init); /* any init terminfo requires */ + if (_scrollregion) + putpad(tgoto(_scrollregion, term.t_nrow, 0)) ; + } + + /* + * Initialize UW-modified NCSA telnet to use its functionkeys + */ + if(gmode&MDFKEY && Pmaster == NULL) + puts("\033[99h"); + + /* return ignored */ + return(0); +} + + +static tinfoclose() +{ + if(!Pmaster){ + if(gmode&MDFKEY) + puts("\033[99l"); /* reset UW-NCSA telnet keys */ + + if(_termcap_end) /* any clean up terminfo requires */ + putpad(_termcap_end); + } + + ttclose(); + + /* return ignored */ + return(0); +} + + +/* + * tinfoinsert - insert a character at the current character position. + * _insertchar takes precedence. + */ +static void +tinfoinsert(ch) +register int ch; +{ + if(_insertchar != NULL){ + putpad(_insertchar); + ttputc(ch); + } + else{ + putpad(_startinsert); + ttputc(ch); + putpad(_endinsert); + } +} + + +/* + * tinfodelete - delete a character at the current character position. + */ +static void +tinfodelete() +{ + if(_startdelete == NULL && _enddelete == NULL) + putpad(_deletechar); + else{ + putpad(_startdelete); + putpad(_deletechar); + putpad(_enddelete); + } +} + + +/* + * o_scrolldown() - open a line at the given row position. + * use either region scrolling or deleteline/insertline + * to open a new line. + */ +o_scrolldown(row, n) +register int row; +register int n; +{ + register int i; + + if(_scrollregion != NULL){ + putpad(tgoto(_scrollregion, term.t_nrow - (term.t_mrow+1), row)); + tinfomove(row, 0); + for(i = 0; i < n; i++) + putpad((_scrollup != NULL && *_scrollup != '\0') ? _scrollup : "\n" ); + putpad(tgoto(_scrollregion, term.t_nrow, 0)); + tinfomove(row, 0); + } + else{ + /* + * this code causes a jiggly motion of the keymenu when scrolling + */ + for(i = 0; i < n; i++){ + tinfomove(term.t_nrow - (term.t_mrow+1), 0); + putpad(_deleteline); + tinfomove(row, 0); + putpad(_insertline); + } +#ifdef NOWIGGLYLINES + /* + * this code causes a sweeping motion up and down the display + */ + tinfomove(term.t_nrow - term.t_mrow - n, 0); + for(i = 0; i < n; i++) + putpad(_deleteline); + tinfomove(row, 0); + for(i = 0; i < n; i++) + putpad(_insertline); +#endif + } + + /* return ignored */ + return(0); +} + + +/* + * o_scrollup() - open a line at the given row position. + * use either region scrolling or deleteline/insertline + * to open a new line. + */ +o_scrollup(row, n) +register int row; +register int n; +{ + register int i; + + if(_scrollregion != NULL){ + putpad(tgoto(_scrollregion, term.t_nrow - (term.t_mrow+1), row)); + /* setting scrolling region moves cursor to home */ + tinfomove(term.t_nrow-(term.t_mrow+1), 0); + for(i = 0;i < n; i++) + putpad((_scrolldown == NULL || _scrolldown[0] == '\0') ? "\n" + : _scrolldown); + putpad(tgoto(_scrollregion, term.t_nrow, 0)); + tinfomove(2, 0); + } + else{ + for(i = 0; i < n; i++){ + tinfomove(row, 0); + putpad(_deleteline); + tinfomove(term.t_nrow - (term.t_mrow+1), 0); + putpad(_insertline); + } +#ifdef NOWIGGLYLINES + /* see note above */ + tinfomove(row, 0); + for(i = 0; i < n; i++) + putpad(_deleteline); + tinfomove(term.t_nrow - term.t_mrow - n, 0); + for(i = 0;i < n; i++) + putpad(_insertline); +#endif + } + + /* return ignored */ + return(0); +} + + + +/* + * o_insert - use terminfo to optimized character insert + * returns: true if it optimized output, false otherwise + */ +o_insert(c) +int c; +{ + if(inschar){ + tinfoinsert(c); + return(1); /* no problems! */ + } + + return(0); /* can't do it. */ +} + + +/* + * o_delete - use terminfo to optimized character insert + * returns true if it optimized output, false otherwise + */ +o_delete() +{ + if(delchar){ + tinfodelete(); + return(1); /* deleted, no problem! */ + } + + return(0); /* no dice. */ +} + + +static tinfomove(row, col) +register int row, col; +{ + putpad(tgoto(_moveto, col, row)); + + /* return ignored */ + return(0); +} + + +static tinfoeeol() +{ + int c, starting_col, starting_line; + char *last_bg_color; + + /* + * If the terminal doesn't have back color erase, then we have to + * erase manually to preserve the background color. + */ + if(pico_usingcolor() && (!_bce || !_cleartoeoln)){ + extern int ttcol, ttrow; + + starting_col = ttcol; + starting_line = ttrow; + last_bg_color = pico_get_last_bg_color(); + pico_set_nbg_color(); + for(c = ttcol; c < term.t_ncol; c++) + ttputc(' '); + + tinfomove(starting_line, starting_col); + if(last_bg_color){ + pico_set_bg_color(last_bg_color); + free(last_bg_color); + } + } + else if(_cleartoeoln) + putpad(_cleartoeoln); + + /* return ignored */ + return(0); +} + + +static tinfoeeop() +{ + int i, starting_col, starting_row; + + /* + * If the terminal doesn't have back color erase, then we have to + * erase manually to preserve the background color. + */ + if(pico_usingcolor() && (!_bce || !_cleartoeos)){ + extern int ttcol, ttrow; + + starting_col = ttcol; + starting_row = ttrow; + tinfoeeol(); /* rest of this line */ + for(i = ttrow+1; i <= term.t_nrow; i++){ /* the remaining lines */ + tinfomove(i, 0); + tinfoeeol(); + } + + tinfomove(starting_row, starting_col); + } + else if(_cleartoeos) + putpad(_cleartoeos); + + /* return ignored */ + return(0); +} + + +static tinforev(state) /* change reverse video status */ +int state; /* FALSE = normal video, TRUE = rev video */ +{ + if(state) + StartInverse(); + else + EndInverse(); + + return(1); +} + + +static tinfobeep() +{ + ttputc(BELL); + + /* return ignored */ + return(0); +} + + +static void +putpad(str) +char *str; +{ + tputs(str, 1, ttputc); +} + +#endif /* USE_TERMINFO */ + + diff --git a/osdep/truncate b/osdep/truncate new file mode 100644 index 0000000..1bcf381 --- /dev/null +++ b/osdep/truncate @@ -0,0 +1,27 @@ +/* + * Tim Rice tim@trr.metro.net Mon Jun 3 16:57:26 PDT 1996 + * + * a quick and dirty trancate() + * Altos System V (5.3.1) does not have one + * neither does SCO Open Server Enterprise 3.0 + * + */ + +truncate(fn, size) +char *fn ; +long size ; +{ + int fdes; + int rc = -1 ; + + if((fdes = open(fn, O_RDWR)) != -1) + { + rc = chsize(fdes, size) ; + + if(close(fdes)) + return(-1) ; + } + return(rc) ; +} + + diff --git a/osdep/unix b/osdep/unix new file mode 100755 index 0000000..3b61f4d --- /dev/null +++ b/osdep/unix @@ -0,0 +1,4170 @@ +int timeo = 0; +time_t time_of_last_input; +int (*pcollator)(); + +#if defined(sv3) || defined(ct) +/* + * Windowing structure to support JWINSIZE/TIOCSWINSZ/TIOCGWINSZ + */ +#define ENAMETOOLONG 78 + +struct winsize { + unsigned short ws_row; /* rows, in characters*/ + unsigned short ws_col; /* columns, in character */ + unsigned short ws_xpixel; /* horizontal size, pixels */ + unsigned short ws_ypixel; /* vertical size, pixels */ +}; +#endif + +#ifdef SIGCHLD +static jmp_buf pico_child_state; +static short pico_child_jmp_ok, pico_child_done; +#endif + +#ifdef MOUSE +static int mexist = 0; /* is the mouse driver installed? */ +static unsigned mnoop; +#endif + +struct color_table { + char *name; + char *canonical_name; + int namelen; + char *rgb; + int val; +}; + +static unsigned color_options; +#define ANSI8_COLOR() (color_options & COLOR_ANSI8_OPT) +#define ANSI16_COLOR() (color_options & COLOR_ANSI16_OPT) +#define ANSI_COLOR() (color_options & (COLOR_ANSI8_OPT | COLOR_ANSI16_OPT)) +#define END_PSEUDO_REVERSE "EndInverse" +static COLOR_PAIR *the_rev_color, *the_normal_color; +static COLOR_PAIR *color_blasted_by_attrs; +static int pinvstate; /* physical state of inverse (standout) attribute */ +static int pboldstate; /* physical state of bold attribute */ +static int pulstate; /* physical state of underline attribute */ +static int rev_color_state; + +static int boldstate; /* should-be state of bold attribute */ +static int ulstate; /* should-be state of underline attribute */ +static int invstate; /* should-be state of Inverse, which could be a color + change or an actual setinverse */ +#define A_UNKNOWN -1 + + +void kpinsert PROTO((char *, int, int)); +void bail PROTO(()); +void flip_rev_color PROTO((int)); +void flip_bold PROTO((int)); +void flip_inv PROTO((int)); +void flip_ul PROTO((int)); +void reset_attr_state PROTO((void)); +SigType do_hup_signal SIG_PROTO((int)); +SigType rtfrmshell SIG_PROTO((int)); +int pathcat PROTO((char *, char **, char *)); +#ifdef RESIZING +SigType winch_handler SIG_PROTO((int)); +#endif +#ifdef SIGCHLD +SigType child_handler SIG_PROTO((int)); +#endif + +extern char *tgoto(); +#if defined(USE_TERMINFO) +extern char *tparm(); +#endif +static void putpad PROTO((char *)); +static void tinitcolor PROTO((void)); +static int tfgcolor PROTO((int)); +static int tbgcolor PROTO((int)); +static struct color_table *init_color_table PROTO((void)); +static void free_color_table PROTO((struct color_table **)); +static int color_to_val PROTO((char *)); + +extern char *_op, *_oc, *_setaf, *_setab, *_setf, *_setb, *_scp; +extern int _colors; +static int _color_inited, _using_color; +static char *_nfcolor, *_nbcolor, *_rfcolor, *_rbcolor; +static char *_last_fg_color, *_last_bg_color; +static int _force_fg_color_change; +static int _force_bg_color_change; + +static struct color_table *color_tbl; +static int dummy; + + +/* + * for alt_editor arg[] building + */ +#define MAXARGS 10 + +/* + * ttopen - this function is called once to set up the terminal device + * streams. if called as pine composer, don't mess with + * tty modes, but set signal handlers. + */ +ttopen() +{ + if(Pmaster == NULL){ + Raw(1); +#ifdef MOUSE + if(gmode & MDMOUSE) + init_mouse(); +#endif /* MOUSE */ + xonxoff_proc(preserve_start_stop); + } + + picosigs(); + + return(1); +} + + +/* + * ttresize - recompute the screen dimensions if necessary, and then + * adjust pico's internal buffers accordingly. + */ +void +ttresize () +{ + int row = -1, col = -1; + + ttgetwinsz(&row, &col); + resize_pico(row, col); +} + + +/* + * picosigs - Install any handlers for the signals we're interested + * in catching. + */ +void +picosigs() +{ + signal(SIGHUP, do_hup_signal); /* deal with SIGHUP */ + signal(SIGTERM, do_hup_signal); /* deal with SIGTERM */ +#ifdef SIGTSTP + signal(SIGTSTP, SIG_DFL); +#endif +#ifdef RESIZING + signal(SIGWINCH, winch_handler); /* window size changes */ +#endif +} + + +/* + * ttclose - this function gets called just before we go back home to + * the command interpreter. If called as pine composer, don't + * worry about modes, but set signals to default, pine will + * rewire things as needed. + */ +ttclose() +{ + if(Pmaster){ + signal(SIGHUP, SIG_DFL); +#ifdef SIGCONT + signal(SIGCONT, SIG_DFL); +#endif +#ifdef RESIZING + signal(SIGWINCH, SIG_DFL); +#endif + } + else{ + Raw(0); +#ifdef MOUSE + end_mouse(); +#endif + } + + return(1); +} + + +/* + * ttgetwinsz - set global row and column values (if we can get them) + * and return. + */ +void +ttgetwinsz(row, col) + int *row, *col; +{ + extern int _tlines, _tcolumns; + + if(*row < 0) + *row = (_tlines > 0) ? _tlines - 1 : NROW - 1; + if(*col <= 0) + *col = (_tcolumns > 0) ? _tcolumns : NCOL; +#ifdef RESIZING + { + struct winsize win; + + if (ioctl(0, TIOCGWINSZ, &win) == 0) { /* set to anything useful.. */ + if(win.ws_row) /* ... the tty drivers says */ + *row = win.ws_row - 1; + + if(win.ws_col) + *col = win.ws_col; + } + + signal(SIGWINCH, winch_handler); /* window size changes */ + } +#endif + + if(*col > NLINE-1) + *col = NLINE-1; +} + + +/* + * ttputc - Write a character to the display. + */ +ttputc(c) +{ + return(putc(c, stdout)); +} + + +/* + * ttflush - flush terminal buffer. Does real work where the terminal + * output is buffered up. A no-operation on systems where byte + * at a time terminal I/O is done. + */ +ttflush() +{ + return(fflush(stdout)); +} + + +/* + * ttgetc - Read a character from the terminal, performing no editing + * and doing no echo at all. + * + * Args: return_on_intr -- Function to get a single character from stdin, + * recorder -- If non-NULL, function used to record keystroke. + * bail_handler -- Function used to bail out on read error. + * + * Returns: The character read from stdin. + * Return_on_intr is returned if read is interrupted. + * If read error, BAIL_OUT is returned unless bail_handler is + * non-NULL, in which case it is called (and usually it exits). + * + * If recorder is non-null, it is used to record the keystroke. + */ +int +ttgetc(return_on_intr, recorder, bail_handler) + int return_on_intr; + int (*recorder) PROTO((int)); + void (*bail_handler)(); +{ + int c; + + switch(c = read_one_char()){ + case READ_INTR: + return(return_on_intr); + + case BAIL_OUT: + if(bail_handler) + (*bail_handler)(); + else + return(BAIL_OUT); + + default: + return(recorder ? (*recorder)(c) : c); + } +} + +/* + * Simple version of ttgetc with simple error handling + * + * Args: recorder -- If non-NULL, function used to record keystroke. + * bail_handler -- Function used to bail out on read error. + * + * Returns: The character read from stdin. + * If read error, BAIL_OUT is returned unless bail_handler is + * non-NULL, in which case it is called (and usually it exits). + * + * If recorder is non-null, it is used to record the keystroke. + * Retries if interrupted. + */ +int +simple_ttgetc(recorder, bail_handler) + int (*recorder) PROTO((int)); + void (*bail_handler)(); +{ + int res; + unsigned char c; + + while((res = read(STDIN_FD, &c, 1)) <= 0) + if(!(res < 0 && errno == EINTR)) + (*bail_handler)(); + + return(recorder ? (*recorder)((int)c) : (int)c); +} + +void +bail() +{ + sleep(30); /* see if os receives SIGHUP */ + kill(getpid(), SIGHUP); /* eof or bad error */ +} + + +#if TYPEAH +/* + * typahead - Check to see if any characters are already in the + * keyboard buffer + */ +typahead() +{ + int x; /* holds # of pending chars */ + + return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x); +} +#endif + + +/* + * ReadyForKey - return true if there's no timeout or we're told input + * is available... + */ +ReadyForKey(timeout) + int timeout; +{ + switch(input_ready(timeout)){ + case READY_TO_READ: + return(1); + break; + + case NO_OP_COMMAND: + case NO_OP_IDLE: + case READ_INTR: + return(0); + + case BAIL_OUT: + case PANIC_NOW: + emlwrite("\007Problem reading from keyboard!", NULL); + kill(getpid(), SIGHUP); /* Bomb out (saving our work)! */ + /* no return */ + } + + /* can't happen */ + return(0); +} + + +/* + * GetKey - Read in a key. + * Do the standard keyboard preprocessing. Convert the keys to the internal + * character set. Resolves escape sequences and returns no-op if global + * timeout value exceeded. + */ +GetKey() +{ + int ch, status, cc; + + if(!ReadyForKey(FUDGE-5)) + return(NODATA); + + switch(status = kbseq(simple_ttgetc, NULL, bail, &ch)){ + case 0: /* regular character */ + break; + + case KEY_DOUBLE_ESC: + /* + * Special hack to get around comm devices eating control characters. + */ + if(!ReadyForKey(5)) + return(BADESC); /* user typed ESC ESC, then stopped */ + else + ch = (*term.t_getchar)(NODATA, NULL, bail); + + ch &= 0x7f; + if(isdigit((unsigned char)ch)){ + int n = 0, i = ch - '0'; + + if(i < 0 || i > 2) + return(BADESC); /* bogus literal char value */ + + while(n++ < 2){ + if(!ReadyForKey(5) + || (!isdigit((unsigned char) (ch = + (*term.t_getchar)(NODATA, NULL, bail))) + || (n == 1 && i == 2 && ch > '5') + || (n == 2 && i == 25 && ch > '5'))){ + return(BADESC); + } + + i = (i * 10) + (ch - '0'); + } + + ch = i; + } + else{ + if(islower((unsigned char)ch)) /* canonicalize if alpha */ + ch = toupper((unsigned char)ch); + + return((isalpha((unsigned char)ch) || ch == '@' + || (ch >= '[' && ch <= '_')) + ? (CTRL | ch) : ((ch == ' ') ? (CTRL | '@') : ch)); + } + + break; + +#ifdef MOUSE + case KEY_XTERM_MOUSE: + { + /* + * Special hack to get mouse events from an xterm. + * Get the details, then pass it past the keymenu event + * handler, and then to the installed handler if there + * is one... + */ + static int down = 0; + int x, y, button; + unsigned cmd; + + button = (*term.t_getchar)(NODATA, NULL, bail) & 0x03; + + x = (*term.t_getchar)(NODATA, NULL, bail) - '!'; + y = (*term.t_getchar)(NODATA, NULL, bail) - '!'; + + if(button == 0){ + down = 1; + if(checkmouse(&cmd, 1, x, y)) + return((int)cmd); + } + else if(down && button == 3){ + down = 0; + if(checkmouse(&cmd, 0, x, y)) + return((int)cmd); + } + + return(NODATA); + } + + break; +#endif /* MOUSE */ + + case KEY_UP : + case KEY_DOWN : + case KEY_RIGHT : + case KEY_LEFT : + case KEY_PGUP : + case KEY_PGDN : + case KEY_HOME : + case KEY_END : + case KEY_DEL : + case F1 : + case F2 : + case F3 : + case F4 : + case F5 : + case F6 : + case F7 : + case F8 : + case F9 : + case F10 : + case F11 : + case F12 : + return(status); + + case KEY_SWALLOW_Z: + status = BADESC; + case KEY_SWAL_UP: + case KEY_SWAL_DOWN: + case KEY_SWAL_LEFT: + case KEY_SWAL_RIGHT: + do + if(!ReadyForKey(2)){ + status = BADESC; + break; + } + while(!strchr("~qz", (*term.t_getchar)(NODATA, NULL, bail))); + + return((status == BADESC) + ? status + : status - (KEY_SWAL_UP - KEY_UP)); + break; + + case KEY_KERMIT: + do{ + cc = ch; + if(!ReadyForKey(2)) + return(BADESC); + else + ch = (*term.t_getchar)(NODATA, NULL, bail) & 0x7f; + }while(cc != '\033' && ch != '\\'); + + ch = NODATA; + break; + + case BADESC: + (*term.t_beep)(); + return(status); + + default: /* punt the whole thing */ + (*term.t_beep)(); + break; + } + + if(ch & 0x80 && Pmaster && Pmaster->hibit_entered) + *Pmaster->hibit_entered = 1; + + if (ch >= 0x00 && ch <= 0x1F) /* C0 control -> C- */ + ch = CTRL | (ch+'@'); + + return(ch); +} + + + +/* + * kbseq - looks at an escape sequence coming from the keyboard and + * compares it to a trie of known keyboard escape sequences, and + * returns the function bound to the escape sequence. + * + * Args: getcfunc -- Function to get a single character from stdin, + * called with the next two arguments to this + * function as its arguments. + * recorder -- If non-NULL, function used to record keystroke. + * bail_handler -- Function used to bail out on read error. + * c -- Pointer to returned character. + * + * Returns: BADESC + * The escaped function. + * 0 if a regular char with char stuffed in location c. + */ +kbseq(getcfunc, recorder, bail_handler, c) + int (*getcfunc)(); + int (*recorder)(); + void (*bail_handler)(); + int *c; +{ + register char b; + register int first = 1; + register KBESC_T *current; + + current = kbesc; + if(current == NULL) /* bag it */ + return(BADESC); + + while(1){ + b = *c = (*getcfunc)(recorder, bail_handler); + + while(current->value != b){ + if(current->left == NULL){ /* NO MATCH */ + if(first) + return(0); /* regular char */ + else + return(BADESC); + } + current = current->left; + } + + if(current->down == NULL) /* match!!!*/ + return(current->func); + else + current = current->down; + + first = 0; + } +} + + +#define newnode() (KBESC_T *)malloc(sizeof(KBESC_T)) +/* + * kpinsert - insert a keystroke escape sequence into the global search + * structure. + */ +void +kpinsert(kstr, kval, termcap_wins) + char *kstr; + int kval; + int termcap_wins; +{ + register char *buf; + register KBESC_T *temp; + register KBESC_T *trail; + + if(kstr == NULL) + return; + + /* + * Don't allow escape sequences that don't start with ESC unless + * termcap_wins. This is to protect against mistakes in termcap files. + */ + if(!termcap_wins && *kstr != '\033') + return; + + temp = trail = kbesc; + buf = kstr; + + for(;;){ + if(temp == NULL){ + temp = newnode(); + temp->value = *buf; + temp->func = 0; + temp->left = NULL; + temp->down = NULL; + if(kbesc == NULL) + kbesc = temp; + else + trail->down = temp; + } + else{ /* first entry */ + while((temp != NULL) && (temp->value != *buf)){ + trail = temp; + temp = temp->left; + } + + if(temp == NULL){ /* add new val */ + temp = newnode(); + temp->value = *buf; + temp->func = 0; + temp->left = NULL; + temp->down = NULL; + trail->left = temp; + } + } + + if(*(++buf) == '\0') + break; + else{ + /* + * Ignore attempt to overwrite shorter existing escape sequence. + * That means that sequences with higher priority should be + * set up first, so if we want termcap sequences to override + * hardwired sequences, put the kpinsert calls for the + * termcap sequences first. (That's what you get if you define + * TERMCAP_WINS.) + */ + if(temp->func != 0) + return; + + trail = temp; + temp = temp->down; + } + } + + /* + * Ignore attempt to overwrite longer sequences we are a prefix + * of (down != NULL) and exact same sequence (func != 0). + */ + if(temp != NULL && temp->down == NULL && temp->func == 0) + temp->func = kval; +} + + + +/* + * kbdestroy() - kills the key pad function key search tree + * and frees all lines associated with it + * + * Should be called with arg kbesc, the top of the tree. + */ +void +kbdestroy(kb) + KBESC_T *kb; +{ + if(kb){ + kbdestroy(kb->left); + kbdestroy(kb->down); + free((char *)kb); + kb = NULL; + } +} + + +/* + * Start or end bold mode + * + * Result: escape sequence to go into or out of reverse color is output + * + * (This is only called when there is a reverse color.) + * + * Arg state = ON set bold + * OFF set normal + */ +void +flip_rev_color(state) + int state; +{ + if((rev_color_state = state) == TRUE) + (void)pico_set_colorp(the_rev_color, PSC_NONE); + else + pico_set_normal_color(); +} + + +/* + * Start or end bold mode + * + * Result: escape sequence to go into or out of bold is output + * + * Arg state = ON set bold + * OFF set normal + */ +void +flip_bold(state) + int state; +{ + extern char *_setbold, *_clearallattr; + + if((pboldstate = state) == TRUE){ + if(_setbold != NULL) + putpad(_setbold); + } + else{ + if(_clearallattr != NULL){ + if(!color_blasted_by_attrs) + color_blasted_by_attrs = pico_get_cur_color(); + + _force_fg_color_change = _force_bg_color_change = 1; + putpad(_clearallattr); + pinvstate = state; + pulstate = state; + rev_color_state = state; + } + } +} + + +/* + * Start or end inverse mode + * + * Result: escape sequence to go into or out of inverse is output + * + * Arg state = ON set inverse + * OFF set normal + */ +void +flip_inv(state) + int state; +{ + extern char *_setinverse, *_clearinverse; + + if((pinvstate = state) == TRUE){ + if(_setinverse != NULL) + putpad(_setinverse); + } + else{ + /* + * Unfortunately, some termcap entries configure end standout to + * be clear all attributes. + */ + if(_clearinverse != NULL){ + if(!color_blasted_by_attrs) + color_blasted_by_attrs = pico_get_cur_color(); + + _force_fg_color_change = _force_bg_color_change = 1; + putpad(_clearinverse); + pboldstate = (pboldstate == FALSE) ? pboldstate : A_UNKNOWN; + pulstate = (pulstate == FALSE) ? pulstate : A_UNKNOWN; + rev_color_state = A_UNKNOWN; + } + } +} + + +/* + * Start or end underline mode + * + * Result: escape sequence to go into or out of underline is output + * + * Arg state = ON set underline + * OFF set normal + */ +void +flip_ul(state) + int state; +{ + extern char *_setunderline, *_clearunderline; + + if((pulstate = state) == TRUE){ + if(_setunderline != NULL) + putpad(_setunderline); + } + else{ + /* + * Unfortunately, some termcap entries configure end underline to + * be clear all attributes. + */ + if(_clearunderline != NULL){ + if(!color_blasted_by_attrs) + color_blasted_by_attrs = pico_get_cur_color(); + + _force_fg_color_change = _force_bg_color_change = 1; + putpad(_clearunderline); + pboldstate = (pboldstate == FALSE) ? pboldstate : A_UNKNOWN; + pinvstate = (pinvstate == FALSE) ? pinvstate : A_UNKNOWN; + rev_color_state = A_UNKNOWN; + } + } +} + +void +StartInverse() +{ + invstate = TRUE; + reset_attr_state(); +} + + +void +EndInverse() +{ + invstate = FALSE; + reset_attr_state(); +} + + +int +InverseState() +{ + return(invstate); +} + +int +StartBold() +{ + extern char *_setbold; + + boldstate = TRUE; + reset_attr_state(); + return(_setbold != NULL); +} + +void +EndBold() +{ + boldstate = FALSE; + reset_attr_state(); +} + +void +StartUnderline() +{ + ulstate = TRUE; + reset_attr_state(); +} + +void +EndUnderline() +{ + ulstate = FALSE; + reset_attr_state(); +} + +void +reset_attr_state() +{ + /* + * If we have to turn some attributes off, do that first since that + * may turn off other attributes as a side effect. + */ + if(boldstate == FALSE && pboldstate != boldstate) + flip_bold(boldstate); + + if(ulstate == FALSE && pulstate != ulstate) + flip_ul(ulstate); + + if(invstate == FALSE){ + if(pico_get_rev_color()){ + if(rev_color_state != invstate) + flip_rev_color(invstate); + } + else{ + if(pinvstate != invstate) + flip_inv(invstate); + } + } + + /* + * Now turn everything on that needs turning on. + */ + if(boldstate == TRUE && pboldstate != boldstate) + flip_bold(boldstate); + + if(ulstate == TRUE && pulstate != ulstate) + flip_ul(ulstate); + + if(invstate == TRUE){ + if(pico_get_rev_color()){ + if(rev_color_state != invstate) + flip_rev_color(invstate); + } + else{ + if(pinvstate != invstate) + flip_inv(invstate); + } + } + + if(color_blasted_by_attrs){ + (void)pico_set_colorp(color_blasted_by_attrs, PSC_NONE); + free_color_pair(&color_blasted_by_attrs); + } + +} + + +static void +tinitcolor() +{ + if(_color_inited || panicking) + return; + + if(ANSI_COLOR() || (_colors > 0 && ((_setaf && _setab) || (_setf && _setb) +/**** not sure how to do this yet + || _scp +****/ + ))){ + _color_inited = 1; + color_tbl = init_color_table(); + + if(ANSI_COLOR()) + putpad("\033[39;49m"); + else{ + if(_op) + putpad(_op); + if(_oc) + putpad(_oc); + } + } +} + + +#if defined(USE_TERMCAP) +/* + * Treading on thin ice here. Tgoto wasn't designed for this. It takes + * arguments column and row. We only use one of them, so we put it in + * the row argument. The 0 is just a placeholder. + */ +#define tparm(s, c) tgoto(s, 0, c) +#endif + +static int +tfgcolor(color) + int color; +{ + if(!_color_inited) + tinitcolor(); + + if(!_color_inited) + return(-1); + + if((ANSI8_COLOR() && (color < 0 || color >= 8)) || + (ANSI16_COLOR() && (color < 0 || color >= 16)) || + (!ANSI_COLOR() && (color < 0 || color >= _colors))) + return(-1); + + if(ANSI_COLOR()){ + char buf[10]; + + if(color < 8) + sprintf(buf, "\033[3%cm", color + '0'); + else + sprintf(buf, "\033[9%cm", (color-8) + '0'); + + putpad(buf); + } + else if(_setaf) + putpad(tparm(_setaf, color)); + else if(_setf) + putpad(tparm(_setf, color)); + else if(_scp){ + /* set color pair method */ + } + + return(0); +} + + +static int +tbgcolor(color) + int color; +{ + if(!_color_inited) + tinitcolor(); + + if(!_color_inited) + return(-1); + + if((ANSI8_COLOR() && (color < 0 || color >= 8)) || + (ANSI16_COLOR() && (color < 0 || color >= 16)) || + (!ANSI_COLOR() && (color < 0 || color >= _colors))) + return(-1); + + if(ANSI_COLOR()){ + char buf[10]; + + if(color < 8) + sprintf(buf, "\033[4%cm", color + '0'); + else + sprintf(buf, "\033[10%cm", (color-8) + '0'); + + putpad(buf); + } + else if(_setab) + putpad(tparm(_setab, color)); + else if(_setb) + putpad(tparm(_setb, color)); + else if(_scp){ + /* set color pair method */ + } + + return(0); +} + + + +/* + * We're not actually using the RGB value other than as a string which + * maps into the color. + * In fact, on some systems color 1 and color 4 are swapped, and color 3 + * and color 6 are swapped. So don't believe the RGB values. + * Still, it feels right to have them be the canonical values, so we do that. + * + * More than one "name" can map to the same "canonical_name". + * More than one "name" can map to the same "val". + * The "val" for a "name" and for its "canonical_name" are the same. + */ +static struct color_table * +init_color_table() +{ + struct color_table *ct = NULL, *t; + int i, size, count; + char colorname[12]; + + count = pico_count_in_color_table(); + + /* + * Special case: If table is of size 8 we use a table of size 16 instead + * and map the 2nd eight into the first 8 so that both 8 and 16 color + * terminals can be used with the same pinerc and colors in the 2nd + * 8 may be useful. We could make this more general and always map + * colors larger than our current # of colors by mapping it modulo + * the color table size. The only problem with this is that it would + * take a boatload of programming to convert what we have now into that, + * and it is highly likely that no one would ever use anything other + * than the 8/16 case. So we'll stick with that special case for now. + */ + if(count == 8) + size = 16; + else + size = count; + + if(size > 0 && size < 256){ + ct = (struct color_table *)malloc((size+1)*sizeof(struct color_table)); + if(ct) + memset(ct, 0, (size+1) * sizeof(struct color_table)); + + for(i = 0, t = ct; t && i < size; i++, t++){ + t->val = i % count; + + switch(i){ + case COL_BLACK: + strcpy(colorname, "black"); + break; + case COL_RED: + strcpy(colorname, "red"); + break; + case COL_GREEN: + strcpy(colorname, "green"); + break; + case COL_YELLOW: + strcpy(colorname, "yellow"); + break; + case COL_BLUE: + strcpy(colorname, "blue"); + break; + case COL_MAGENTA: + strcpy(colorname, "magenta"); + break; + case COL_CYAN: + strcpy(colorname, "cyan"); + break; + case COL_WHITE: + strcpy(colorname, "white"); + break; + default: + sprintf(colorname, "color%03.3d", i); + break; + } + + t->namelen = strlen(colorname); + t->name = (char *)malloc((t->namelen+1) * sizeof(char)); + if(t->name) + strcpy(t->name, colorname); + + /* + * For an 8 color terminal, canonical black == black, but + * canonical red == color009, etc. + * + * This is weird. What we have is 16-color xterms where color 0 + * is black (fine, that matches) colors 1 - 7 are called + * red, ..., white but they are set at 2/3rds brightness so that + * bold can be brighter. Those 7 colors suck. Color 8 is some + * sort of gray, colors 9 - 15 are real red, ..., white. On other + * 8 color terminals and in PC-Pine, we want to equate color 0 + * with color 0 on 16-color, but color 1 (red) is really the + * same as the 16-color color 9. So color 9 - 15 are the real + * colors on a 16-color terminal and colors 1 - 7 are the real + * colors on an 8-color terminal. We make that work by mapping + * the 2nd eight into the first eight when displaying on an + * 8-color terminal, and by using the canonical_name when + * we modify and write out a color. The canonical name is set + * to the "real* color (0, 9, 10, ..., 15 on 16-color terminal). + */ + if(size == count || i == 0 || i > 7){ + t->canonical_name = (char *)malloc((t->namelen+1)*sizeof(char)); + strcpy(t->canonical_name, colorname); + } + else{ + t->canonical_name = (char *)malloc(9*sizeof(char)); + sprintf(t->canonical_name, "color%03.3d", i+8); + } + + t->rgb = (char *)malloc((RGBLEN+1) * sizeof(char)); + if(t->rgb){ + if(count == 8){ + switch(i){ + case COL_BLACK: + case 8: + strcpy(t->rgb, "000,000,000"); + break; + case COL_RED: + case 9: + strcpy(t->rgb, "255,000,000"); + break; + case COL_GREEN: + case 10: + strcpy(t->rgb, "000,255,000"); + break; + case COL_YELLOW: + case 11: + strcpy(t->rgb, "255,255,000"); + break; + case COL_BLUE: + case 12: + strcpy(t->rgb, "000,000,255"); + break; + case COL_MAGENTA: + case 13: + strcpy(t->rgb, "255,000,255"); + break; + case COL_CYAN: + case 14: + strcpy(t->rgb, "000,255,255"); + break; + case COL_WHITE: + case 15: + strcpy(t->rgb, "255,255,255"); + break; + default: + /* + * These aren't really used as RGB values, just as + * strings for the lookup. We don't know how to + * convert to any RGB, we just know how to output + * the escape sequences. So it doesn't matter that + * the numbers in the sprintf below are too big. + * We are using the fact that all rgb values start with + * a digit or space and color names don't in the lookup + * routines below. + */ + sprintf(t->rgb, "%d,%d,%d", 256+i, 256+i, 256+i); + break; + } + } + else if(count == 16){ + /* + * This set of RGB values seems to come close to describing + * what a 16-color xterm gives you. + */ + switch(i){ + case COL_BLACK: + strcpy(t->rgb, "000,000,000"); + break; + case COL_RED: /* actually dark red */ + strcpy(t->rgb, "174,000,000"); + break; + case COL_GREEN: /* actually dark green */ + strcpy(t->rgb, "000,174,000"); + break; + case COL_YELLOW: /* actually dark yellow */ + strcpy(t->rgb, "174,174,000"); + break; + case COL_BLUE: /* actually dark blue */ + strcpy(t->rgb, "000,000,174"); + break; + case COL_MAGENTA: /* actually dark magenta */ + strcpy(t->rgb, "174,000,174"); + break; + case COL_CYAN: /* actually dark cyan */ + strcpy(t->rgb, "000,174,174"); + break; + case COL_WHITE: /* actually light gray */ + strcpy(t->rgb, "174,174,174"); + break; + case 8: /* dark gray */ + strcpy(t->rgb, "064,064,064"); + break; + case 9: /* red */ + strcpy(t->rgb, "255,000,000"); + break; + case 10: /* green */ + strcpy(t->rgb, "000,255,000"); + break; + case 11: /* yellow */ + strcpy(t->rgb, "255,255,000"); + break; + case 12: /* blue */ + strcpy(t->rgb, "000,000,255"); + break; + case 13: /* magenta */ + strcpy(t->rgb, "255,000,255"); + break; + case 14: /* cyan */ + strcpy(t->rgb, "000,255,255"); + break; + case 15: /* white */ + strcpy(t->rgb, "255,255,255"); + break; + default: + sprintf(t->rgb, "%d,%d,%d", 256+i, 256+i, 256+i); + break; + } + } + else{ + switch(i){ + case COL_BLACK: + strcpy(t->rgb, "000,000,000"); + break; + case COL_RED: + strcpy(t->rgb, "255,000,000"); + break; + case COL_GREEN: + strcpy(t->rgb, "000,255,000"); + break; + case COL_YELLOW: + strcpy(t->rgb, "255,255,000"); + break; + case COL_BLUE: + strcpy(t->rgb, "000,000,255"); + break; + case COL_MAGENTA: + strcpy(t->rgb, "255,000,255"); + break; + case COL_CYAN: + strcpy(t->rgb, "000,255,255"); + break; + case COL_WHITE: + strcpy(t->rgb, "255,255,255"); + break; + default: + sprintf(t->rgb, "%d,%d,%d", 256+i, 256+i, 256+i); + break; + } + } + } + } + } + + return(ct); +} + + +/* + * Map from integer color value to canonical color name. + */ +char * +colorx(color) + int color; +{ + struct color_table *ct; + static char cbuf[12]; + + /* before we get set up, we still need to use this a bit */ + if(!color_tbl){ + switch(color){ + case COL_BLACK: + return("black"); + case COL_RED: + return("red"); + case COL_GREEN: + return("green"); + case COL_YELLOW: + return("yellow"); + case COL_BLUE: + return("blue"); + case COL_MAGENTA: + return("magenta"); + case COL_CYAN: + return("cyan"); + case COL_WHITE: + return("white"); + default: + sprintf(cbuf, "color%03.3d", color); + return(cbuf); + } + } + + for(ct = color_tbl; ct->name; ct++) + if(ct->val == color) + break; + + if(ct->name) + return(ct->canonical_name); + + /* not supposed to get here */ + sprintf(cbuf, "color%03.3d", color); + return(cbuf); +} + + +/* + * Argument is a color name which could be an RGB string, a name like "blue", + * or a name like "color011". + * + * Returns a pointer to the canonical name of the color. + */ +char * +color_to_canonical_name(s) + char *s; +{ + struct color_table *ct; + + if(!s || !color_tbl) + return(NULL); + + if(*s == ' ' || isdigit(*s)){ + /* check for rgb string instead of name */ + for(ct = color_tbl; ct->rgb; ct++) + if(!strncmp(ct->rgb, s, RGBLEN)) + break; + } + else{ + for(ct = color_tbl; ct->name; ct++) + if(!struncmp(ct->name, s, ct->namelen)) + break; + } + + if(ct->name) + return(ct->canonical_name); + + return(""); +} + + +/* + * Argument is the name of a color or an RGB value that we recognize. + * The table should be set up so that the val returned is the same whether + * or not we choose the canonical name. + * + * Returns the integer value for the color. + */ +static int +color_to_val(s) + char *s; +{ + struct color_table *ct; + + if(!s || !color_tbl) + return(-1); + + if(*s == ' ' || isdigit(*s)){ + /* check for rgb string instead of name */ + for(ct = color_tbl; ct->rgb; ct++) + if(!strncmp(ct->rgb, s, RGBLEN)) + break; + } + else{ + for(ct = color_tbl; ct->name; ct++) + if(!struncmp(ct->name, s, ct->namelen)) + break; + } + + if(ct->name) + return(ct->val); + else + return(-1); +} + + +static void +free_color_table(ctbl) + struct color_table **ctbl; +{ + struct color_table *t; + + if(ctbl && *ctbl){ + for(t = *ctbl; t->name; t++){ + if(t->name){ + free(t->name); + t->name = NULL; + } + + if(t->canonical_name){ + free(t->canonical_name); + t->canonical_name = NULL; + } + + if(t->rgb){ + free(t->rgb); + t->rgb = NULL; + } + } + + free(*ctbl); + *ctbl = NULL; + } +} + + +int +pico_count_in_color_table() +{ + return(ANSI8_COLOR() ? 8 : ANSI16_COLOR() ? 16 : _colors); +} + + +void +pico_nfcolor(s) + char *s; +{ + if(_nfcolor){ + free(_nfcolor); + _nfcolor = NULL; + } + + if(s){ + _nfcolor = (char *)malloc(strlen(s)+1); + if(_nfcolor) + strcpy(_nfcolor, s); + + if(the_normal_color) + strcpy(the_normal_color->fg, _nfcolor); + } + else if(the_normal_color) + free_color_pair(&the_normal_color); +} + + +void +pico_nbcolor(s) + char *s; +{ + if(_nbcolor){ + free(_nbcolor); + _nbcolor = NULL; + } + + if(s){ + _nbcolor = (char *)malloc(strlen(s)+1); + if(_nbcolor) + strcpy(_nbcolor, s); + + if(the_normal_color) + strcpy(the_normal_color->bg, _nbcolor); + } + else if(the_normal_color) + free_color_pair(&the_normal_color); +} + +void +pico_rfcolor(s) + char *s; +{ + if(_rfcolor){ + free(_rfcolor); + _rfcolor = NULL; + } + + if(s){ + _rfcolor = (char *)malloc(strlen(s)+1); + if(_rfcolor) + strcpy(_rfcolor, s); + + if(the_rev_color) + strcpy(the_rev_color->fg, _rfcolor); + } + else if(the_rev_color) + free_color_pair(&the_rev_color); +} + +void +pico_rbcolor(s) + char *s; +{ + if(_rbcolor){ + free(_rbcolor); + _rbcolor = NULL; + } + + if(s){ + _rbcolor = (char *)malloc(strlen(s)+1); + if(_rbcolor) + strcpy(_rbcolor, s); + + if(the_rev_color) + strcpy(the_rev_color->bg, _rbcolor); + } + else if(the_rev_color) + free_color_pair(&the_rev_color); +} + +int +pico_hascolor() +{ + if(!_color_inited) + tinitcolor(); + + return(_color_inited); +} + +int +pico_usingcolor() +{ + return(_using_color && pico_hascolor()); +} + +void +pico_toggle_color(on) + int on; +{ + if(on){ + if(pico_hascolor()) + _using_color = 1; + } + else{ + _using_color = 0; + if(_color_inited){ + _color_inited = 0; + if(!panicking) + free_color_table(&color_tbl); + + if(ANSI_COLOR()) + putpad("\033[39;49m"); + else{ + if(_op) + putpad(_op); + if(_oc) + putpad(_oc); + } + } + } +} + +unsigned +pico_get_color_options() +{ + return(color_options); +} + +/* + * Absolute set of options. Caller has to OR things together and so forth. + */ +void +pico_set_color_options(flags) + unsigned flags; +{ + color_options = flags; +} + +void +pico_endcolor() +{ + pico_toggle_color(0); + if(panicking) + return; + + if(_nfcolor){ + free(_nfcolor); + _nfcolor = NULL; + } + + if(_nbcolor){ + free(_nbcolor); + _nbcolor = NULL; + } + + if(_rfcolor){ + free(_rfcolor); + _rfcolor = NULL; + } + + if(_rbcolor){ + free(_rbcolor); + _rbcolor = NULL; + } + + if(_last_fg_color){ + free(_last_fg_color); + _last_fg_color = NULL; + } + + if(_last_bg_color){ + free(_last_bg_color); + _last_bg_color = NULL; + } + + if(the_rev_color) + free_color_pair(&the_rev_color); + + if(the_normal_color) + free_color_pair(&the_normal_color); +} + +void +pico_set_nfg_color() +{ + if(_nfcolor) + (void)pico_set_fg_color(_nfcolor); +} + +void +pico_set_nbg_color() +{ + if(_nbcolor) + (void)pico_set_bg_color(_nbcolor); +} + +void +pico_set_normal_color() +{ + if(!_nfcolor || !_nbcolor || + !pico_set_fg_color(_nfcolor) || !pico_set_bg_color(_nbcolor)){ + (void)pico_set_fg_color(colorx(DEFAULT_NORM_FORE)); + (void)pico_set_bg_color(colorx(DEFAULT_NORM_BACK)); + } +} + +/* + * If inverse is a color, returns a pointer to that color. + * If not, returns NULL. + * + * NOTE: Don't free this! + */ +COLOR_PAIR * +pico_get_rev_color() +{ + if(pico_usingcolor() && _rfcolor && _rbcolor && + pico_is_good_color(_rfcolor) && pico_is_good_color(_rbcolor)){ + if(!the_rev_color) + the_rev_color = new_color_pair(_rfcolor, _rbcolor); + + return(the_rev_color); + } + else + return(NULL); +} + +/* + * Returns a pointer to the normal color. + * + * NOTE: Don't free this! + */ +COLOR_PAIR * +pico_get_normal_color() +{ + if(pico_usingcolor() && _nfcolor && _nbcolor && + pico_is_good_color(_nfcolor) && pico_is_good_color(_nbcolor)){ + if(!the_normal_color) + the_normal_color = new_color_pair(_nfcolor, _nbcolor); + + return(the_normal_color); + } + else + return(NULL); +} + + +/* + * Just like pico_set_color except it doesn't set the color, it just + * returns the value. Assumes def of PSC_NONE, since otherwise we always + * succeed and don't need to call this. + */ +int +pico_is_good_colorpair(cp) + COLOR_PAIR *cp; +{ + if(!cp || (!pico_is_good_color(cp->fg) || !pico_is_good_color(cp->bg))) + return(FALSE); + + return(TRUE); +} + + +COLOR_PAIR * +pico_set_colorp(col, flags) + COLOR_PAIR *col; + int flags; +{ + return(pico_set_colors((char *) (col ? col->fg : NULL), + (char *) (col ? col->bg : NULL), flags)); +} + + +/* + * Sets color to (fg,bg). + * Flags == PSC_NONE No alternate default if fg,bg fails. + * == PSC_NORM Set it to Normal color on failure. + * == PSC_REV Set it to Reverse color on failure. + * + * If flag PSC_RET is set, returns an allocated copy of the previous + * color pair, otherwise returns NULL. + */ +COLOR_PAIR * +pico_set_colors(fg, bg, flags) + char *fg, *bg; + int flags; +{ + int uc; + COLOR_PAIR *cp = NULL, *rev = NULL; + + if(flags & PSC_RET) + cp = pico_get_cur_color(); + + if(fg && !strcmp(fg, END_PSEUDO_REVERSE)){ + EndInverse(); + if(cp) + free_color_pair(&cp); + } + else if(!((uc=pico_usingcolor()) && fg && bg && + pico_set_fg_color(fg) && pico_set_bg_color(bg))){ + + if(uc && flags & PSC_NORM) + pico_set_normal_color(); + else if(flags & PSC_REV){ + if(rev = pico_get_rev_color()){ + pico_set_fg_color(rev->fg); /* these will succeed */ + pico_set_bg_color(rev->bg); + } + else{ + StartInverse(); + if(cp){ + strcpy(cp->fg, END_PSEUDO_REVERSE); + strcpy(cp->bg, END_PSEUDO_REVERSE); + } + } + } + } + + return(cp); +} + + +int +pico_is_good_color(s) + char *s; +{ + struct color_table *ct; + + if(!s || !color_tbl) + return(FALSE); + + if(!strcmp(s, END_PSEUDO_REVERSE)) + return(TRUE); + else if(*s == ' ' || isdigit(*s)){ + /* check for rgb string instead of name */ + for(ct = color_tbl; ct->rgb; ct++) + if(!strncmp(ct->rgb, s, RGBLEN)) + break; + } + else{ + for(ct = color_tbl; ct->name; ct++) + if(!struncmp(ct->name, s, ct->namelen)) + break; + } + + return(ct->name ? TRUE : FALSE); +} + + +/* + * Return TRUE on success. + */ +int +pico_set_fg_color(s) + char *s; +{ + int val; + + if(!s || !color_tbl) + return(FALSE); + + if(!strcmp(s, END_PSEUDO_REVERSE)){ + EndInverse(); + return(TRUE); + } + + if((val = color_to_val(s)) >= 0){ + /* already set correctly */ + if(!_force_fg_color_change && _last_fg_color && + !strcmp(_last_fg_color,colorx(val))) + return(TRUE); + + _force_fg_color_change = 0; + if(_last_fg_color){ + free(_last_fg_color); + _last_fg_color = NULL; + } + + if(_last_fg_color = (char *)malloc(strlen(colorx(val))+1)) + strcpy(_last_fg_color, colorx(val)); + + tfgcolor(val); + return(TRUE); + } + else + return(FALSE); +} + + +int +pico_set_bg_color(s) + char *s; +{ + int val; + + if(!s || !color_tbl) + return(FALSE); + + if(!strcmp(s, END_PSEUDO_REVERSE)){ + EndInverse(); + return(TRUE); + } + + if((val = color_to_val(s)) >= 0){ + /* already set correctly */ + if(!_force_bg_color_change && _last_bg_color && + !strcmp(_last_bg_color,colorx(val))) + return(TRUE); + + _force_bg_color_change = 0; + if(_last_bg_color){ + free(_last_bg_color); + _last_bg_color = NULL; + } + + if(_last_bg_color = (char *)malloc(strlen(colorx(val))+1)) + strcpy(_last_bg_color, colorx(val)); + + tbgcolor(val); + return(TRUE); + } + else + return(FALSE); +} + + +/* + * Return a pointer to an rgb string for the input color. The output is 11 + * characters long and looks like rrr,ggg,bbb. + * + * Args colorName -- The color to convert to ascii rgb. + * + * Returns Pointer to a static buffer containing the rgb string. + */ +char * +color_to_asciirgb(colorName) + char *colorName; +{ + static char c_to_a_buf[RGBLEN+1]; + + struct color_table *ct; + + for(ct = color_tbl; ct && ct->name; ct++) + if(!strucmp(ct->name, colorName)) + break; + + if(ct && ct->name) + strcpy(c_to_a_buf, ct->rgb); + else{ + int l; + + /* + * If we didn't find the color we're in a bit of trouble. This + * most likely means that the user is using the same pinerc on + * two terminals, one with more colors than the other. We didn't + * find a match because this color isn't present on this terminal. + * Since the return value of this function is assumed to be + * RGBLEN long, we'd better make it that long. + * It still won't work correctly because colors will be screwed up, + * but at least the embedded colors in filter.c will get properly + * sucked up when they're encountered. + */ + strncpy(c_to_a_buf, "xxxxxxxxxxx", RGBLEN); /* RGBLEN is 11 */ + l = strlen(colorName); + strncpy(c_to_a_buf, colorName, (l < RGBLEN) ? l : RGBLEN); + c_to_a_buf[RGBLEN] = '\0'; + } + + return(c_to_a_buf); +} + +char * +pico_get_last_fg_color() +{ + char *ret = NULL; + + if(_last_fg_color) + if(ret = (char *)malloc(strlen(_last_fg_color)+1)) + strcpy(ret, _last_fg_color); + + return(ret); +} + +char * +pico_get_last_bg_color() +{ + char *ret = NULL; + + if(_last_bg_color) + if(ret = (char *)malloc(strlen(_last_bg_color)+1)) + strcpy(ret, _last_bg_color); + + return(ret); +} + + +COLOR_PAIR * +pico_get_cur_color() +{ + return(new_color_pair(_last_fg_color, _last_bg_color)); +} + + +COLOR_PAIR * +new_color_pair(fg, bg) + char *fg, *bg; +{ + COLOR_PAIR *ret; + + if((ret = (COLOR_PAIR *)malloc(sizeof(*ret))) != NULL){ + memset(ret, 0, sizeof(*ret)); + if(fg){ + strncpy(ret->fg, fg, MAXCOLORLEN); + ret->fg[MAXCOLORLEN] = '\0'; + } + + if(bg){ + strncpy(ret->bg, bg, MAXCOLORLEN); + ret->bg[MAXCOLORLEN] = '\0'; + } + } + + return(ret); +} + + +void +free_color_pair(cp) + COLOR_PAIR **cp; +{ + if(cp && *cp){ + free(*cp); + *cp = NULL; + } +} + + +/* + * alt_editor - fork off an alternate editor for mail message composition + * if one is configured and passed from pine. If not, only + * ask for the editor if advanced user flag is set, and + * suggest environment's EDITOR value as default. + */ +alt_editor(f, n) +{ + char eb[NLINE]; /* buf holding edit command */ + char *fn; /* tmp holder for file name */ + char result[128]; /* result string */ + char prmpt[128]; + int child, pid, i, done = 0, ret = 0, rv; + SigType (*ohup) SIG_PROTO((int)); + SigType (*oint) SIG_PROTO((int)); + SigType (*osize) SIG_PROTO((int)); +#if defined(HAVE_WAIT_UNION) + union wait stat; +#ifndef WIFEXITED +#define WIFEXITED(X) (!(X).w_termsig) /* nonzero if child killed */ +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(X) X.w_retcode /* child's exit value */ +#endif +#else + int stat; +#ifndef WIFEXITED +#define WIFEXITED(X) (!((X) & 0xff)) /* low bits, child killed */ +#endif +#ifndef WEXITSTATUS +#define WEXITSTATUS(X) ((X) >> 8) /* high bits, exit value */ +#endif +#endif + +#ifndef PATH_MAX +#define PATH_MAX NLINE +#endif + + if(gmode&MDSCUR){ + emlwrite("Alternate %s not available in restricted mode", + f ? "speller" : "editor"); + return(-1); + } + + strcpy(result, "Alternate %s complete."); + + if(f){ + if(alt_speller) + strcpy(eb, alt_speller); + else + return(-1); + } + else if(Pmaster == NULL){ + return(-1); + } + else{ + eb[0] = '\0'; + + if(Pmaster->alt_ed){ + char **lp, *wsp, *path, fname[PATH_MAX+1]; + int c; + + for(lp = Pmaster->alt_ed; *lp && **lp; lp++){ + if(wsp = strpbrk(*lp, " \t")){ + c = *wsp; + *wsp = '\0'; + } + + if(strchr(*lp, '/')){ + rv = fexist(*lp, "x", (off_t *)NULL); + } + else{ + if(!(path = getenv("PATH"))) + path = ":/bin:/usr/bin"; + + rv = ~FIOSUC; + while(rv != FIOSUC && *path && pathcat(fname, &path, *lp)) + rv = fexist(fname, "x", (off_t *)NULL); + } + + if(wsp) + *wsp = c; + + if(rv == FIOSUC){ + strcpy(eb, *lp); + break; + } + } + } + + if(!eb[0]){ + if(!(gmode&MDADVN)){ + emlwrite("\007Unknown Command",NULL); + return(-1); + } + + if(getenv("EDITOR")) + strcpy(eb, (char *)getenv("EDITOR")); + else + *eb = '\0'; + + while(!done){ + pid = mlreplyd("Which alternate editor ? ", eb, + NLINE, QDEFLT, NULL); + switch(pid){ + case ABORT: + curwp->w_flag |= WFMODE; + return(-1); + case HELPCH: + emlwrite("no alternate editor help yet", NULL); + +/* take sleep and break out after there's help */ + sleep(3); + break; + case (CTRL|'L'): + sgarbf = TRUE; + update(); + break; + case TRUE: + case FALSE: /* does editor exist ? */ + if(*eb == '\0'){ /* leave silently? */ + mlerase(); + curwp->w_flag |= WFMODE; + return(-1); + } + + done++; + break; + default: + break; + } + } + } + } + + if((fn=writetmp(1, NULL)) == NULL){ /* get temp file */ + emlwrite("Problem writing temp file for alt editor", NULL); + return(-1); + } + + strcat(eb, " "); + strcat(eb, fn); + + + for(i = 0; i <= ((Pmaster) ? term.t_nrow : term.t_nrow - 1); i++){ + movecursor(i, 0); + if(!i){ + fputs("Invoking alternate ", stdout); + fputs(f ? "speller..." : "editor...", stdout); + } + + peeol(); + } + + (*term.t_flush)(); + if(Pmaster) + (*Pmaster->tty_fix)(0); + else + vttidy(); + +#ifdef SIGCHLD + if(Pmaster){ + /* + * The idea here is to keep any mail connections our caller + * may have open while our child's out running around... + */ + pico_child_done = pico_child_jmp_ok = 0; + (void) signal(SIGCHLD, child_handler); + } +#endif + + if((child = fork()) > 0){ /* wait for the child to finish */ + ohup = signal(SIGHUP, SIG_IGN); /* ignore signals for now */ + oint = signal(SIGINT, SIG_IGN); +#ifdef RESIZING + osize = signal(SIGWINCH, SIG_IGN); +#endif + +#ifdef SIGCHLD + if(Pmaster){ + while(!pico_child_done){ + (*Pmaster->newmail)(0, 0); + if(!pico_child_done){ + if(setjmp(pico_child_state) == 0){ + pico_child_jmp_ok = 1; + sleep(600); + } + else + our_sigunblock(SIGCHLD); + } + + pico_child_jmp_ok = 0; + } + } +#endif + + while((pid = (int) wait(&stat)) != child) + ; + + signal(SIGHUP, ohup); /* restore signals */ + signal(SIGINT, oint); +#ifdef RESIZING + signal(SIGWINCH, osize); +#endif + + /* + * Report child's unnatural or unhappy exit... + */ + if(WIFEXITED(stat) && WEXITSTATUS(stat) == 0) + strcpy(result, "Alternate %s done"); + else { + sprintf(result, "Alternate %%s terminated abnormally (%d)", + WIFEXITED(stat) ? WEXITSTATUS(stat) : -1); + if(f) + ret = -1; + else{ + sprintf(prmpt, "Alt editor failed, use file %.20s of size %%ld chars anyway", fn); + ret = -2; + } + } + } + else if(child == 0){ /* spawn editor */ + signal(SIGHUP, SIG_DFL); /* let editor handle signals */ + signal(SIGINT, SIG_DFL); +#ifdef RESIZING + signal(SIGWINCH, SIG_DFL); +#endif +#ifdef SIGCHLD + (void) signal(SIGCHLD, SIG_DFL); +#endif + if(execl("/bin/sh", "sh", "-c", eb, 0) < 0) + exit(-1); + } + else { /* error! */ + sprintf(result, "\007Can't fork %%s: %s", errstr(errno)); + ret = -1; + } + +#ifdef SIGCHLD + (void) signal(SIGCHLD, SIG_DFL); +#endif + + if(Pmaster) + (*Pmaster->tty_fix)(1); + + /* + * Editor may have set a hibit, we don't know. Assume it did. + */ + if(!f && Pmaster && Pmaster->hibit_entered) + *Pmaster->hibit_entered = 1; + + /* + * replace edited text with new text + */ + curbp->b_flag &= ~BFCHG; /* make sure old text gets blasted */ + + if(ret == -2){ + off_t filesize; + char prompt[128]; + + rv = fexist(fn, "r", &filesize); + if(rv == FIOSUC && filesize > 0){ + sprintf(prompt, prmpt, (long) filesize); + /* clear bottom 3 rows */ + pclear(term.t_nrow-2, term.t_nrow+1); + i = mlyesno(prompt, FALSE); + if(i == TRUE){ + ret = 0; + strcpy(result, "OK, alternate %s done"); + } + else + ret = -1; + } + else + ret = -1; + } + + if(ret == 0) + readin(fn, 0, 0); /* read new text overwriting old */ + + unlink(fn); /* blast temp file */ + curbp->b_flag |= BFCHG; /* mark dirty for packbuf() */ + ttopen(); /* reset the signals */ + pico_refresh(0, 1); /* redraw */ + update(); + emlwrite(result, f ? "speller" : "editor"); + return(ret); +} + + + +int +pathcat(buf, path, file) + char *buf, **path, *file; +{ + register int n = 0; + + while(**path && **path != ':'){ + if(n++ > PATH_MAX) + return(FALSE); + + *buf++ = *(*path)++; + } + + if(n){ + if(n++ > PATH_MAX) + return(FALSE); + + *buf++ = '/'; + } + + while(*buf = *file++){ + if(n++ > PATH_MAX) + return(FALSE); + + buf++; + } + + if(**path == ':') + (*path)++; + + return(TRUE); +} + + + + +/* + * bktoshell - suspend and wait to be woken up + */ +int +bktoshell() /* suspend MicroEMACS and wait to wake up */ +{ +#ifdef SIGTSTP + if(!(gmode&MDSSPD)){ + emlwrite("\007Unknown command: ^Z", NULL); + return(0); + } + + if(Pmaster){ + if(!Pmaster->suspend){ + emlwrite("\007Unknown command: ^Z", NULL); + return(0); + } + + if((*Pmaster->suspend)() == NO_OP_COMMAND){ + int rv; + + if(km_popped){ + term.t_mrow = 2; + curwp->w_ntrows -= 2; + } + + clearcursor(); + mlerase(); + rv = (*Pmaster->showmsg)('x'); + ttresize(); + picosigs(); + if(rv) /* Did showmsg corrupt the display? */ + pico_refresh(0, 1); /* Yes, repaint */ + + mpresf = 1; + if(km_popped){ + term.t_mrow = 0; + curwp->w_ntrows += 2; + } + } + else{ + ttresize(); + pclear(0, term.t_nrow); + pico_refresh(0, 1); + } + + return(1); + } + + if(gmode&MDSPWN){ + char *shell; + + vttidy(); + movecursor(0, 0); + (*term.t_eeop)(); + printf("\n\n\nUse \"exit\" to return to Pi%s\n", + (gmode & MDBRONLY) ? "lot" : "co"); + system((shell = (char *)getenv("SHELL")) ? shell : "/bin/csh"); + rtfrmshell SIG_PROTO((dummy)); /* fixup tty */ + } + else { + movecursor(term.t_nrow-1, 0); + peeol(); + movecursor(term.t_nrow, 0); + peeol(); + movecursor(term.t_nrow, 0); + printf("\n\n\nUse \"fg\" to return to Pi%s\n", + (gmode & MDBRONLY) ? "lot" : "co"); + ttclose(); + movecursor(term.t_nrow, 0); + peeol(); + (*term.t_flush)(); + + signal(SIGCONT, rtfrmshell); /* prepare to restart */ + signal(SIGTSTP, SIG_DFL); /* prepare to stop */ + kill(0, SIGTSTP); + } + + return(1); +#endif +} + + +/* + * rtfrmshell - back from shell, fix modes and return + */ +SigType +rtfrmshell SIG_PROTO((int sig)) +{ +#ifdef SIGCONT + signal(SIGCONT, SIG_DFL); + ttopen(); + ttresize(); + pclear(0, term.t_nrow); + pico_refresh(0, 1); +#endif +} + + + +/* + * do_hup_signal - jump back in the stack to where we can handle this + */ +SigType +do_hup_signal SIG_PROTO((int sig)) +{ + signal(SIGHUP, SIG_IGN); /* ignore further SIGHUP's */ + signal(SIGTERM, SIG_IGN); /* ignore further SIGTERM's */ + if(Pmaster){ + extern jmp_buf finstate; + + longjmp(finstate, COMP_GOTHUP); + } + else{ + /* + * if we've been interrupted and the buffer is changed, + * save it... + */ + if(anycb() == TRUE){ /* time to save */ + if(curbp->b_fname[0] == '\0'){ /* name it */ + strcpy(curbp->b_fname, "pico.save"); + } + else{ + strcat(curbp->b_fname, ".save"); + } + unlink(curbp->b_fname); + writeout(curbp->b_fname, TRUE); + } + vttidy(); + exit(1); + } +} + + +/* + * big bitmap of ASCII characters allowed in a file name + * (needs reworking for other char sets) + */ +unsigned char okinfname[32] = { + 0, 0, /* ^@ - ^G, ^H - ^O */ + 0, 0, /* ^P - ^W, ^X - ^_ */ + 0x80, 0x17, /* SP - ' , ( - / */ + 0xff, 0xc4, /* 0 - 7 , 8 - ? */ + 0x7f, 0xff, /* @ - G , H - O */ + 0xff, 0xe1, /* P - W , X - _ */ + 0x7f, 0xff, /* ` - g , h - o */ + 0xff, 0xf6, /* p - w , x - DEL */ + 0, 0, /* > DEL */ + 0, 0, /* > DEL */ + 0, 0, /* > DEL */ + 0, 0, /* > DEL */ + 0, 0 /* > DEL */ +}; + + +/* + * fallowc - returns TRUE if c is allowable in filenames, FALSE otw + */ +fallowc(c) +char c; +{ + return(okinfname[c>>3] & 0x80>>(c&7)); +} + + +/* + * fexist - returns TRUE if the file exists with mode passed in m, + * FALSE otherwise. By side effect returns length of file in l + */ +fexist(file, m, l) +char *file; +char *m; /* files mode: r,w,rw,t or x */ +off_t *l; /* t means use lstat */ +{ + struct stat sbuf; + extern int lstat(); + int (*stat_f)() = (m && *m == 't') ? lstat : stat; + + if(l) + *l = (off_t)0; + + if((*stat_f)(file, &sbuf) < 0){ + switch(errno){ + case ENOENT : /* File not found */ + return(FIOFNF); +#ifdef ENAMETOOLONG + case ENAMETOOLONG : /* Name is too long */ + return(FIOLNG); +#endif + case EACCES : /* File not found */ + return(FIOPER); + default: /* Some other error */ + return(FIOERR); + } + } + + if(l) + *l = (off_t)sbuf.st_size; + + if((sbuf.st_mode&S_IFMT) == S_IFDIR) + return(FIODIR); + else if(*m == 't'){ + struct stat sbuf2; + + /* + * If it is a symbolic link pointing to a directory, treat + * it like it is a directory, not a link. + */ + if((sbuf.st_mode&S_IFMT) == S_IFLNK){ + if(stat(file, &sbuf2) < 0){ + switch(errno){ + case ENOENT : /* File not found */ + return(FIOSYM); /* call it a link */ +#ifdef ENAMETOOLONG + case ENAMETOOLONG : /* Name is too long */ + return(FIOLNG); +#endif + case EACCES : /* File not found */ + return(FIOPER); + default: /* Some other error */ + return(FIOERR); + } + } + + if((sbuf2.st_mode&S_IFMT) == S_IFDIR) + return(FIODIR); + } + + return(((sbuf.st_mode&S_IFMT) == S_IFLNK) ? FIOSYM : FIOSUC); + } + + if(*m == 'r'){ /* read access? */ + if(*(m+1) == 'w') /* and write access? */ + return((can_access(file,READ_ACCESS)==0) + ? (can_access(file,WRITE_ACCESS)==0) + ? FIOSUC + : FIONWT + : FIONRD); + else if(!*(m+1)) /* just read access? */ + return((can_access(file,READ_ACCESS)==0) ? FIOSUC : FIONRD); + } + else if(*m == 'w' && !*(m+1)) /* write access? */ + return((can_access(file,WRITE_ACCESS)==0) ? FIOSUC : FIONWT); + else if(*m == 'x' && !*(m+1)) /* execute access? */ + return((can_access(file,EXECUTE_ACCESS)==0) ? FIOSUC : FIONEX); + return(FIOERR); /* bad m arg */ +} + + +/* + * isdir - returns true if fn is a readable directory, false otherwise + * silent on errors (we'll let someone else notice the problem;)). + */ +isdir(fn, l, d) +char *fn; +long *l; +time_t *d; +{ + struct stat sbuf; + + if(l) + *l = 0; + + if(stat(fn, &sbuf) < 0) + return(0); + + if(l) + *l = sbuf.st_size; + + if(d) + *d = sbuf.st_mtime; + + return((sbuf.st_mode&S_IFMT) == S_IFDIR); +} + + +/* + * gethomedir - returns the users home directory + * Note: home is malloc'd for life of pico + */ +char * +gethomedir(l) +int *l; +{ + static char *home = NULL; + static short hlen = 0; + + if(home == NULL){ + char buf[NLINE]; + strcpy(buf, "~"); + fixpath(buf, NLINE); /* let fixpath do the work! */ + hlen = strlen(buf); + if((home = (char *)malloc((hlen + 1) * sizeof(char))) == NULL){ + emlwrite("Problem allocating space for home dir", NULL); + return(0); + } + + strcpy(home, buf); + } + + if(l) + *l = hlen; + + return(home); +} + + +/* + * homeless - returns true if given file does not reside in the current + * user's home directory tree. + */ +homeless(f) +char *f; +{ + char *home; + int len; + + home = gethomedir(&len); + return(strncmp(home, f, len)); +} + + + +/* + * errstr - return system error string corresponding to given errno + * Note: strerror() is not provided on all systems, so it's + * done here once and for all. + * + * Not anymore! There are now systems that won't let you use + * sys_nerr and sys_errlist, so it is time to switch to using + * strerror instead. If this doesn't work, uncomment the old stuff. + */ +char * +errstr(err) +int err; +{ + return((err >= 0) ? (char *) strerror(err) : NULL); +#ifdef OLDWAY + return((err >= 0 && err < sys_nerr) ? (char *)sys_errlist[err] : NULL); +#endif +} + + + +/* + * getfnames - return all file names in the given directory in a single + * malloc'd string. n contains the number of names + */ +char * +getfnames(dn, pat, n, e) +char *dn, *pat, *e; +int *n; +{ + long l; + size_t avail, alloced, incr = 1024; + char *names, *np, *p; + struct stat sbuf; +#if defined(ct) + FILE *dirp; + char fn[DIRSIZ+1]; +#else + DIR *dirp; /* opened directory */ +#endif +#ifdef USE_DIRENT + struct dirent *dp; +#else + struct direct *dp; +#endif + + *n = 0; + + if(stat(dn, &sbuf) < 0){ + switch(errno){ + case ENOENT : /* File not found */ + if(e) + sprintf(e, "\007File not found: \"%s\"", dn); + + break; +#ifdef ENAMETOOLONG + case ENAMETOOLONG : /* Name is too long */ + if(e) + sprintf(e, "\007File name too long: \"%s\"", dn); + + break; +#endif + default: /* Some other error */ + if(e) + sprintf(e, "\007Error getting file info: \"%s\"", dn); + + break; + } + return(NULL); + } + else{ +#ifndef MAX +#define MAX(x,y) ((x) > (y) ? (x) : (y)) +#endif + /* + * We'd like to use 512 * st_blocks as an initial estimate but + * some systems have a stat struct with no st_blocks in it. + */ + avail = alloced = MAX(sbuf.st_size, incr); + if((sbuf.st_mode&S_IFMT) != S_IFDIR){ + if(e) + sprintf(e, "\007Not a directory: \"%s\"", dn); + + return(NULL); + } + } + + if((names=(char *)malloc(alloced * sizeof(char))) == NULL){ + if(e) + sprintf(e, "\007Can't malloc space for file names"); + + return(NULL); + } + + errno = 0; + if((dirp=opendir(dn)) == NULL){ + if(e) + sprintf(e, "\007Can't open \"%s\": %s", dn, errstr(errno)); + + free((char *)names); + return(NULL); + } + + np = names; + +#if defined(ct) + while(fread(&dp, sizeof(struct direct), 1, dirp) > 0) { + /* skip empty slots with inode of 0 */ + if(dp.d_ino == 0) + continue; + (*n)++; /* count the number of active slots */ + (void)strncpy(fn, dp.d_name, DIRSIZ); + fn[14] = '\0'; + p = fn; + while((*np++ = *p++) != '\0') + ; + } +#else + while((dp = readdir(dirp)) != NULL) + if(!pat || !*pat || !strncmp(dp->d_name, pat, strlen(pat))){ + (*n)++; + p = dp->d_name; + l = strlen(p); + while(avail < l+1){ + char *oldnames; + + alloced += incr; + avail += incr; + oldnames = names; + if((names=(char *)realloc((void *)names, alloced * sizeof(char))) + == NULL){ + if(e) + sprintf(e, "\007Can't malloc enough space for file names"); + + return(NULL); + } + + np = names + (np-oldnames); + } + + avail -= (l+1); + + while(*np++ = *p++) + ; + } +#endif + + closedir(dirp); /* shut down */ + return(names); +} + + +/* + * fioperr - given the error number and file name, display error + */ +void +fioperr(e, f) +int e; +char *f; +{ + switch(e){ + case FIOFNF: /* File not found */ + emlwrite("\007File \"%s\" not found", f); + break; + case FIOEOF: /* end of file */ + emlwrite("\007End of file \"%s\" reached", f); + break; + case FIOLNG: /* name too long */ + emlwrite("\007File name \"%s\" too long", f); + break; + case FIODIR: /* file is a directory */ + emlwrite("\007File \"%s\" is a directory", f); + break; + case FIONWT: + emlwrite("\007Write permission denied: %s", f); + break; + case FIONRD: + emlwrite("\007Read permission denied: %s", f); + break; + case FIOPER: + emlwrite("\007Permission denied: %s", f); + break; + case FIONEX: + emlwrite("\007Execute permission denied: %s", f); + break; + default: + emlwrite("\007File I/O error: %s", f); + } +} + + + +/* + * pfnexpand - pico's function to expand the given file name if there is + * a leading '~' + */ +char *pfnexpand(fn, len) + char *fn; + size_t len; +{ + struct passwd *pw; + register char *x, *y, *z; + char *home = NULL; + char name[20]; + + if(*fn == '~') { + for(x = fn+1, y = name; + *x != '/' && *x != '\0' && y-name < sizeof(name)-1; + *y++ = *x++) + ; + + *y = '\0'; + if(x == fn + 1){ /* ~/ */ + if (!(home = (char *) getenv("HOME"))) + if (pw = getpwuid(geteuid())) + home = pw->pw_dir; + } + else if(*name){ /* ~username/ */ + if(pw = getpwnam(name)) + home = pw->pw_dir; + } + + if(!home || (strlen(home) + strlen(fn) >= len)) + return(NULL); + + /* make room for expanded path */ + for(z = x + strlen(x), y = fn + strlen(x) + strlen(home); + z >= x; + *y-- = *z--) + ; + + /* and insert the expanded address */ + for(x = fn, y = home; *y != '\0'; *x++ = *y++) + ; + } + return(fn); +} + + + +/* + * fixpath - make the given pathname into an absolute path + */ +void +fixpath(name, len) + char *name; + size_t len; +{ + register char *shft; + + /* filenames relative to ~ */ + if(!((name[0] == '/') + || (name[0] == '.' + && (name[1] == '/' || (name[1] == '.' && name[2] == '/'))))){ + if(Pmaster && !(gmode&MDCURDIR) + && (*name != '~' && strlen(name)+2 < len)){ + + if(gmode&MDTREE && strlen(name)+strlen(opertree)+1 < len){ + int off = strlen(opertree); + + for(shft = strchr(name, '\0'); shft >= name; shft--) + shft[off+1] = *shft; + + strncpy(name, opertree, off); + name[off] = '/'; + } + else{ + for(shft = strchr(name, '\0'); shft >= name; shft--) + shft[2] = *shft; + + name[0] = '~'; + name[1] = '/'; + } + } + + pfnexpand(name, len); + } +} + + +/* + * compresspath - given a base path and an additional directory, collapse + * ".." and "." elements and return absolute path (appending + * base if necessary). + * + * returns 1 if OK, + * 0 if there's a problem + * new path, by side effect, if things went OK + */ +compresspath(base, path, len) +char *base, *path; +int len; +{ + register int i; + int depth = 0; + char *p; + char *stack[32]; + char pathbuf[NLINE]; + +#define PUSHD(X) (stack[depth++] = X) +#define POPD() ((depth > 0) ? stack[--depth] : "") + + if(*path == '~'){ + fixpath(path, len); + strcpy(pathbuf, path); + } + else if(*path != C_FILESEP) + sprintf(pathbuf, "%s%c%s", base, C_FILESEP, path); + else + strcpy(pathbuf, path); + + p = &pathbuf[0]; + for(i=0; pathbuf[i] != '\0'; i++){ /* pass thru path name */ + if(pathbuf[i] == '/'){ + if(p != pathbuf) + PUSHD(p); /* push dir entry */ + + p = &pathbuf[i+1]; /* advance p */ + pathbuf[i] = '\0'; /* cap old p off */ + continue; + } + + if(pathbuf[i] == '.'){ /* special cases! */ + if(pathbuf[i+1] == '.' /* parent */ + && (pathbuf[i+2] == '/' || pathbuf[i+2] == '\0')){ + if(!strcmp(POPD(), "")) /* bad news! */ + return(0); + + i += 2; + p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1]; + } + else if(pathbuf[i+1] == '/' || pathbuf[i+1] == '\0'){ + i++; + p = (pathbuf[i] == '\0') ? "" : &pathbuf[i+1]; + } + } + } + + if(*p != '\0') + PUSHD(p); /* get last element */ + + path[0] = '\0'; + for(i = 0; i < depth; i++){ + strcat(path, S_FILESEP); + strcat(path, stack[i]); + } + + return(1); /* everything's ok */ +} + + + +/* + * Check if we can access a file in a given way + * + * Args: file -- The file to check + * mode -- The mode ala the access() system call, see ACCESS_EXISTS + * and friends in pine.h. + * + * Result: returns 0 if the user can access the file according to the mode, + * -1 if he can't (and errno is set). + */ +int +can_access(file, mode) + char *file; + int mode; +{ + return(access(file, mode)); +} + + +/* + * This routine is derived from BSD4.3 code, + * Copyright (c) 1987 Regents of the University of California. + * All rights reserved. + */ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)mktemp.c 5.7 (Berkeley) 6/27/88"; +#endif /* LIBC_SCCS and not lint */ + +static char * +was_nonexistent_tmp_name(as, create_it, ext) + char *as; + int create_it; + char *ext; +{ + register char *start, *trv; + struct stat sbuf; + unsigned pid; + static unsigned n = 0; + int fd, tries = 0; + + pid = ((unsigned)getpid() * 100) + n++; + + /* extra X's get set to 0's */ + for(trv = as; *trv; ++trv) + ; + + /* + * We should probably make the name random instead of having it + * be the pid. + */ + while(*--trv == 'X'){ + *trv = (pid % 10) + '0'; + pid /= 10; + } + + /* add the extension, enough room guaranteed by caller */ + if(ext){ + strcat(as, "."); + strcat(as, ext); + } + + /* + * Check for write permission on target directory; if you have + * six X's and you can't write the directory, this will run for + * a *very* long time. + */ + for(start = ++trv; trv > as && *trv != '/'; --trv) + ; + + if(*trv == '/'){ + *trv = '\0'; + if(stat(as==trv ? "/" : as, &sbuf) || !(sbuf.st_mode & S_IFDIR)) + return((char *)NULL); + + *trv = '/'; + } + else if (stat(".", &sbuf) == -1) + return((char *)NULL); + + for(;;){ + /* + * Check with lstat to be sure we don't have + * a symlink. If lstat fails and no such file, then we + * have a winner. Otherwise, lstat shouldn't fail. + * If lstat succeeds, then skip it because it exists. + */ + if(lstat(as, &sbuf)){ /* lstat failed */ + if(errno == ENOENT){ /* no such file, success */ + /* + * If create_it is set, create the file so that the + * evil ones don't have a chance to put something there + * that they can read or write before we create it + * ourselves. + */ + if(!create_it || + ((fd=open(as, O_CREAT|O_EXCL|O_WRONLY,0600)) >= 0 + && close(fd) == 0)) + return(as); + else if(++tries > 3) /* open failed unexpectedly */ + return((char *)NULL); + } + else /* failed for unknown reason */ + return((char *)NULL); + } + + for(trv = start;;){ + if(!*trv) + return((char *)NULL); + + /* + * Change the digits from the initial values into + * lower case letters and try again. + */ + if(*trv == 'z') + *trv++ = 'a'; + else{ + if(isdigit((unsigned char)*trv)) + *trv = 'a'; + else + ++*trv; + + break; + } + } + } + /*NOTREACHED*/ +} + + +/* + * This routine is derived from BSD4.3 code, + * Copyright (c) 1988 Regents of the University of California. + * All rights reserved. + */ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)tmpnam.c 4.5 (Berkeley) 6/27/88"; +#endif /* LIBC_SCCS and not lint */ +/*---------------------------------------------------------------------- + Return a unique file name in a given directory. This is not quite + the same as the usual tempnam() function, though it is similar. + We want it to use the TMPDIR/TMP/TEMP environment variable only if dir + is NULL, instead of using it regardless if it is set. + We also want it to be safer than tempnam(). + If we return a filename, we are saying that the file did not exist + at the time this function was called (and it wasn't a symlink pointing + to a file that didn't exist, either). + If dir is NULL this is a temp file in a public directory. In that + case we create the file with permission 0600 before returning. + + Args: dir -- The directory to create the name in + prefix -- Prefix of the name + + Result: Malloc'd string equal to new name is returned. It must be free'd + by the caller. Returns the string on success and NULL on failure. + ----*/ +char * +temp_nam(dir, prefix) + char *dir, *prefix; +{ + struct stat buf; + size_t l, ll; + char *f, *name; + + if(!(name = (char *)malloc((unsigned int)NFILEN))) + return((char *)NULL); + + if(!dir && (f = getenv("TMPDIR")) && !stat(f, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(f, WRITE_ACCESS|EXECUTE_ACCESS)){ + strncpy(name, f, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + if(!dir && (f = getenv("TMP")) && !stat(f, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(f, WRITE_ACCESS|EXECUTE_ACCESS)){ + strncpy(name, f, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + if(!dir && (f = getenv("TEMP")) && !stat(f, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(f, WRITE_ACCESS|EXECUTE_ACCESS)){ + strncpy(name, f, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + if(dir && !stat(dir, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(dir, WRITE_ACCESS|EXECUTE_ACCESS)){ + strncpy(name, dir, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + +#ifndef P_tmpdir +#define P_tmpdir "/usr/tmp" +#endif + if(!stat(P_tmpdir, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(P_tmpdir, WRITE_ACCESS|EXECUTE_ACCESS)){ + strncpy(name, P_tmpdir, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + if(!stat("/tmp", &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access("/tmp", WRITE_ACCESS|EXECUTE_ACCESS)){ + strncpy(name, "/tmp", NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + free((void *)name); + return((char *)NULL); + +done: + if(name[0] && *((f = &name[l=strlen(name)]) - 1) != '/' && l+1 < NFILEN){ + *f++ = '/'; + *f = '\0'; + l++; + } + + if(prefix && (ll = strlen(prefix)) && l+ll < NFILEN){ + strcpy(f, prefix); + f += ll; + l += ll; + } + + if(l+6 < NFILEN) + strcpy(f, "XXXXXX"); + else{ + free((void *)name); + return((char *)NULL); + } + + return(was_nonexistent_tmp_name(name, 1, NULL)); +} + +/*---------------------------------------------------------------------- + + Like temp_nam but create a unique name with an extension. + + Result: Malloc'd string equal to new name is returned. It must be free'd + by the caller. Returns the string on success and NULL on failure. + ----*/ +char * +temp_nam_ext(dir, prefix, ext) + char *dir, *prefix, *ext; +{ + struct stat buf; + size_t l, ll; + char *f, *name; + + if(ext == NULL || *ext == '\0') + return(temp_nam(dir, prefix)); + if(!(name = (char *)malloc((unsigned int)NFILEN))) + return((char *)NULL); + + if(!dir && (f = getenv("TMPDIR")) && !stat(f, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(f, WRITE_ACCESS|EXECUTE_ACCESS)){ + strncpy(name, f, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + if(!dir && (f = getenv("TMP")) && !stat(f, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(f, WRITE_ACCESS|EXECUTE_ACCESS)){ + strncpy(name, f, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + if(!dir && (f = getenv("TEMP")) && !stat(f, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(f, WRITE_ACCESS|EXECUTE_ACCESS)){ + strncpy(name, f, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + if(dir && !stat(dir, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(dir, WRITE_ACCESS|EXECUTE_ACCESS)){ + strncpy(name, dir, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + +#ifndef P_tmpdir +#define P_tmpdir "/usr/tmp" +#endif + if(!stat(P_tmpdir, &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access(P_tmpdir, WRITE_ACCESS|EXECUTE_ACCESS)){ + strncpy(name, P_tmpdir, NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + if(!stat("/tmp", &buf) && + (buf.st_mode&S_IFMT) == S_IFDIR && + !can_access("/tmp", WRITE_ACCESS|EXECUTE_ACCESS)){ + strncpy(name, "/tmp", NFILEN-1); + name[NFILEN-1] = '\0'; + goto done; + } + + free((void *)name); + return((char *)NULL); + +done: + if(name[0] && *((f = &name[l=strlen(name)]) - 1) != '/' && l+1 < NFILEN){ + *f++ = '/'; + *f = '\0'; + l++; + } + + if(prefix && (ll = strlen(prefix)) && l+ll < NFILEN){ + strcpy(f, prefix); + f += ll; + l += ll; + } + + if(l+6+strlen(ext)+1 < NFILEN) + strcpy(f, "XXXXXX"); + else{ + free((void *)name); + return((char *)NULL); + } + + return(was_nonexistent_tmp_name(name, 1, ext)); +} + + +/* + * tmpname - return a temporary file name in the given buffer, the filename + * is in the directory dir unless dir is NULL. The file did not exist at + * the time of the temp_nam call, but was created by temp_nam. + */ +void +tmpname(dir, name) +char *dir; +char *name; +{ + char *t; + + if(t = temp_nam((dir && *dir) ? dir : NULL, "pico.")){ + strncpy(name, t, NFILEN-1); + name[NFILEN-1] = '\0'; + free((void *)t); + } + else { + emlwrite("Unable to construct temp file name", NULL); + name[0] = '\0'; + } +} + + +/* + * Take a file name, and from it + * fabricate a buffer name. This routine knows + * about the syntax of file names on the target system. + * I suppose that this information could be put in + * a better place than a line of code. + */ +void +makename(bname, fname) +char bname[]; +char fname[]; +{ + register char *cp1; + register char *cp2; + + cp1 = &fname[0]; + while (*cp1 != 0) + ++cp1; + + while (cp1!=&fname[0] && cp1[-1]!='/') + --cp1; + + cp2 = &bname[0]; + while (cp2!=&bname[NBUFN-1] && *cp1!=0 && *cp1!=';') + *cp2++ = *cp1++; + + *cp2 = 0; +} + + +/* + * copy - copy contents of file 'a' into a file named 'b'. Return error + * if either isn't accessible or is a directory + */ +copy(a, b) +char *a, *b; +{ + int in, out, n, rv = 0; + char *cb; + struct stat tsb, fsb; + extern int errno; + + if(stat(a, &fsb) < 0){ /* get source file info */ + emlwrite("Can't Copy: %s", errstr(errno)); + return(-1); + } + + if(!(fsb.st_mode&S_IREAD)){ /* can we read it? */ + emlwrite("\007Read permission denied: %s", a); + return(-1); + } + + if((fsb.st_mode&S_IFMT) == S_IFDIR){ /* is it a directory? */ + emlwrite("\007Can't copy: %s is a directory", a); + return(-1); + } + + if(stat(b, &tsb) < 0){ /* get dest file's mode */ + switch(errno){ + case ENOENT: + break; /* these are OK */ + default: + emlwrite("\007Can't Copy: %s", errstr(errno)); + return(-1); + } + } + else{ + if(!(tsb.st_mode&S_IWRITE)){ /* can we write it? */ + emlwrite("\007Write permission denied: %s", b); + return(-1); + } + + if((tsb.st_mode&S_IFMT) == S_IFDIR){ /* is it directory? */ + emlwrite("\007Can't copy: %s is a directory", b); + return(-1); + } + + if(fsb.st_dev == tsb.st_dev && fsb.st_ino == tsb.st_ino){ + emlwrite("\007Identical files. File not copied", NULL); + return(-1); + } + } + + if((in = open(a, O_RDONLY)) < 0){ + emlwrite("Copy Failed: %s", errstr(errno)); + return(-1); + } + + if((out=creat(b, fsb.st_mode&0xfff)) < 0){ + emlwrite("Can't Copy: %s", errstr(errno)); + close(in); + return(-1); + } + + if((cb = (char *)malloc(NLINE*sizeof(char))) == NULL){ + emlwrite("Can't allocate space for copy buffer!", NULL); + close(in); + close(out); + return(-1); + } + + while(1){ /* do the copy */ + if((n = read(in, cb, NLINE)) < 0){ + emlwrite("Can't Read Copy: %s", errstr(errno)); + rv = -1; + break; /* get out now */ + } + + if(n == 0) /* done! */ + break; + + if(write(out, cb, n) != n){ + emlwrite("Can't Write Copy: %s", errstr(errno)); + rv = -1; + break; + } + } + + free(cb); + close(in); + close(out); + return(rv); +} + + +/* + * Open a file for writing. Return TRUE if all is well, and FALSE on error + * (cannot create). + */ +ffwopen(fn, readonly) +char *fn; +int readonly; +{ + int fd; + extern FIOINFO g_pico_fio; +#ifndef MODE_READONLY +#define MODE_READONLY (0600) +#endif + + /* + * Call open() by hand since we don't want O_TRUNC -- it'll + * screw over-quota users. The strategy is to overwrite the + * existing file's data and call ftruncate before close to lop + * off bytes + */ + + g_pico_fio.flags = FIOINFO_WRITE; + g_pico_fio.name = fn; + if((fd = open(fn, O_CREAT|O_WRONLY, readonly ? MODE_READONLY : 0666)) >= 0 + && (g_pico_fio.fp = fdopen(fd, "w")) != NULL + && fseek(g_pico_fio.fp, 0L, 0) == 0) + return (FIOSUC); + + emlwrite("Cannot open file for writing: %s", errstr(errno)); + return (FIOERR); +} + + +/* + * Close a file. Should look at the status in all systems. + */ +ffclose() +{ + extern FIOINFO g_pico_fio; + + errno = 0; + if((g_pico_fio.flags & FIOINFO_WRITE) + && (fflush(g_pico_fio.fp) == EOF + || ftruncate(fileno(g_pico_fio.fp), + (off_t) ftell(g_pico_fio.fp)) < 0)){ + emlwrite("\007Error preparing to close file: %s", errstr(errno)); + sleep(5); + } + + if (fclose(g_pico_fio.fp) == EOF) { + emlwrite("\007Error closing file: %s", errstr(errno)); + return(FIOERR); + } + + return(FIOSUC); +} + + + +#define EXTEND_BLOCK 1024 + + +/* + * ffelbowroom - make sure the destination's got enough room to receive + * what we're about to write... + */ +ffelbowroom() +{ + register LINE *lp; + register long n; + int x; + char s[EXTEND_BLOCK], *errstring = NULL; + struct stat fsbuf; + extern FIOINFO g_pico_fio; + + /* Figure out how much room do we need */ + /* first, what's total */ + for(n=0L, lp=lforw(curbp->b_linep); lp != curbp->b_linep; lp=lforw(lp)) + n += (llength(lp) + 1); + + errno = 0; /* make sure previous error are cleared */ + + if(fstat(fileno(g_pico_fio.fp), &fsbuf) == 0){ + n -= fsbuf.st_size; + + if(n > 0L){ /* must be growing file, extend it */ + memset(s, 'U', EXTEND_BLOCK); + if(fseek(g_pico_fio.fp, fsbuf.st_size, 0) == 0){ + for( ; n > 0L; n -= EXTEND_BLOCK){ + x = (n < EXTEND_BLOCK) ? (int) n : EXTEND_BLOCK; + if(fwrite(s, x * sizeof(char), 1, g_pico_fio.fp) != 1){ + errstring = errstr(errno); + break; + } + } + + if(!errstring + && (fflush(g_pico_fio.fp) == EOF + || fsync(fileno(g_pico_fio.fp)) < 0)) + errstring = errstr(errno); + + if(errstring) /* clean up */ + (void) ftruncate(fileno(g_pico_fio.fp), fsbuf.st_size); + else if(fseek(g_pico_fio.fp, 0L, 0) != 0) + errstring = errstr(errno); + } + else + errstring = errstr(errno); + } + } + else + errstring = errstr(errno); + + if(errstring){ + sprintf(s, "Error writing to %s: %s", g_pico_fio.name, errstring); + emlwrite(s, NULL); + (void) fclose(g_pico_fio.fp); + return(FALSE); + } + + return(TRUE); +} + + +/* + * P_open - run the given command in a sub-shell returning a file pointer + * from which to read the output + * + * note: + * For OS's other than unix, you will have to rewrite this function. + * Hopefully it'll be easy to exec the command into a temporary file, + * and return a file pointer to that opened file or something. + */ +FILE *P_open(s) +char *s; +{ + return(popen(s, "r")); +} + + + +/* + * P_close - close the given descriptor + * + */ +void +P_close(fp) +FILE *fp; +{ + pclose(fp); +} + + + +/* + * worthit - generic sort of test to roughly gage usefulness of using + * optimized scrolling. + * + * note: + * returns the line on the screen, l, that the dot is currently on + */ +worthit(l) +int *l; +{ + int i; /* l is current line */ + unsigned below; /* below is avg # of ch/line under . */ + + *l = doton(&i, &below); + below = (i > 0) ? below/(unsigned)i : 0; + + return(below > 3); +} + + + +/* + * pico_new_mail - just checks mtime and atime of mail file and notifies user + * if it's possible that they have new mail. + */ +pico_new_mail() +{ + int ret = 0; + static time_t lastchk = 0; + struct stat sbuf; + char inbox[256], *p; + + if(p = (char *)getenv("MAIL")) + /* fix unsafe sprintf - noticed by petter wahlman */ + sprintf(inbox, "%.*s", sizeof(inbox)-1, p); + else + sprintf(inbox,"%.*s/%.*s", sizeof(inbox)/3, MAILDIR, sizeof(inbox)/3, + (char *) getlogin()); + + if(stat(inbox, &sbuf) == 0){ + ret = sbuf.st_atime <= sbuf.st_mtime && + (lastchk < sbuf.st_mtime && lastchk < sbuf.st_atime); + lastchk = sbuf.st_mtime; + return(ret); + } + else + return(ret); +} + + + +/* + * time_to_check - checks the current time against the last time called + * and returns true if the elapsed time is > below. + * Newmail won't necessarily check, but we want to give it + * a chance to check or do a keepalive. + */ +time_to_check() +{ + static time_t lasttime = 0L; + + if(!timeo) + return(FALSE); + + if(time((time_t *) 0) - lasttime > (Pmaster ? (time_t)(FUDGE-10) : timeo)){ + lasttime = time((time_t *) 0); + return(TRUE); + } + else + return(FALSE); +} + + +/* + * sstrcasecmp - compare two pointers to strings case independently + */ +int +sstrcasecmp(s1, s2) + const QSType *s1, *s2; +{ + return((*pcollator)(*(char **)s1, *(char **)s2)); +} + + +/*-------------------------------------------------- + A case insensitive strcmp() + + Args: o, r -- The two strings to compare + + Result: integer indicating which is greater + ---*/ +int +strucmp(o, r) + register char *o, *r; +{ + if(o == NULL){ + if(r == NULL) + return 0; + else + return -1; + } + else if(r == NULL) + return 1; + + while(*o && *r + && ((isupper((unsigned char)(*o)) + ? (unsigned char)tolower((unsigned char)(*o)) + : (unsigned char)(*o)) + == (isupper((unsigned char)(*r)) + ? (unsigned char)tolower((unsigned char)(*r)) + : (unsigned char)(*r)))){ + o++; + r++; + } + + return((isupper((unsigned char)(*o)) + ? tolower((unsigned char)(*o)) + : (int)(unsigned char)(*o)) + - (isupper((unsigned char)(*r)) + ? tolower((unsigned char)(*r)) + : (int)(unsigned char)(*r))); +} + + +/*---------------------------------------------------------------------- + A case insensitive strncmp() + + Args: o, r -- The two strings to compare + n -- length to stop comparing strings at + + Result: integer indicating which is greater + + ----*/ +int +struncmp(o, r, n) + register char *o, + *r; + register int n; +{ + if(n < 1) + return 0; + + if(o == NULL){ + if(r == NULL) + return 0; + else + return -1; + } + else if(r == NULL) + return 1; + + n--; + while(n && *o && *r + && ((isupper((unsigned char)(*o)) + ? (unsigned char)tolower((unsigned char)(*o)) + : (unsigned char)(*o)) + == (isupper((unsigned char)(*r)) + ? (unsigned char)tolower((unsigned char)(*r)) + : (unsigned char)(*r)))){ + o++; + r++; + n--; + } + + return((isupper((unsigned char)(*o)) + ? tolower((unsigned char)(*o)) + : (int)(unsigned char)(*o)) + - (isupper((unsigned char)(*r)) + ? tolower((unsigned char)(*r)) + : (int)(unsigned char)(*r))); +} + + +/* + * chkptinit -- initialize anything we need to support composer + * checkpointing + */ +void +chkptinit(file, n) + char *file; + int n; +{ + unsigned pid; + char *chp; + + if(!file[0]){ + long gmode_save = gmode; + + if(gmode&MDCURDIR) + gmode &= ~MDCURDIR; /* so fixpath will use home dir */ + + strcpy(file, "#picoXXXXX#"); + fixpath(file, NLINE); + gmode = gmode_save; + } + else{ + int l = strlen(file); + + if(file[l-1] != '/'){ + file[l++] = '/'; + file[l] = '\0'; + } + + strcpy(file + l, "#picoXXXXX#"); + } + + pid = (unsigned)getpid(); + for(chp = file+strlen(file) - 2; *chp == 'X'; chp--){ + *chp = (pid % 10) + '0'; + pid /= 10; + } + + unlink(file); +} + +void +set_collation(collation, ctype) + int collation; + int ctype; +{ + extern int collator(); /* strcoll isn't declared on all systems */ +#ifdef LC_COLLATE + char *status = NULL; +#endif + + pcollator = strucmp; + +#ifdef LC_COLLATE + if(collation){ + /* + * This may not have the desired effect, if collator is not + * defined to be strcoll in os.h and strcmp and friends + * don't know about locales. If your system does have strcoll + * but we haven't defined collator to be strcoll in os.h, let us know. + */ + status = setlocale(LC_COLLATE, ""); + + /* + * If there is an error or if the locale is the "C" locale, then we + * don't want to use strcoll because in the default "C" locale strcoll + * uses strcmp ordering and we want strucmp ordering. + * + * The problem with this is that setlocale returns a string which is + * not equal to "C" on some systems even when the locale is "C", so we + * can't really tell on those systems. On some systems like that, we + * may end up with a strcmp-style collation instead of a strucmp-style. + * We recommend that the users of those systems explicitly set + * LC_COLLATE in their environment. + */ + if(status && !(status[0] == 'C' && status[1] == '\0')) + pcollator = collator; + } +#endif +#ifdef LC_CTYPE + if(ctype){ + (void)setlocale(LC_CTYPE, ""); + } +#endif +} + + +#ifdef RESIZING +/* + * winch_handler - handle window change signal + */ +SigType winch_handler SIG_PROTO((int sig)) +{ + signal(SIGWINCH, winch_handler); + ttresize(); + if(Pmaster && Pmaster->winch_cleanup && Pmaster->arm_winch_cleanup) + (*Pmaster->winch_cleanup)(); +} +#endif /* RESIZING */ + + +#ifdef SIGCHLD +/* + * child_handler - handle child status change signal + */ +SigType child_handler SIG_PROTO ((int sig)) +{ + pico_child_done = 1; + if(pico_child_jmp_ok){ +#ifdef sco + /* + * Villy Kruse says: + * This probably only affects older unix systems with a "broken" sleep + * function such as AT&T System V rel 3.2 and systems derived from + * that version. The problem is that the sleep function on these + * versions of unix will set up a signal handler for SIGALRM which + * will longjmp into the sleep function when the alarm goes off. + * This gives problems if another signal handler longjmps out of the + * sleep function, thus making the stack frame for the signal function + * invalid, and when the ALARM handler later longjmps back into the + * sleep function it does no longer have a valid stack frame. + * My sugested fix is to cancel the pending alarm in the SIGCHLD + * handler before longjmp'ing. This shouldn't hurt as there + * shouldn't be any ALARM pending at this point except possibly from + * the sleep call. + * + * + * [Even though it shouldn't hurt, we'll make it sco-specific for now.] + * + * + * The sleep call might have set up a signal handler which would + * longjmp back into the sleep code, and that would cause a crash. + */ + signal(SIGALRM, SIG_IGN); /* Cancel signal handeler */ + alarm(0); /* might longjmp back into sleep */ +#endif + longjmp(pico_child_state, 1); + } +} +#endif /* SIGCHLD */ + + +#ifdef POSIX_SIGNALS +/*---------------------------------------------------------------------- + Reset signals after critical imap code + ----*/ +SigType +(*posix_signal(sig_num, action))() + int sig_num; + SigType (*action)(); +{ + struct sigaction new_action, old_action; + + memset((void *)&new_action, 0, sizeof(struct sigaction)); + sigemptyset (&new_action.sa_mask); + new_action.sa_handler = action; +#ifdef SA_RESTART + new_action.sa_flags = SA_RESTART; +#else + new_action.sa_flags = 0; +#endif + sigaction(sig_num, &new_action, &old_action); + return(old_action.sa_handler); +} + +int +posix_sigunblock(mask) + int mask; +{ + sigset_t sig_mask; + + sigemptyset(&sig_mask); + sigaddset(&sig_mask, mask); + return(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL)); +} +#endif /* POSIX_SIGNALS */ + + +#if defined(sv3) || defined(ct) +/* Placed by rll to handle the rename function not found in AT&T */ +rename(oldname, newname) + char *oldname; + char *newname; +{ + int rtn; + + if ((rtn = link(oldname, newname)) != 0) { + perror("Was not able to rename file."); + return(rtn); + } + + if ((rtn = unlink(oldname)) != 0) + perror("Was not able to unlink file."); + + return(rtn); +} +#endif + + +#ifdef MOUSE + +/* + * init_mouse - check for xterm and initialize mouse tracking if present... + */ +init_mouse() +{ + if(mexist) + return(TRUE); + + if(getenv("DISPLAY")){ + mouseon(); + kpinsert("\033[M", KEY_XTERM_MOUSE, 1); + return(mexist = TRUE); + } + else + return(FALSE); +} + + +/* + * end_mouse - clear xterm mouse tracking if present... + */ +void +end_mouse() +{ + if(mexist){ + mexist = 0; /* just see if it exists here. */ + mouseoff(); + } +} + + +/* + * mouseexist - function to let outsiders know if mouse is turned on + * or not. + */ +mouseexist() +{ + return(mexist); +} + + +/* + * mouseon - call made available for programs calling pico to turn ON the + * mouse cursor. + */ +void +mouseon() +{ + fputs(XTERM_MOUSE_ON, stdout); +} + + +/* + * mouseon - call made available for programs calling pico to turn OFF the + * mouse cursor. + */ +void +mouseoff() +{ + fputs(XTERM_MOUSE_OFF, stdout); +} + + +/* + * checkmouse - look for mouse events in key menu and return + * appropriate value. + */ +int +checkmouse(ch, down, mcol, mrow) +unsigned *ch; +int down, mcol, mrow; +{ + static int oindex; + int i = 0, rv = 0; + MENUITEM *mp; + + if(!mexist || mcol < 0 || mrow < 0) + return(FALSE); + + if(down) /* button down */ + oindex = -1; + + for(mp = mfunc; mp; mp = mp->next) + if(mp->action && M_ACTIVE(mrow, mcol, mp)) + break; + + if(mp){ + unsigned long r; + + r = (*mp->action)(down ? M_EVENT_DOWN : M_EVENT_UP, + mrow, mcol, M_BUTTON_LEFT, 0); + if(r & 0xffff){ + *ch = (unsigned)((r>>16)&0xffff); + rv = TRUE; + } + } + else{ + while(1){ /* see if we understand event */ + if(i >= 12){ + i = -1; + break; + } + + if(M_ACTIVE(mrow, mcol, &menuitems[i])) + break; + + i++; + } + + if(down){ /* button down */ + oindex = i; /* remember where */ + if(i != -1 + && menuitems[i].label_hiliter != NULL + && menuitems[i].val != mnoop) /* invert label */ + (*menuitems[i].label_hiliter)(1, &menuitems[i]); + } + else{ /* button up */ + if(oindex != -1){ + if(i == oindex){ + *ch = menuitems[i].val; + rv = TRUE; + } + } + } + } + + /* restore label */ + if(!down + && oindex != -1 + && menuitems[oindex].label_hiliter != NULL + && menuitems[oindex].val != mnoop) + (*menuitems[oindex].label_hiliter)(0, &menuitems[oindex]); + + return(rv); +} + + +/* + * invert_label - highlight the label of the given menu item. + */ +void +invert_label(state, m) +int state; +MENUITEM *m; +{ + unsigned i, j; + int col_offset, savettrow, savettcol; + char *lp; + + get_cursor(&savettrow, &savettcol); + + /* + * Leave the command name bold + */ + col_offset = (state || !(lp=strchr(m->label, ' '))) ? 0 : (lp - m->label); + movecursor((int)m->tl.r, (int)m->tl.c + col_offset); + flip_inv(state); + + for(i = m->tl.r; i <= m->br.r; i++) + for(j = m->tl.c + col_offset; j <= m->br.c; j++) + if(i == m->lbl.r && j == m->lbl.c + col_offset && m->label){ + lp = m->label + col_offset; /* show label?? */ + while(*lp && j++ < m->br.c) + putc(*lp++, stdout); + + continue; + } + else + putc(' ', stdout); + + if(state) + flip_inv(FALSE); + + movecursor(savettrow, savettcol); +} +#endif /* MOUSE */ + + diff --git a/pico-win.lnk b/pico-win.lnk new file mode 100644 index 0000000..e5d9a93 --- /dev/null +++ b/pico-win.lnk @@ -0,0 +1,6 @@ +bdate+mswinver+main +pico +pico +libpico+libw+shell+toolhelp+llibcew+oldnames+commdlg+winsock+ +..\spell\spell +mswin.def diff --git a/pico.c b/pico.c new file mode 100644 index 0000000..36aba68 --- /dev/null +++ b/pico.c @@ -0,0 +1,1749 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: pico.c 14020 2005-03-31 17:08:28Z hubert $"; +#endif +/* + * Program: Main Pine Composer routines + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2005 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + * + * WEEMACS/PICO NOTES: + * + * 01 Nov 89 - MicroEmacs 3.6 vastly pared down and becomes a function call + * weemacs() and plugged into the Pine mailer. Lots of unused + * MicroEmacs code laying around. + * + * 17 Jan 90 - weemacs() became weemacs() the composer. Header editing + * functions added. + * + * 09 Sep 91 - weemacs() renamed pico() for the PIne COmposer. + * + */ + + +/* + * This program is in public domain; written by Dave G. Conroy. + * This file contains the main driving routine, and some keyboard processing + * code, for the MicroEMACS screen editor. + * + * REVISION HISTORY: + * + * 1.0 Steve Wilhite, 30-Nov-85 + * - Removed the old LK201 and VT100 logic. Added code to support the + * DEC Rainbow keyboard (which is a LK201 layout) using the the Level + * 1 Console In ROM INT. See "rainbow.h" for the function key defs + * Steve Wilhite, 1-Dec-85 + * - massive cleanup on code in display.c and search.c + * + * 2.0 George Jones, 12-Dec-85 + * - Ported to Amiga. + * + * 3.0 Daniel Lawrence, 29-Dec-85 + * 16-apr-86 + * - updated documentation and froze development for 3.6 net release + */ + +/* make global definitions not external */ +#define maindef + +#include "headers.h" +#include "ebind.h" /* default key bindings */ + + +void func_init PROTO((void)); +void breplace PROTO((void *)); +int any_header_changes PROTO((void)); +int cleanwhitespace PROTO((void)); +int isquotedspace PROTO((LINE *)); +#ifdef _WINDOWS +int composer_file_drop PROTO((int, int, char *)); +#endif + + +/* + * function key mappings + */ +static int pfkm[12][2] = { + { F1, (CTRL|'G')}, + { F2, (CTRL|'C')}, + { F3, (CTRL|'X')}, + { F4, (CTRL|'J')}, + { F5, (CTRL|'R')}, + { F6, (CTRL|'W')}, + { F7, (CTRL|'Y')}, + { F8, (CTRL|'V')}, + { F9, (CTRL|'K')}, + { F10, (CTRL|'U')}, + { F11, (CTRL|'O')}, +#ifdef SPELLER + { F12, (CTRL|'T')} +#else + { F12, (CTRL|'D')} +#endif +}; + + +/* + * flag for the various functions in pico() to set when ready + * for pico() to return... + */ +int pico_all_done = 0; +jmp_buf finstate; +char *pico_anchor = NULL; +extern struct headerentry *headents; + +/* + * pico - the main routine for Pine's composer. + * + */ +pico(pm) +PICO *pm; +{ + register int c; + register int f; + register int n; + char bname[NBUFN]; /* buffer name of file to read */ + extern struct on_display ods; + int checkpointcnt = 0, input = 0; + char chkptfile[NLINE]; +#ifdef _WINDOWS + int cursor_shown; +#endif + + Pmaster = pm; + gmode = MDWRAP; + gmode |= pm->pine_flags; /* high 4 bits rsv'd for pine */ + + alt_speller = pm->alt_spell; + pico_all_done = 0; + km_popped = 0; + + if(!vtinit()) /* Init Displays. */ + return(COMP_CANCEL); + + strcpy(bname, "main"); /* default buffer name */ + edinit(bname); /* Buffers, windows. */ + + if(InitMailHeader(pm)) /* init mail header structure */ + gmode &= ~(P_BODY | P_HEADEND); /* flip off special header stuff */ + + /* setup to process commands */ + lastflag = 0; /* Fake last flags. */ + curbp->b_mode |= gmode; /* and set default modes*/ + + pico_anchor = (char *)malloc((strlen(Pmaster->pine_anchor) + 1) + * sizeof(char)); + if(pico_anchor) + strcpy(pico_anchor, Pmaster->pine_anchor); + + bindtokey(DEL, (gmode & P_DELRUBS) ? forwdel : backdel); + + if(pm->msgtext) + breplace(pm->msgtext); + +#ifdef _WINDOWS + cursor_shown = mswin_showcaret(1); /* turn on for main window */ + mswin_allowpaste(MSWIN_PASTE_FULL); + mswin_setscrollcallback (pico_scroll_callback); +#endif + + /* prepare for checkpointing */ + chkptfile[0] = '\0'; + chkptinit((*Pmaster->ckptdir)(chkptfile, NLINE), NLINE); + if(gmode & P_CHKPTNOW) + writeout(chkptfile, TRUE); + + pico_all_done = setjmp(finstate); /* jump out of HUP handler ? */ + + if(gmode & MDALTNOW){ + while(!pico_all_done){ + if(((gmode & P_BODY) || !Pmaster->headents) + && alt_editor(0, 1) < 0) + break; /* if problem, drop into pico */ + + if(Pmaster->headents){ + update(); /* paint screen, n' start editing... */ + HeaderEditor((gmode & (P_HEADEND | P_BODY)) ? 2 : 0, 0); + gmode |= P_BODY; /* make sure we enter alt ed next */ + } + else + pico_all_done = COMP_EXIT; + } + } + else if(!pico_all_done){ + if(gmode & P_BODY){ /* begin editing the header? */ + ArrangeHeader(); /* line up pointers */ + /* + * Move to the offset pine asked us to move to. + * Perhaps we should be checking to see if this is + * a reasonable number before moving. + */ + if(Pmaster && Pmaster->edit_offset) + forwchar(FALSE, Pmaster->edit_offset); + } + else{ + update(); /* paint screen, */ + HeaderEditor((gmode & P_HEADEND) ? 2 : 0, 0); + } + } + + while(1){ + if(pico_all_done){ +#ifdef _WINDOWS + if(!cursor_shown) + mswin_showcaret(0); + + mswin_allowpaste(MSWIN_PASTE_DISABLE); + mswin_setscrollcallback (NULL); +#endif + c = anycb() ? BUF_CHANGED : 0; + switch(pico_all_done){ /* prepare for/handle final events */ + case COMP_EXIT : /* already confirmed */ + packheader(); + if(Pmaster + && (Pmaster->strip_ws_before_send + || Pmaster->allow_flowed_text)) + cleanwhitespace(); + c |= COMP_EXIT; + break; + + case COMP_CANCEL : /* also already confirmed */ + packheader(); + c = COMP_CANCEL; + break; + + case COMP_GOTHUP: + /* + * pack up and let caller know that we've received a SIGHUP + */ + if(ComposerEditing) /* expand addr if needed */ + call_builder(&headents[ods.cur_e], NULL, NULL); + + packheader(); + c |= COMP_GOTHUP; + break; + + case COMP_SUSPEND : + default: /* safest if internal error */ + /* + * If we're in the headers mark the current header line + * with start_here bit so caller knows where to reset. + * Also set the edit_offset, which is either the offset + * into this header line or the offset into the body. + * Packheader will adjust edit_offset for multi-line + * headers. + */ + if(ComposerEditing){ /* in the headers */ + headents[ods.cur_e].start_here = 1; + Pmaster->edit_offset = ods.p_off; + } + else{ + register LINE *clp; + register long offset; + + for(clp = lforw(curbp->b_linep), offset = 0L; + clp != curwp->w_dotp; + clp = lforw(clp)) + offset += (llength(clp) + 1); + + Pmaster->edit_offset = offset + curwp->w_doto; + } + + packheader(); + c |= COMP_SUSPEND; + break; + } + + free(pico_anchor); + vttidy(); /* clean up tty modes */ + zotdisplay(); /* blast display buffers */ + zotedit(); + unlink(chkptfile); + Pmaster = NULL; /* blat global */ + + return(c); + } + + if(km_popped){ + km_popped--; + if(km_popped == 0) /* cause bottom three lines to be repainted */ + curwp->w_flag |= WFHARD; + } + + if(km_popped){ /* temporarily change to cause menu to be painted */ + term.t_mrow = 2; + curwp->w_ntrows -= 2; + curwp->w_flag |= WFMODE; + movecursor(term.t_nrow-2, 0); /* clear status line, too */ + peeol(); + } + + update(); /* Fix up the screen */ + if(km_popped){ + term.t_mrow = 0; + curwp->w_ntrows += 2; + } + +#ifdef MOUSE +#ifdef EX_MOUSE + /* New mouse function for real mouse text seletion. */ + register_mfunc(mouse_in_pico, 2, 0, term.t_nrow - (term.t_mrow+1), + term.t_ncol); +#else + mouse_in_content(KEY_MOUSE, -1, -1, -1, 0); + register_mfunc(mouse_in_content, 2, 0, term.t_nrow - (term.t_mrow + 1), + term.t_ncol); +#endif +#endif +#ifdef _WINDOWS + mswin_setdndcallback (composer_file_drop); + mswin_mousetrackcallback(pico_cursor); +#endif + c = GetKey(); + if (term.t_nrow < 6 && c != NODATA){ + (*term.t_beep)(); + emlwrite("Please make the screen bigger.", NULL); + continue; + } + +#ifdef MOUSE +#ifdef EX_MOUSE + clear_mfunc(mouse_in_pico); +#else + clear_mfunc(mouse_in_content); +#endif +#endif +#ifdef _WINDOWS + mswin_cleardndcallback (); + mswin_mousetrackcallback(NULL); +#endif + if(c == NODATA || time_to_check()){ /* new mail ? */ + if((*Pmaster->newmail)(c == NODATA ? 0 : 2, 1) >= 0){ + int rv; + + if(km_popped){ + term.t_mrow = 2; + curwp->w_ntrows -= 2; + curwp->w_flag |= WFHARD; + km_popped = 0; + } + + clearcursor(); + mlerase(); + rv = (*Pmaster->showmsg)(c); + ttresize(); + picosigs(); /* restore altered handlers */ + if(rv) /* Did showmsg corrupt the display? */ + PaintBody(0); /* Yes, repaint */ + + mpresf = 1; + input = 0; + } + + clearcursor(); + movecursor(0, 0); + } + + if(km_popped) + switch(c){ + case NODATA: + case (CTRL|'L'): + km_popped++; + break; + + default: + mlerase(); + break; + } + + if(c == NODATA) /* no op, getkey timed out */ + continue; + else if(!input++) + (*Pmaster->keybinput)(); + + if (mpresf != FALSE) { /* message stay around only */ + if (mpresf++ > NMMESSDELAY) /* so long! */ + mlerase(); + } + + f = FALSE; /* vestigial */ + n = 1; + /* Do it. */ + execute(normalize_cmd(c, pfkm, 2), f, n); + if(++checkpointcnt >= CHKPTDELAY){ + checkpointcnt = 0; + writeout(chkptfile, TRUE); + } + } +} + +/* + * Initialize all of the buffers and windows. The buffer name is passed down + * as an argument, because the main routine may have been told to read in a + * file by default, and we want the buffer name to be right. + */ + +/* + * For the pine composer, we don't want to take over the whole screen + * for editing. the first some odd lines are to be used for message + * header information editing. + */ +void +edinit(bname) +char bname[]; +{ + register BUFFER *bp; + register WINDOW *wp; + + if(Pmaster) + func_init(); + + bp = bfind(bname, TRUE, BFWRAPOPEN); /* First buffer */ + wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window */ + + if (bp==NULL || wp==NULL){ + if(Pmaster) + return; + else + exit(1); + } + + curbp = bp; /* Make this current */ + wheadp = wp; + curwp = wp; + wp->w_wndp = NULL; /* Initialize window */ + wp->w_bufp = bp; + bp->b_nwnd = 1; /* Displayed. */ + wp->w_linep = bp->b_linep; + wp->w_dotp = bp->b_linep; + wp->w_doto = 0; + wp->w_markp = wp->w_imarkp = NULL; + wp->w_marko = wp->w_imarko = 0; + bp->b_linecnt = -1; + + if(Pmaster){ + term.t_mrow = Pmaster->menu_rows; + wp->w_toprow = ComposerTopLine = COMPOSER_TOP_LINE; + wp->w_ntrows = term.t_nrow - COMPOSER_TOP_LINE - term.t_mrow; + fillcol = Pmaster->fillcolumn; + strcpy(opertree, + (Pmaster->oper_dir && strlen(Pmaster->oper_dir) < NLINE) + ? Pmaster->oper_dir : ""); + } + else{ + if(sup_keyhelp) + term.t_mrow = 0; + else + term.t_mrow = 2; + + wp->w_toprow = 2; + wp->w_ntrows = term.t_nrow - 2 - term.t_mrow; + if(userfillcol > 0) /* set fill column */ + fillcol = userfillcol; + else + fillcol = term.t_ncol - 6; + } + + /* + * MDSCUR mode implies MDTREE mode with a opertree of home directory, + * unless opertree has been set differently. + */ + if((gmode & MDSCUR) && !opertree[0]) + strncpy(opertree, gethomedir(NULL), NLINE); + + if(*opertree) + fixpath(opertree, NLINE); + + wp->w_force = 0; + wp->w_flag = WFMODE|WFHARD; /* Full. */ +} + + +/* + * This is the general command execution routine. It handles the fake binding + * of all the keys to "self-insert". It also clears out the "thisflag" word, + * and arranges to move it to the "lastflag", so that the next command can + * look at it. Return the status of command. + */ +execute(c, f, n) +int c, f, n; +{ + register KEYTAB *ktp; + register int status; + + ktp = (Pmaster) ? &keytab[0] : &pkeytab[0]; + + while (ktp->k_fp != NULL) { + if (ktp->k_code == c) { + + if(lastflag&CFFILL){ + curwp->w_flag |= WFMODE; + if(Pmaster == NULL) + sgarbk = TRUE; + } + + thisflag = 0; + status = (*ktp->k_fp)(f, n); + if((lastflag & CFFILL) && !(thisflag & CFFILL)) + fdelete(); + if((lastflag & CFFLBF) && !(thisflag & CFFLBF)) + kdelete(); + + lastflag = thisflag; + + /* + * Reset flag saying wrap should open a new line whenever + * we execute a command (as opposed to just typing in text). + * However, if that command leaves us in the same line on the + * screen, then don't reset. + */ + if(curwp->w_flag & (WFMOVE | WFHARD)) + curbp->b_flag |= BFWRAPOPEN; /* wrap should open new line */ + + return (status); + } + ++ktp; + } + + if(lastflag & CFFILL) /* blat unusable fill data */ + fdelete(); + if(lastflag & CFFLBF) + kdelete(); + + if (VALID_KEY(c)) { /* Self inserting. */ + + if (n <= 0) { /* Fenceposts. */ + lastflag = 0; + return (n<0 ? FALSE : TRUE); + } + thisflag = 0; /* For the future. */ + + /* do the appropriate insertion */ + /* pico never does C mode, this is simple */ + status = linsert(n, c); + + /* + * Check to make sure we didn't go off of the screen + * with that character. Take into account tab expansion. + * If so wrap the line... + */ + if(curwp->w_bufp->b_mode & MDWRAP){ + register int j; + register int k; + + for(j = k = 0; j < llength(curwp->w_dotp); j++, k++) + if(isspace((unsigned char)lgetc(curwp->w_dotp, j).c)){ + if(lgetc(curwp->w_dotp, j).c == TAB) + while(k+1 & 0x07) + k++; + } + else if(k >= fillcol){ + wrapword(); + break; + } + } + + lastflag = thisflag; + return (status); + } + + if(c&CTRL) + emlwrite("\007Unknown Command: ^%c", (void *)(c&0xff)); + else + emlwrite("\007Unknown Command", NULL); + + lastflag = 0; /* Fake last flags. */ + return (FALSE); +} + + + +/* + * Fancy quit command, as implemented by Norm. If the any buffer has + * changed do a write on that buffer and exit emacs, otherwise simply exit. + */ +int +quickexit(f, n) +int f, n; +{ + register BUFFER *bp; /* scanning pointer to buffers */ + + bp = bheadp; + while (bp != NULL) { + if ((bp->b_flag&BFCHG) != 0 /* Changed. */ + && (bp->b_flag&BFTEMP) == 0) { /* Real. */ + curbp = bp; /* make that buffer cur */ + filesave(f, n); + } + bp = bp->b_bufp; /* on to the next buffer */ + } + return(wquit(f, n)); /* conditionally quit */ +} + + + +/* + * abort_composer - ask the question here, then go quit or + * return FALSE + */ +abort_composer(f, n) +int f, n; +{ + char *result; + + result = ""; + + Pmaster->arm_winch_cleanup++; + if(Pmaster->canceltest){ + if(((Pmaster->pine_flags & MDHDRONLY) && !any_header_changes()) + || (result = (*Pmaster->canceltest)(redraw_pico_for_callback))){ + pico_all_done = COMP_CANCEL; + emlwrite(result, NULL); + Pmaster->arm_winch_cleanup--; + return(TRUE); + } + else{ + emlwrite("Cancel Cancelled", NULL); + curwp->w_flag |= WFMODE; /* and modeline so we */ + sgarbk = TRUE; /* redraw the keymenu */ + pclear(term.t_nrow - 1, term.t_nrow + 1); + Pmaster->arm_winch_cleanup--; + return(FALSE); + } + } + else switch(mlyesno(Pmaster->headents + ? "Cancel message (answering \"Yes\" will abandon your mail message)" + : (anycb() == FALSE) + ? "Cancel Edit (and abandon changes)" + : "Cancel Edit", + FALSE)){ + case TRUE: + pico_all_done = COMP_CANCEL; + return(TRUE); + + case ABORT: + emlwrite("\007Cancel Cancelled", NULL); + break; + + default: + mlerase(); + } + return(FALSE); +} + + +/* + * suspend_composer - return to pine with what's been edited so far + */ +suspend_composer(f, n) +int f, n; +{ + if(Pmaster && Pmaster->headents) + pico_all_done = COMP_SUSPEND; + else + (*term.t_beep)(); + + return(TRUE); +} + + + +/* + * Quit command. If an argument, always quit. Otherwise confirm if a buffer + * has been changed and not written out. Normally bound to "C-X C-C". + */ +wquit(f, n) +int f, n; +{ + register int s; + + if(Pmaster){ + char *result; + + /* First, make sure there are no outstanding problems */ + if(AttachError()){ + emlwrite("\007Problem with attachments! Fix errors or delete attachments.", NULL); + return(FALSE); + } + +#ifdef SPELLER + if(Pmaster->always_spell_check) + if(spell(0, 0) == -1) + sleep(3); /* problem, show error */ +#endif + /* + * if we're not in header, show some of it as we verify sending... + */ + display_for_send(); + packheader(); + Pmaster->arm_winch_cleanup++; + if((!(Pmaster->pine_flags & MDHDRONLY) || any_header_changes()) + && (result = (*Pmaster->exittest)(Pmaster->headents, + redraw_pico_for_callback, + Pmaster->allow_flowed_text))){ + Pmaster->arm_winch_cleanup--; + if(sgarbf) + update(); + + lchange(WFHARD); /* set update flags... */ + curwp->w_flag |= WFMODE; /* and modeline so we */ + sgarbk = TRUE; /* redraw the keymenu */ + pclear(term.t_nrow - 2, term.t_nrow + 1); + if(*result) + emlwrite(result, NULL); + } + else{ + Pmaster->arm_winch_cleanup--; + pico_all_done = COMP_EXIT; + return(TRUE); + } + } + else{ + if (f != FALSE /* Argument forces it. */ + || anycb() == FALSE /* All buffers clean. */ + /* User says it's OK. */ + || (s=mlyesno("Save modified buffer (ANSWERING \"No\" WILL DESTROY CHANGES)", -1)) == FALSE) { + vttidy(); +#if defined(USE_TERMCAP) || defined(USE_TERMINFO) || defined(VMS) + kbdestroy(kbesc); +#endif + exit(0); + } + + if(s == TRUE){ + if(filewrite(0,1) == TRUE) + wquit(1, 0); + } + else if(s == ABORT){ + emlwrite("Exit cancelled", NULL); + if(term.t_mrow == 0) + curwp->w_flag |= WFHARD; /* cause bottom 3 lines to paint */ + } + return(s); + } + + return(FALSE); +} + + +/* + * Has any editing been done to headers? + */ +any_header_changes() +{ + struct headerentry *he; + + for(he = Pmaster->headents; he->name != NULL; he++) + if(he->dirty) + break; + + return(he->name && he->dirty); +} + +int +isquotedspace(line) + LINE *line; +{ + int i, was_quote = 0; + for(i = 0; i < llength(line); i++){ + if(lgetc(line, i).c == '>') + was_quote = 1; + else if(was_quote && lgetc(line, i).c == ' '){ + if(i+1 < llength(line) && isspace(lgetc(line,i+1).c)) + return 1; + else + return 0; + } + else + return 0; + } + return 0; +} + +/* + * This function serves two purposes, 1) to strip white space when + * Pmaster asks that the composition have its trailing white space + * stripped, or 2) to prepare the text as flowed text, as Pmaster + * is telling us that we're working with flowed text. + * + * What flowed currently means to us is stripping all trailing white + * space, except for one space if the following line is a continuation + * of the paragraph. Also, we space-stuff all lines beginning + * with white-space, and leave siglines alone. + */ +int +cleanwhitespace() +{ + LINE *cur_line = NULL, *cursor_dotp = NULL, **lp = NULL; + int i = 0, cursor_doto = 0, is_cursor_line = 0; + + cursor_dotp = curwp->w_dotp; + cursor_doto = curwp->w_doto; + gotobob(FALSE, 1); + + for(lp = &curwp->w_dotp; (*lp) != curbp->b_linep; (*lp) = lforw(*lp)){ + if(!(llength(*lp) == 3 + && lgetc(*lp, 0).c == '-' + && lgetc(*lp, 1).c == '-' + && lgetc(*lp, 2).c == ' ') + && llength(*lp)){ + is_cursor_line = (cursor_dotp == (*lp)); + /* trim trailing whitespace, to be added back if flowing */ + for(i = llength(*lp); i; i--) + if(!isspace(lgetc(*lp, i - 1).c)) + break; + if(i != llength(*lp)){ + int flow_line = 0; + + if(Pmaster && !Pmaster->strip_ws_before_send + && lforw(*lp) != curbp->b_linep + && llength(lforw(*lp)) + && !(isspace(lgetc(lforw(*lp), 0).c) + || isquotedspace(lforw(*lp))) + && !(llength(lforw(*lp)) == 3 + && lgetc(lforw(*lp), 0).c == '-' + && lgetc(lforw(*lp), 1).c == '-' + && lgetc(lforw(*lp), 2).c == ' ')) + flow_line = 1; + if(flow_line && i && lgetc(*lp, i).c == ' '){ + /* flowed line ending with space */ + i++; + if(i != llength(*lp)){ + curwp->w_doto = i; + ldelete(llength(*lp) - i, NULL); + } + } + else if(flow_line && i && isspace(lgetc(*lp, i).c)){ + /* flowed line ending with whitespace other than space*/ + curwp->w_doto = i; + ldelete(llength(*lp) - i, NULL); + linsert(1, ' '); + } + else{ + curwp->w_doto = i; + ldelete(llength(*lp) - i, NULL); + } + } + if(Pmaster && Pmaster->allow_flowed_text + && llength(*lp) && isspace(lgetc(*lp, 0).c)){ + /* space-stuff only if flowed */ + curwp->w_doto = 0; + if(is_cursor_line && cursor_doto) + cursor_doto++; + linsert(1, ' '); + } + if(is_cursor_line) + cursor_dotp = (*lp); + } + } + + /* put the cursor back where we found it */ + gotobob(FALSE, 1); + curwp->w_dotp = cursor_dotp; + curwp->w_doto = (cursor_doto < llength(curwp->w_dotp)) + ? cursor_doto : llength(curwp->w_dotp) - 1; + + return(0); +} + +/* + * Remove all trailing white space from the text + */ +int +stripwhitespace() +{ + int i; + LINE *cur_line = lforw(curbp->b_linep); + + do{ + /* we gotta test for the sigdash case here */ + if(!(cur_line->l_used == 3 && + lgetc(cur_line, 0).c == '-' && + lgetc(cur_line, 1).c == '-' && + lgetc(cur_line, 2).c == ' ')) + for(i = cur_line->l_used - 1; i >= 0; i--) + if(isspace(lgetc(cur_line, i).c)) + cur_line->l_used--; + else + break; + }while((cur_line = lforw(cur_line)) != curbp->b_linep); + return 0; +} + +/* + * Abort. + * Beep the beeper. Kill off any keyboard macro, etc., that is in progress. + * Sometimes called as a routine, to do general aborting of stuff. + */ +ctrlg(f, n) +int f, n; +{ + emlwrite("Cancelled", NULL); + return (ABORT); +} + + +/* tell the user that this command is illegal while we are in + * VIEW (read-only) mode + */ +rdonly() +{ + (*term.t_beep)(); + emlwrite("Key illegal in VIEW mode", NULL); + return(FALSE); +} + + + +/* + * reset all globals to their initial values + */ +void +func_init() +{ + extern int vtrow; + extern int vtcol; + extern int lbound; + + /* + * re-initialize global buffer type variables .... + */ + fillcol = (term.t_ncol > 80) ? 77 : term.t_ncol - 6; + eolexist = TRUE; + revexist = FALSE; + sgarbf = TRUE; + mpresf = FALSE; + mline_open = FALSE; + ComposerEditing = FALSE; + + /* + * re-initialize hardware display variables .... + */ + vtrow = vtcol = lbound = 0; + clearcursor(); + + pat[0] = rpat[0] = '\0'; + browse_dir[0] = '\0'; +} + + +/* + * pico_help - help function for standalone composer + */ +pico_help(text, title, i) +char *text[], *title; +int i; +{ + register int numline = 0; + char **p; + + p = text; + while(*p++ != NULL) + numline++; + return(wscrollw(COMPOSER_TOP_LINE, term.t_nrow-1, text, numline)); +} + + + +/* + * zotedit() - kills the buffer and frees all lines associated with it!!! + */ +void +zotedit() +{ + wheadp->w_linep = wheadp->w_dotp = wheadp->w_markp = wheadp->w_imarkp = NULL; + bheadp->b_linep = bheadp->b_dotp = bheadp->b_markp = NULL; + + free((char *) wheadp); /* clean up window */ + wheadp = NULL; + curwp = NULL; + + free((char *) bheadp); /* clean up buffers */ + bheadp = NULL; + curbp = NULL; + + zotheader(); /* blast header lines */ + + kdelete(); /* blast kill buffer */ + +} + + +#ifdef MOUSE +/* + * Generic mouse handling functions + */ +MENUITEM menuitems[12]; /* key labels and functions */ +MENUITEM *mfunc = NULL; /* list of regional functions */ +mousehandler_t mtrack; /* mouse tracking handler */ + +/* last mouse position */ +static int levent = 0, lrow = 0, lcol = 0, doubleclick, lbutton, lflags; +#ifdef DOS +static clock_t lastcalled = 0; +#else +static time_t lastcalled = 0; +#endif +static mousehandler_t lastf; + + +/* + * register_mfunc - register the given function to get called + * on mouse events in the given display region + */ +register_mfunc(f, tlr, tlc, brr, brc) +mousehandler_t f; +int tlr, tlc, brr, brc; +{ + MENUITEM **mp; + + if(!mouseexist()) + return(FALSE); + + for(mp = &mfunc; *mp; mp = &(*mp)->next) + ; + + *mp = (MENUITEM *)malloc(sizeof(MENUITEM)); + memset(*mp, 0, sizeof(MENUITEM)); + + (*mp)->action = f; + (*mp)->tl.r = tlr; + (*mp)->br.r = brr; + (*mp)->tl.c = tlc; + (*mp)->br.c = brc; + (*mp)->lbl.c = (*mp)->lbl.r = 0; + (*mp)->label = ""; + return(TRUE); +} + + +/* + * clear_mfunc - clear any previously set mouse function + */ +void +clear_mfunc(f) +mousehandler_t f; +{ + MENUITEM *mp, *tp; + + if(mp = mfunc){ + if(mp->action == f) + mfunc = mp->next; + else + for(tp = mp; tp->next; tp = tp->next) + if(tp->next->action == f){ + mp = tp->next; + tp->next = tp->next->next; + break; + } + + if(mp){ + mp->action = NULL; + free(mp); + } + } +} + + + +#ifdef EX_MOUSE + +void +clear_mtrack () +{ + mtrack = NULL; + mswin_allowmousetrack (FALSE); +} + + +void +register_mtrack (f) +mousehandler_t f; +{ + if (f) { + mtrack = f; + mswin_allowmousetrack (TRUE); + } + else + clear_mtrack (); +} + + +static void +move_dot_to (row, col) + int row, col; +{ + LINE *lp; + int i; + + lp = curwp->w_linep; + i = row - ((Pmaster) ? ComposerTopLine : 2); + while(i-- && lp != curbp->b_linep) /* count from top */ + lp = lforw(lp); + curgoal = col; + curwp->w_dotp = lp; /* to new dot. */ + curwp->w_doto = getgoal(lp); + curwp->w_flag |= WFMOVE; +} + + +/* + * mouse_in_pico + * + * When the mouse goes down in the body we set the mark and start + * tracking. + * + * As the mouse moves we update the dot and redraw the screen. + * + * If the mouse moves above or below the pico body region of the + * screen we scroll the text and update the dot position. + * + * When the mouse comes up we clean up. If the mouse did not + * move, then we clear the mark and turn off the selection. + * + * Most of the mouse processing is handled here. The exception is + * mouse down in the header. Can't call HeaderEditor() from here so + * we send up the KEY_MOUSE character, which gets dispatched to + * mousepress(), which _can_ call HeaderEditor(). + */ +unsigned long +mouse_in_pico(mevent, row, col, button, flags) + int mevent; + int row, col, button, flags; +{ + unsigned long rv = 0; /* Our return value. */ + int trow, tcol; /* translated row and col. */ + + static int lheader = FALSE; /* Mouse down was in header. */ + + + /* + * What's up. + */ + switch (mevent) { + case M_EVENT_DOWN: + if(button != M_BUTTON_LEFT) + break; + + /* Ignore mouse down if not in pico body region. */ + if (row < 2 || row > term.t_nrow - (term.t_mrow+1)) { + clear_mtrack (); + break; + } + + /* Detect double clicks. Not that we do anything with em, just + * detect them. */ +#ifdef DOS +#ifdef CLOCKS_PER_SEC + doubleclick = (lrow == row && lcol == col + && clock() < (lastcalled + CLOCKS_PER_SEC/2)); +#else +#ifdef CLK_TCK +doubleclick = (lrow == row && lcol == col + && clock() < (lastcalled + CLK_TCK/2)); +#else + doubleclick = FALSE; +#endif +#endif + lastcalled = clock(); +#else + doubleclick = (lrow == row && lcol == col + && time(0) < (lastcalled + 2)); + lastcalled = time(0); +#endif + lheader = FALSE; /* Rember mouse down position. */ + levent = mevent; + lrow = row; + lcol = col; + lbutton = button; + lflags = flags; + + /* Mouse down in body? */ + if (row < (Pmaster ? ComposerTopLine : 2)) { + /* Mouse down in message header -> no tracking, just remember + * where */ + lheader = TRUE; + } + else { + /* Mouse down in message. + * If no shift key and an existing mark -> clear the mark. + * If shift key and no existing mark -> set mark before moving */ + if (!(flags & M_KEY_SHIFT) && curwp->w_markp) + setmark (0,1); /* this clears the mark. */ + else if (flags & M_KEY_SHIFT && !curwp->w_markp) + setmark (0,1); /* while this sets the mark. */ + + /* Reposition dot to mouse down. */ + move_dot_to (row, col); + + /* Set the mark to dot if no existing mark. */ + if (curwp->w_markp == NULL) + setmark (0,1); + + /* Track mouse movement. */ + register_mtrack (mouse_in_pico); + update (); + lheader = FALSE; /* Just to be sure. */ + } + break; + + + case M_EVENT_TRACK: + /* Mouse tracking. */ + if (lheader) /* Ignore mouse movement in header. */ + break; + + /* If above or below body, scroll body and adjust the row and col. */ + if (row < (Pmaster ? ComposerTopLine : 2)) { + /* Scroll text down screen and move dot to top left corner. */ + scrollupline (0,1); + trow = (Pmaster) ? ComposerTopLine : 2; + tcol = 0; + } + else if (row > term.t_nrow - (term.t_mrow + 1)) { + /* Scroll text up screen and move dot to bottom right corner. */ + scrolldownline (0,1); + trow = term.t_nrow - (term.t_mrow + 1); + tcol = term.t_ncol; + } + else { + trow = row; + tcol = col; + } + + /* Move dot to target column. */ + move_dot_to (trow, tcol); + + /* Update screen. */ + update (); + break; + + + case M_EVENT_UP: + if(button == M_BUTTON_RIGHT){ +#ifdef _WINDOWS + pico_popup(); +#endif + break; + } + else if(button != M_BUTTON_LEFT) + break; + + if (lheader) { + lheader = FALSE; + /* Last down in header. */ + if (row == lrow && col == lcol) { + /* Mouse up and down in same place in header. Means the + * user want to edit the header. Return KEY_MOUSE which + * will cause mousepress to be called, which will + * call HeaderEditor. Can't call HeaderEditor from here + * because that would mess up layering. */ + if (curwp->w_marko) + setmark (0,1); + rv = ((unsigned long)KEY_MOUSE << 16) | TRUE; + } + } + else { + /* If up at same place, clear mark */ + if (curwp->w_markp == curwp->w_dotp && + curwp->w_marko == curwp->w_doto) { + setmark (0,1); + curwp->w_flag |= WFMOVE; + } + clear_mtrack (); + update (); + } + break; + } + + return(rv); +} +#endif + + + +/* + * mouse_in_content - general mechanism used to pass recognized mouse + * events in predefined region back thru the usual + * keyboard input stream. The actual return value + * passed back from this function is set dynamically + * via the "down" argument which is read when both the + * "row" and "col" arguments are negative. + */ +unsigned long +mouse_in_content(mevent, row, col, button, flags) + int mevent; + int row, col, button, flags; +{ + unsigned long rv = 0; + static unsigned mouse_val = KEY_MOUSE; + + if(row == -1 && col == -1){ + mouse_val = mevent; /* setting return value */ + } + else { + /* A real event. */ + levent = mevent; + switch (mevent) { + case M_EVENT_DOWN: + /* Mouse down does not mean anything, just keep track of + * where it went down and if this is a double click. */ +#ifdef DOS +#ifdef CLOCKS_PER_SEC + doubleclick = (lrow == row && lcol == col + && clock() < (lastcalled + CLOCKS_PER_SEC/2)); +#else +#ifdef CLK_TCK + doubleclick = (lrow == row && lcol == col + && clock() < (lastcalled + CLK_TCK/2)); +#else + doubleclick = FALSE; +#endif +#endif + lastcalled = clock(); +#else + doubleclick = (lrow == row && lcol == col + && time(0) < (lastcalled + 2)); + lastcalled = time(0); +#endif + lrow = row; + lcol = col; + lbutton = button; + lflags = flags; + break; + + case M_EVENT_UP: + /* Mouse up. If in the same position as it went down + * then we return the value set above, which goes into + * the character input stream, which gets processed as + * a mouse event by some upper layer, which calls to + * mouse_get_last(). */ + if (lrow == row && lcol == col) { + rv = mouse_val; + rv = (rv << 16) | TRUE; + } + break; + + case M_EVENT_TRACK: + break; + } + } + + return(rv); +} + + +/* + * mouse_get_last - Get last mouse event. + * + */ +void +mouse_get_last(f, mp) + mousehandler_t *f; + MOUSEPRESS *mp; +{ + if (f != NULL) + *f = lastf; + if (mp != NULL) { + mp->mevent = levent; + mp->row = lrow; + mp->col = lcol; + mp->doubleclick = doubleclick; + mp->button = lbutton; + mp->flags = lflags; + } +} + + + +/* + * register_key - register the given keystroke to accept mouse events + */ +void +register_key(i, rval, label, label_printer, row, col, len, kn, kl) +int i; +unsigned rval; +char *label; +void (*label_printer)(); +int row, col, len; +COLOR_PAIR *kn, *kl; +{ + if(i > 11) + return; + + menuitems[i].val = rval; + menuitems[i].tl.r = menuitems[i].br.r = row; + menuitems[i].tl.c = col; + menuitems[i].br.c = col + len; + menuitems[i].lbl.r = menuitems[i].tl.r; + menuitems[i].lbl.c = menuitems[i].tl.c; + menuitems[i].label_hiliter = label_printer; + if(menuitems[i].label){ + free(menuitems[i].label); + menuitems[i].label = NULL; + } + if(menuitems[i].kncp) + free_color_pair(&menuitems[i].kncp); + if(menuitems[i].klcp) + free_color_pair(&menuitems[i].klcp); + if(kn) + menuitems[i].kncp = new_color_pair(kn->fg, kn->bg); + else + menuitems[i].kncp = NULL; + if(kl) + menuitems[i].klcp = new_color_pair(kl->fg, kl->bg); + else + menuitems[i].klcp = NULL; + + if(label + && (menuitems[i].label =(char *)malloc((strlen(label)+1)*sizeof(char)))) + strcpy(menuitems[i].label, label); +} + + +int +mouse_on_key(row, col) + int row, col; +{ + int i; + + for(i = 0; i < 12; i++) + if(M_ACTIVE(row, col, &menuitems[i])) + return(TRUE); + + return(FALSE); +} +#endif /* MOUSE */ + + +/* + * Below are functions for use outside pico to manipulate text + * in a pico's native format (circular linked list of lines). + * + * The idea is to streamline pico use by making it fairly easy + * for outside programs to prepare text intended for pico's use. + * The simple char * alternative is messy as it requires two copies + * of the same text, and isn't very economic in limited memory + * situations (THANKS BELLEVUE-BILLY.). + */ +typedef struct picotext { + LINE *linep; + LINE *dotp; + int doto; + short crinread; +} PICOTEXT; + +#define PT(X) ((PICOTEXT *)(X)) + +/* + * pico_get - return window struct pointer used as a handle + * to the other pico_xxx routines. + */ +void * +pico_get() +{ + PICOTEXT *wp = NULL; + LINE *lp = NULL; + + if(wp = (PICOTEXT *)malloc(sizeof(PICOTEXT))){ + wp->crinread = 0; + if((lp = lalloc(0)) == NULL){ + free(wp); + return(NULL); + } + + wp->dotp = wp->linep = lp->l_fp = lp->l_bp = lp; + wp->doto = 0; + } + else + emlwrite("Can't allocate space for text", NULL); + + return((void *)wp); +} + +/* + * pico_give - free resources and give up picotext struct + */ +void +pico_give(w) +void *w; +{ + register LINE *lp; + register LINE *fp; + + fp = lforw(PT(w)->linep); + while((lp = fp) != PT(w)->linep){ + fp = lforw(lp); + free(lp); + } + free(PT(w)->linep); + free((PICOTEXT *)w); +} + +/* + * pico_readc - return char at current point. Up to calling routines + * to keep cumulative count of chars. + */ +int +pico_readc(w, c) +void *w; +unsigned char *c; +{ + int rv = 0; + + if(PT(w)->crinread){ + *c = '\012'; /* return LF */ + PT(w)->crinread = 0; + rv++; + } + else if(PT(w)->doto < llength(PT(w)->dotp)){ /* normal char to return */ + *c = (unsigned char) lgetc(PT(w)->dotp, (PT(w)->doto)++).c; + rv++; + } + else if(PT(w)->dotp != PT(w)->linep){ /* return line break */ + PT(w)->dotp = lforw(PT(w)->dotp); + PT(w)->doto = 0; +#if defined(DOS) || defined(OS2) + *c = '\015'; + PT(w)->crinread++; +#else + *c = '\012'; /* return local eol! */ +#endif + rv++; + } /* else no chars to return */ + + return(rv); +} + + +/* + * pico_writec - write a char into picotext and advance pointers. + * Up to calling routines to keep track of total chars + * written + */ +int +pico_writec(w, c) +void *w; +int c; +{ + int rv = 0; + + if(c == '\r') /* ignore CR's */ + rv++; /* so fake it */ + else if(c == '\n'){ /* insert newlines on LF */ + /* + * OK, if there are characters on the current line or + * dotp is pointing to the delimiter line, insert a newline + * No here's the tricky bit; preserve the implicit EOF newline. + */ + if(lforw(PT(w)->dotp) == PT(w)->linep && PT(w)->dotp != PT(w)->linep){ + PT(w)->dotp = PT(w)->linep; + PT(w)->doto = 0; + } + else{ + register LINE *lp; + + if((lp = lalloc(0)) == NULL){ + emlwrite("Can't allocate space for more characters",NULL); + return(0); + } + + if(PT(w)->dotp == PT(w)->linep){ + lforw(lp) = PT(w)->linep; + lback(lp) = lback(PT(w)->linep); + lforw(lback(lp)) = lback(PT(w)->linep) = lp; + } + else{ + lforw(lp) = lforw(PT(w)->dotp); + lback(lp) = PT(w)->dotp; + lback(lforw(lp)) = lforw(PT(w)->dotp) = lp; + PT(w)->dotp = lp; + PT(w)->doto = 0; + } + } + + rv++; + } + else + rv = geninsert(&PT(w)->dotp, &PT(w)->doto, PT(w)->linep, c, 0, 1, NULL); + + return((rv) ? 1 : 0); /* return number written */ +} + + +/* + * pico_puts - just write the given string into the text + */ +int +pico_puts(w, s) +void *w; +char *s; +{ + int rv = 0; + + while(*s != '\0') + rv += pico_writec(w, (int)*s++); + + return((rv) ? 1 : 0); +} + + +/* + * pico_seek - position dotp and dot at requested location + */ +int +pico_seek(w, offset, orig) +void *w; +long offset; +int orig; +{ + register LINE *lp; + + PT(w)->crinread = 0; + switch(orig){ + case 0 : /* SEEK_SET */ + PT(w)->dotp = lforw(PT(w)->linep); + PT(w)->doto = 0; + case 1 : /* SEEK_CUR */ + lp = PT(w)->dotp; + while(lp != PT(w)->linep){ + if(offset <= llength(lp)){ + PT(w)->doto = (int)offset; + PT(w)->dotp = lp; + break; + } + + offset -= ((long)llength(lp) +#if defined(DOS) || defined(OS2) + + 2L); +#else + + 1L); +#endif + lp = lforw(lp); + } + break; + + case 2 : /* SEEK_END */ + PT(w)->dotp = lback(PT(w)->linep); + PT(w)->doto = llength(PT(w)->dotp); + break; + default : + return(-1); + } + + return(0); +} + + +/* + * breplace - replace the current window's text with the given + * LINEs + */ +void +breplace(w) +void *w; +{ + register LINE *lp; + register LINE *fp; + + fp = lforw(curbp->b_linep); + while((lp = fp) != curbp->b_linep){ /* blast old lines */ + fp = lforw(lp); + free(lp); + } + free(curbp->b_linep); + + curbp->b_linep = PT(w)->linep; /* arrange pointers */ + + curwp->w_linep = lforw(curbp->b_linep); + curwp->w_dotp = lforw(curbp->b_linep); + curwp->w_doto = 0; + curwp->w_markp = curwp->w_imarkp = NULL; + curwp->w_marko = curwp->w_imarko = 0; + + curbp->b_dotp = curwp->w_dotp; + curbp->b_doto = curbp->b_marko = 0; + curbp->b_markp = NULL; + curbp->b_linecnt = -1; + + curwp->w_flag |= WFHARD; +} + + +#ifdef _WINDOWS +/* + * + */ +int +composer_file_drop(x, y, filename) + int x, y; + char *filename; +{ + int attached = 0; + if((ComposerTopLine > 2 && x <= ComposerTopLine) + || !LikelyASCII(filename)){ + AppendAttachment(filename, NULL, NULL); + attached++; + } + else{ + setimark(FALSE, 1); + ifile(filename); + swapimark(FALSE, 1); + } + + if(ComposerEditing){ /* update display */ + PaintBody(0); + } + else{ + pico_refresh(0, 1); + update(); + } + + if(attached) + emlwrite("Attached dropped file \"%s\"", filename); + else + emlwrite("Inserted dropped file \"%s\"", filename); + + if(ComposerEditing){ /* restore cursor */ + HeaderPaintCursor(); + } + else{ + curwp->w_flag |= WFHARD; + update(); + } + + return(1); +} + + + +int +pico_cursor(col, row) + int col; + long row; +{ + return((row > 1 && row <= term.t_nrow - (term.t_mrow + 1)) + ? MSWIN_CURSOR_IBEAM + : MSWIN_CURSOR_ARROW); +} +#endif /* _WINDOWS */ diff --git a/pico.h b/pico.h new file mode 100644 index 0000000..01836ee --- /dev/null +++ b/pico.h @@ -0,0 +1,605 @@ +/* + * $Id: pico.h 14019 2005-03-30 22:44:40Z jpf $ + * + * Program: pico.h - definitions for Pine's composer library + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + */ + +#ifndef PICO_H +#define PICO_H +/* + * Defined for attachment support + */ +#define ATTACHMENTS 1 + + +/* + * defs of return codes from pine mailer composer. + */ +#define BUF_CHANGED 0x01 +#define COMP_CANCEL 0x02 +#define COMP_EXIT 0x04 +#define COMP_FAILED 0x08 +#define COMP_SUSPEND 0x10 +#define COMP_GOTHUP 0x20 + + +/* + * top line from the top of the screen for the editor to do + * its stuff + */ +#define COMPOSER_TOP_LINE 2 +#define COMPOSER_TITLE_LINE 0 + + + +/* + * definitions of Mail header structures + */ +struct hdr_line { + char text[256]; + struct hdr_line *next; + struct hdr_line *prev; +}; + +#if defined(DOS) || defined(HELPFILE) +#define HELP_T short +#else +#define HELP_T char ** +#endif + + +/* + * This structure controls the header line items on the screen. An + * instance of this should be created and passed in as an argument when + * pico is called. The list is terminated by an entry with the name + * element NULL. + */ + +struct headerentry { + char *prompt; + char *name; + HELP_T help; + int prlen; + int maxlen; + char **realaddr; + int (*builder)(); /* Function to verify/canonicalize val */ + struct headerentry *affected_entry, *next_affected; + /* entry builder's 4th arg affects */ + char *(*selector)(); /* Browser for possible values */ + char *key_label; /* Key label for key to call browser */ + char *(*fileedit)(); /* Editor for file named in header */ + unsigned display_it:1; /* field is to be displayed by default */ + unsigned break_on_comma:1; /* Field breaks on commas */ + unsigned is_attach:1; /* Special case field for attachments */ + unsigned rich_header:1; /* Field is part of rich header */ + unsigned only_file_chars:1; /* Field is a file name */ + unsigned single_space:1; /* Crush multiple spaces into one */ + unsigned sticky:1; /* Can't change this via affected_entry*/ + unsigned dirty:1; /* We've changed this entry */ + unsigned start_here:1; /* begin composer on first on lit */ + unsigned blank:1; /* blank line separator */ +#ifdef KS_OSDATAVAR + KS_OSDATAVAR /* Port-Specific keymenu data */ +#endif + void *bldr_private; /* Data managed by builders */ + struct hdr_line *hd_text; +}; + + +/* + * Structure to pass as arg to builders. + * + * me -- A pointer to the bldr_private data for the entry currently + * being edited. + * tptr -- A malloc'd copy of the displayed text for the affected_entry + * pointed to by the aff argument. + * aff -- A pointer to the bldr_private data for the affected_entry (the + * entry that this entry affects). + * next -- The next affected_entry in the list. For example, the Lcc entry + * affects the To entry which affects the Fcc entry. + */ +typedef struct bld_arg { + void **me; + char *tptr; + void **aff; + struct bld_arg *next; +} BUILDER_ARG; + +#define BUILDER_SCREEN_MANGLED 0x1 +#define BUILDER_MESSAGE_DISPLAYED 0x2 + + +/* + * structure to keep track of header display + */ +struct on_display { + int p_off; /* offset into line */ + int p_len; /* length of line */ + int p_line; /* physical line on screen */ + int top_e; /* topline's header entry */ + struct hdr_line *top_l; /* top line on display */ + int cur_e; /* current header entry */ + struct hdr_line *cur_l; /* current hd_line */ +}; /* global on_display struct */ + + +/* + * Structure to handle attachments + */ +typedef struct pico_atmt { + char *description; /* attachment description */ + char *filename; /* file/pseudonym for attachment */ + char *size; /* size of attachment */ + char *id; /* attachment id */ + unsigned short flags; + struct pico_atmt *next; +} PATMT; + +/* + * Structure to contain color options + */ +typedef struct pico_colors { + COLOR_PAIR *tbcp; /* title bar color pair */ + COLOR_PAIR *klcp; /* key label color pair */ + COLOR_PAIR *kncp; /* key name color pair */ + COLOR_PAIR *stcp; /* status color pair */ +} PCOLORS; + +/* + * Flags for attachment handling + */ +#define A_FLIT 0x0001 /* Accept literal file and size */ +#define A_ERR 0x0002 /* Problem with specified attachment */ +#define A_TMP 0x0004 /* filename is temporary, delete it */ + + +/* + * Master pine composer structure. Right now there's not much checking + * that any of these are pointing to something, so pine must have them pointing + * somewhere. + */ +typedef struct pico_struct { + void *msgtext; /* ptrs to malloc'd arrays of char */ + char *pine_anchor; /* ptr to pine anchor line */ + char *pine_version; /* string containing Pine's version */ + char *oper_dir; /* Operating dir (confine to tree) */ + char *home_dir; /* Home directory that should be used (WINDOWS) */ + char *quote_str; /* prepended to lines of quoted text */ + char *exit_label; /* Label for ^X in keymenu */ + char *ctrlr_label; /* Label for ^R in keymenu */ + char *alt_spell; /* Checker to use other than "spell" */ + char **alt_ed; /* name of alternate editor or NULL */ + int fillcolumn; /* where to wrap */ + int menu_rows; /* number of rows in menu (0 or 2) */ + long edit_offset; /* offset into hdr line or body */ + int *hibit_entered; /* hibit input came from user */ + PATMT *attachments; /* linked list of attachments */ + PCOLORS *colors; /* colors for titlebar and keymenu */ + long pine_flags; /* entry mode flags */ + /* The next few bits are features that don't fit in pine_flags */ + /* If we had this to do over, it would probably be one giant bitmap */ + unsigned always_spell_check:1; /* always spell-checking upon quit */ + unsigned strip_ws_before_send:1; /* don't default strip bc of flowed */ + unsigned allow_flowed_text:1; /* clean text when done to keep flowed */ + int (*helper)(); /* Pine's help function */ + int (*showmsg)(); /* Pine's display_message */ + int (*suspend)(); /* Pine's suspend */ + void (*keybinput)(); /* Pine's keyboard input indicator */ + int (*tty_fix)(); /* Let Pine fix tty state */ + long (*newmail)(); /* Pine's report_new_mail */ + long (*msgntext)(); /* callback to get msg n's text */ + int (*upload)(); /* callback to rcv uplaoded text */ + char *(*ckptdir)(); /* callback for checkpoint file dir */ + char *(*exittest)(); /* callback to verify exit request */ + char *(*canceltest)(); /* callback to verify cancel request */ + int (*mimetype)(); /* callback to display mime type */ + int (*expander)(); /* callback to expand address lists */ + void (*resize)(); /* callback handling screen resize */ + void (*winch_cleanup)(); /* callback handling screen resize */ + int arm_winch_cleanup; /* do the winch_cleanup if resized */ + HELP_T search_help; + HELP_T ins_help; + HELP_T ins_m_help; + HELP_T composer_help; + HELP_T browse_help; + HELP_T attach_help; + struct headerentry *headents; +} PICO; + + +/* + * Used to save and restore global pico variables that are destroyed by + * calling pico a second time. This happens when pico calls a selector + * in the HeaderEditor and that selector calls pico again. + */ +typedef struct _save_stuff { + int vtrow, + vtcol, + lbound; + VIDEO **vscreen, + **pscreen; /* save pointers */ + struct on_display ods; /* save whole struct */ + short delim_ps, + invert_ps; + int pico_all_done; + jmp_buf finstate; + char *pico_anchor; /* save pointer */ + PICO *Pmaster; /* save pointer */ + int fillcol; + char *pat; /* save array */ + int ComposerTopLine, + ComposerEditing; + long gmode; + char *alt_speller; /* save pointer */ + char *quote_str; /* save pointer */ + int currow, + curcol, + thisflag, + lastflag, + curgoal; + char *opertree; /* save array */ + WINDOW *curwp; /* save pointer */ + WINDOW *wheadp; /* save pointer */ + BUFFER *curbp; /* save pointer */ + BUFFER *bheadp; /* save pointer */ + int km_popped; + int mrow; +} VARS_TO_SAVE; + + +#ifdef MOUSE +/* + * Mouse buttons. + */ +#define M_BUTTON_LEFT 0 +#define M_BUTTON_MIDDLE 1 +#define M_BUTTON_RIGHT 2 + + +/* + * Flags. (modifier keys) + */ +#define M_KEY_CONTROL 0x01 /* Control key was down. */ +#define M_KEY_SHIFT 0x02 /* Shift key was down. */ + + +/* + * Mouse Events + */ +#define M_EVENT_DOWN 0x01 /* Mouse went down. */ +#define M_EVENT_UP 0x02 /* Mouse went up. */ +#define M_EVENT_TRACK 0x04 /* Mouse tracking */ + +/* + * Mouse event information. + */ +typedef struct mouse_struct { + char mevent; /* Indicates type of event: Down, Up or + Track */ + char down; /* TRUE when mouse down event */ + char doubleclick; /* TRUE when double click. */ + int button; /* button pressed. */ + int flags; /* What other keys pressed. */ + int row; + int col; +} MOUSEPRESS; + + + +typedef unsigned long (*mousehandler_t) PROTO((int, int, int, int, int)); + +typedef struct point { + unsigned r:8; /* row value */ + unsigned c:8; /* column value */ +} MPOINT; + + +typedef struct menuitem { + unsigned val; /* return value */ + mousehandler_t action; /* action to perform */ + MPOINT tl; /* top-left corner of active area */ + MPOINT br; /* bottom-right corner of active area */ + MPOINT lbl; /* where the label starts */ + char *label; + void (*label_hiliter)(); + COLOR_PAIR *kncp; /* key name color pair */ + COLOR_PAIR *klcp; /* key label color pair */ + struct menuitem *next; +} MENUITEM; +#endif + + +/* + * Structure used to manage keyboard input that comes as escape + * sequences (arrow keys, function keys, etc.) + */ +typedef struct KBSTREE { + char value; + int func; /* Routine to handle it */ + struct KBSTREE *down; + struct KBSTREE *left; +} KBESC_T; + +/* + * Protos for functions used to manage keyboard escape sequences + * NOTE: these may ot actually get defined under some OS's (ie, DOS, WIN) + */ +extern int kbseq PROTO((int (*)(), int (*)(), void (*)(), int *)); +extern void kbdestroy PROTO((KBESC_T *)); + + +/* + * various flags that they may passed to PICO + */ +#define P_HICTRL 0x80000000 /* overwrite mode */ +#define P_CHKPTNOW 0x40000000 /* do the checkpoint on entry */ +#define P_DELRUBS 0x20000000 /* map ^H to forwdel */ +#define P_LOCALLF 0x10000000 /* use local vs. NVT EOL */ +#define P_BODY 0x08000000 /* start composer in body */ +#define P_HEADEND 0x04000000 /* start composer at end of header */ +#define P_VIEW MDVIEW /* read-only */ +#define P_FKEYS MDFKEY /* run in function key mode */ +#define P_SECURE MDSCUR /* run in restricted (demo) mode */ +#define P_TREE MDTREE /* restrict to a subtree */ +#define P_SUSPEND MDSSPD /* allow ^Z suspension */ +#define P_ADVANCED MDADVN /* enable advanced features */ +#define P_CURDIR MDCURDIR /* use current dir for lookups */ +#define P_ALTNOW MDALTNOW /* enter alt ed sans hesitation */ +#define P_SUBSHELL MDSPWN /* spawn subshell for suspend */ +#define P_COMPLETE MDCMPLT /* enable file name completion */ +#define P_DOTKILL MDDTKILL /* kill from dot to eol */ +#define P_SHOCUR MDSHOCUR /* cursor follows hilite in browser*/ +#define P_HIBITIGN MDHBTIGN /* ignore chars with hi bit set */ +#define P_DOTFILES MDDOTSOK /* browser displays dot files */ +#define P_NOBODY MDHDRONLY /* Operate only on given headers */ +#define P_ALLOW_GOTO MDGOTO /* support "Goto" in file browser */ +#define P_REPLACE MDREPLACE /* allow "Replace" in "Where is" */ + +/* + * definitions for various PICO modes + */ +#define MDWRAP 0x00000001 /* word wrap */ +#define MDSPELL 0x00000002 /* spell error parcing */ +#define MDEXACT 0x00000004 /* Exact matching for searches */ +#define MDVIEW 0x00000008 /* read-only buffer */ +#define MDFKEY 0x00000010 /* function key mode */ +#define MDSCUR 0x00000020 /* secure (for demo) mode */ +#define MDSSPD 0x00000040 /* suspendable mode */ +#define MDADVN 0x00000080 /* Pico's advanced mode */ +#define MDTOOL 0x00000100 /* "tool" mode (quick exit) */ +#define MDBRONLY 0x00000200 /* indicates standalone browser */ +#define MDCURDIR 0x00000400 /* use current dir for lookups */ +#define MDALTNOW 0x00000800 /* enter alt ed sans hesitation */ +#define MDSPWN 0x00001000 /* spawn subshell for suspend */ +#define MDCMPLT 0x00002000 /* enable file name completion */ +#define MDDTKILL 0x00004000 /* kill from dot to eol */ +#define MDSHOCUR 0x00008000 /* cursor follows hilite in browser */ +#define MDHBTIGN 0x00010000 /* ignore chars with hi bit set */ +#define MDDOTSOK 0x00020000 /* browser displays dot files */ +#define MDEXTFB 0x00040000 /* stand alone File browser */ +#define MDTREE 0x00080000 /* confine to a subtree */ +#define MDMOUSE 0x00100000 /* allow mouse (part. in xterm) */ +#define MDONECOL 0x00200000 /* single column browser */ +#define MDHDRONLY 0x00400000 /* header editing exclusively */ +#define MDGOTO 0x00800000 /* support "Goto" in file browser */ +#define MDREPLACE 0x01000000 /* allow "Replace" in "Where is"*/ +#define MDTCAPWINS 0x02000000 /* Termcap overrides defaults */ + +/* + * Main defs + */ +#ifdef maindef +PICO *Pmaster = NULL; /* composer specific stuff */ +char *version = "4.10"; /* PICO version number */ + +#else +extern PICO *Pmaster; /* composer specific stuff */ +extern char *version; /* pico version! */ + +#endif /* maindef */ + + +/* + * Flags for FileBrowser call + */ +#define FB_READ 0x0001 /* Looking for a file to read. */ +#define FB_SAVE 0x0002 /* Looking for a file to save. */ +#define FB_ATTACH 0x0004 /* Looking for a file to attach */ +#define FB_LMODEPOS 0x0008 /* ListMode is a possibility */ +#define FB_LMODE 0x0010 /* Using ListMode now */ + + +/* + * number of keystrokes to delay removing an error message, or new mail + * notification, or checkpointing + */ +#define MESSDELAY 25 +#define NMMESSDELAY 60 +#ifndef CHKPTDELAY +#define CHKPTDELAY 100 +#endif + + +/* + * defs for keypad and function keys... + */ +#define KEY_UP 0x0811 +#define KEY_DOWN 0x0812 +#define KEY_RIGHT 0x0813 +#define KEY_LEFT 0x0814 +#define KEY_PGUP 0x0815 +#define KEY_PGDN 0x0816 +#define KEY_HOME 0x0817 +#define KEY_END 0x0818 +#define KEY_DEL 0x0819 +#define BADESC 0x0820 +#define KEY_MOUSE 0x0821 /* Fake key to indicate mouse event. */ +#define KEY_SCRLUPL 0x0822 +#define KEY_SCRLDNL 0x0823 +#define KEY_SCRLTO 0x0824 +#define KEY_XTERM_MOUSE 0x0825 +#define KEY_DOUBLE_ESC 0x0826 +#define KEY_SWALLOW_Z 0x0827 +#define KEY_SWAL_UP 0x0828 /* These four have to be in the same order */ +#define KEY_SWAL_DOWN 0x0829 /* as KEY_UP, KEY_DOWN, ... */ +#define KEY_SWAL_RIGHT 0x0830 +#define KEY_SWAL_LEFT 0x0831 +#define KEY_KERMIT 0x0832 +#define KEY_JUNK 0x0840 +#define KEY_RESIZE 0x0841 /* Fake key to cause resize. */ +#define KEY_MENU_FLAG 0x1000 +#define KEY_MASK 0x13FF + +/* + * Don't think we are using the fact that this is zero anywhere, + * but just in case we'll leave it. + */ +#define NO_OP_COMMAND 0x0 /* no-op for short timeouts */ +#define NO_OP_IDLE 0x0842 /* no-op for >25 second timeouts */ +#define READY_TO_READ 0x0843 +#define BAIL_OUT 0x0844 +#define PANIC_NOW 0x0845 +#define READ_INTR 0x0846 +#define NODATA 0x08FF + +#define IDLE_TIMEOUT (8) +#define FUDGE (30) /* better be at least 20 */ + +/* + * defines for function keys + */ +#define F1 0x1001 /* Functin key one */ +#define F2 0x1002 /* Functin key two */ +#define F3 0x1003 /* Functin key three */ +#define F4 0x1004 /* Functin key four */ +#define F5 0x1005 /* Functin key five */ +#define F6 0x1006 /* Functin key six */ +#define F7 0x1007 /* Functin key seven */ +#define F8 0x1008 /* Functin key eight */ +#define F9 0x1009 /* Functin key nine */ +#define F10 0x100A /* Functin key ten */ +#define F11 0x100B /* Functin key eleven */ +#define F12 0x100C /* Functin key twelve */ + +/* 1st tier pine function keys */ +#define PF1 F1 +#define PF2 F2 +#define PF3 F3 +#define PF4 F4 +#define PF5 F5 +#define PF6 F6 +#define PF7 F7 +#define PF8 F8 +#define PF9 F9 +#define PF10 F10 +#define PF11 F11 +#define PF12 F12 + +#define PF2OPF(x) (x + 0x10) +#define PF2OOPF(x) (x + 0x20) +#define PF2OOOPF(x) (x + 0x30) + +/* 2nd tier pine function keys */ +#define OPF1 PF2OPF(PF1) +#define OPF2 PF2OPF(PF2) +#define OPF3 PF2OPF(PF3) +#define OPF4 PF2OPF(PF4) +#define OPF5 PF2OPF(PF5) +#define OPF6 PF2OPF(PF6) +#define OPF7 PF2OPF(PF7) +#define OPF8 PF2OPF(PF8) +#define OPF9 PF2OPF(PF9) +#define OPF10 PF2OPF(PF10) +#define OPF11 PF2OPF(PF11) +#define OPF12 PF2OPF(PF12) + +/* 3rd tier pine function keys */ +#define OOPF1 PF2OOPF(PF1) +#define OOPF2 PF2OOPF(PF2) +#define OOPF3 PF2OOPF(PF3) +#define OOPF4 PF2OOPF(PF4) +#define OOPF5 PF2OOPF(PF5) +#define OOPF6 PF2OOPF(PF6) +#define OOPF7 PF2OOPF(PF7) +#define OOPF8 PF2OOPF(PF8) +#define OOPF9 PF2OOPF(PF9) +#define OOPF10 PF2OOPF(PF10) +#define OOPF11 PF2OOPF(PF11) +#define OOPF12 PF2OOPF(PF12) + +/* 4th tier pine function keys */ +#define OOOPF1 PF2OOOPF(PF1) +#define OOOPF2 PF2OOOPF(PF2) +#define OOOPF3 PF2OOOPF(PF3) +#define OOOPF4 PF2OOOPF(PF4) +#define OOOPF5 PF2OOOPF(PF5) +#define OOOPF6 PF2OOOPF(PF6) +#define OOOPF7 PF2OOOPF(PF7) +#define OOOPF8 PF2OOOPF(PF8) +#define OOOPF9 PF2OOOPF(PF9) +#define OOOPF10 PF2OOOPF(PF10) +#define OOOPF11 PF2OOOPF(PF11) +#define OOOPF12 PF2OOOPF(PF12) + + +/* + * useful function definitions + */ +int pico PROTO((PICO *)); +int pico_file_browse PROTO((PICO *, char *, int, char *, int, char *, int)); +void *pico_get PROTO((void)); +void pico_give PROTO((void *)); +int pico_readc PROTO((void *, unsigned char *)); +int pico_writec PROTO((void *, int)); +int pico_puts PROTO((void *, char *)); +int pico_seek PROTO((void *, long, int)); +int pico_replace PROTO((void *, char *)); +int pico_fncomplete PROTO((char *, char *, int)); +#if defined(DOS) || defined(OS2) +int pico_nfsetcolor PROTO((char *)); +int pico_nbsetcolor PROTO((char *)); +int pico_rfsetcolor PROTO((char *)); +int pico_rbsetcolor PROTO((char *)); +#endif +#ifdef MOUSE +int init_mouse PROTO((void)); +void end_mouse PROTO((void)); +int mouseexist PROTO((void)); +int register_mfunc PROTO((mousehandler_t, int, int, int, int)); +void clear_mfunc PROTO((mousehandler_t)); +unsigned long mouse_in_content PROTO((int, int, int, int, int)); +unsigned long mouse_in_pico PROTO((int, int, int, int, int)); +void mouse_get_last PROTO((mousehandler_t *, MOUSEPRESS *)); +void register_key PROTO((int, unsigned, char *, void (*)(), + int, int, int, COLOR_PAIR *, COLOR_PAIR *)); +int mouse_on_key PROTO((int, int)); +int checkmouse PROTO((unsigned *, int, int, int)); +void invert_label PROTO((int, MENUITEM *)); +void mouseon PROTO((void)); +void mouseoff PROTO((void)); +#endif /* MOUSE */ + + +#endif /* PICO_H */ diff --git a/picolib.def b/picolib.def new file mode 100644 index 0000000..2f22a75 --- /dev/null +++ b/picolib.def @@ -0,0 +1,94 @@ +; +; pico.def +; Linker module definition file for pico editor interface +; +LIBRARY PICOLIB INITINSTANCE +DESCRIPTION 'UW pico editor interface' +DATA + MULTIPLE NONSHARED +EXPORTS + ; pico interface + pico + pico_get + pico_give + pico_seek + pico_new_mail + pico_nbcolor + pico_rbcolor + pico_nfcolor + pico_rfcolor + pico_puts + pico_readc + pico_writec + pico_fncomplete + pico_file_browse + ; pc functions + ibmgetc + ibmbeep + ibmputc + ibmeeol + ibmeeop + ibmmove + ibmopen + ibmclose + ibmrev + vidUpdate + ; keyboard interface + kbd_ready + kbd_getkey + kbd_flush + ; mouse/key functions + clear_mfunc + register_mfunc + init_mouse + end_mouse + checkmouse + mouseon + mouseoff + register_key + mouse_get_last + ; utility functions + interrupt_ok + dont_interrupt + win_multiplex + enter_text_mode + exit_text_mode + normalize_cmd + rebindfunc + time_to_check + wquit + readin + update + edinit + mpresf + vtinit + movecursor + GetKey + mouse_in_content + mlerase + execute + makename + forwdel + forwline + emlwrite + bindtokey + quickexit + fixpath + set_browser_title + gethomedir + FileBrowse + ; exported global data + timeout + userfillcol + alt_speller + sup_keyhelp + term + peeol + gmode + curbp + curwp + Pmaster + lastflag + opertree + km_popped + os2_fflush diff --git a/pilot.c b/pilot.c new file mode 100644 index 0000000..66b7713 --- /dev/null +++ b/pilot.c @@ -0,0 +1,350 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: pilot.c 13703 2004-06-11 21:49:40Z hubert $"; +#endif +/* + * Program: Main stand-alone Pine File Browser routines + * + * Author: Michael Seibel + * Networks and Distributed Computing + * Computing & Communications + * University of Washington + * Administration Building, AG-44 + * Seattle, WA 98195 + * Internet: mikes@cac.washington.edu + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + * + * BROWSER NOTES: + * + * 30 Sep 92 - Stand alone PIne's "Lister of Things" came into being. + * It's built against libpico.a from a command line like: + * + * cc pilot.c libpico.a -ltermcap -lc -o pilot + * + * should it become a fleshed out tool, we'll move it into + * the normal build process. + */ + +#include "headers.h" + + +#define PILOT_VERSION "UW PILOT 2.0" + + +extern char *gethomedir(); + +char *pilot_args PROTO((int, char **, int *, int *)); +void pilot_args_help PROTO((void)); +void pilot_display_args_err PROTO((char *, char **, int)); + +char args_pilot_missing_flag[] = "unknown flag \"%c\""; +char args_pilot_missing_arg[] = "missing or empty argument to \"%c\" flag"; +char args_pilot_missing_num[] = "non numeric argument for \"%c\" flag"; +char args_pilot_missing_color[] = "missing color for \"%s\" flag"; + +char *args_pilot_args[] = { +"Possible Starting Arguments for Pilot file browser:", +"", +"\tArgument\t\tMeaning", +"\t -a \t\tShowDot - show dot files in file browser", +"\t -j \t\tGoto - allow 'Goto' command in file browser", +"\t -g \t\tShow - show cursor in file browser", +"\t -m \t\tMouse - turn on mouse support", +"\t -v \t\tOneColumn - use single column display", +"\t -x \t\tNoKeyhelp - suppress keyhelp", +"\t -q \t\tTermdefWins - termcap or terminfo takes precedence over defaults", +"\t -f \t\tKeys - force use of function keys", +"\t -h \t\tHelp - give this list of options", +"\t -n[#s] \tMail - notify about new mail every #s seconds, default=180", +"\t -t \t\tShutdown - enable special shutdown mode", +"\t -o \tOperation - specify the operating directory", +"\t -z \t\tSuspend - allow use of ^Z suspension", +#if defined(DOS) || defined(OS2) +"\t -cnf color \tforeground color", +"\t -cnb color \tbackground color", +"\t -crf color \treverse foreground color", +"\t -crb color \treverse background color", +#endif +"\t -setlocale_ctype\tdo setlocale(LC_CTYPE) if available", +"\t -no_setlocale_collate\tdo not do setlocale(LC_COLLATE)", +"", +"\t All arguments may be followed by a directory name to start in.", +"", +NULL +}; + + +/* + * main standalone browser routine + */ +main(argc, argv) +char *argv[]; +{ + char bname[NBUFN]; /* buffer name of file to read */ + char filename[NSTRING]; + char filedir[NSTRING]; + char *dir; + int setlocale_collate = 1; + int setlocale_ctype = 0; + + timeo = 0; + Pmaster = NULL; /* turn OFF composer functionality */ + km_popped = 0; + opertree[0] = '\0'; opertree[NLINE] = '\0'; + filename[0] ='\0'; + gmode |= MDBRONLY; /* turn on exclusive browser mode */ + + /* + * Read command line flags before initializing, otherwise, we never + * know to init for f_keys... + */ + if(dir = pilot_args(argc, argv, &setlocale_collate, &setlocale_ctype)){ + strcpy(filedir, dir); + fixpath(filedir, NSTRING); + } + else + strcpy(filedir, gethomedir(NULL)); + + set_collation(setlocale_collate, setlocale_ctype); + + if(!vtinit()) /* Displays. */ + exit(1); + + strcpy(bname, "main"); /* default buffer name */ + edinit(bname); /* Buffers, windows. */ +#if defined(USE_TERMCAP) || defined(USE_TERMINFO) || defined(VMS) + if(kbesc == NULL){ /* will arrow keys work ? */ + (*term.t_putchar)('\007'); + emlwrite("Warning: keypad keys may be non-functional", NULL); + } +#endif /* USE_TERMCAP/USE_TERMINFO/VMS */ + + curbp->b_mode |= gmode; /* and set default modes*/ + if(timeo) + emlwrite("Checking for new mail every %D seconds", (void *) timeo); + + set_browser_title(PILOT_VERSION); + FileBrowse(filedir, NSTRING, filename, NSTRING, NULL, 0, NULL); + wquit(1, 0); +} + + +/* + * Parse the command line args. + * + * Args ac + * av + * + * Result: command arguments parsed + * possible printing of help for command line + * various global flags set + * returns the name of directory to start in if specified, else NULL + */ +char * +pilot_args(ac, av, setlocale_collate, setlocale_ctype) + int ac; + char **av; + int *setlocale_collate; + int *setlocale_ctype; +{ + int c, usage = 0; + char *str; + char tmp_1k_buf[1000]; /* tmp buf to contain err msgs */ + +Loop: + /* while more arguments with leading - */ + while(--ac > 0 && **++av == '-'){ + /* while more chars in this argument */ + while(*++*av){ + + if(strcmp(*av, "setlocale_ctype") == 0){ + *setlocale_ctype = 1; + goto Loop; + } + else if(strcmp(*av, "no_setlocale_collate") == 0){ + *setlocale_collate = 0; + goto Loop; + } +#if defined(DOS) || defined(OS2) + if(strcmp(*av, "cnf") == 0 + || strcmp(*av, "cnb") == 0 + || strcmp(*av, "crf") == 0 + || strcmp(*av, "crb") == 0){ + + char *cmd = *av; /* save it to use below */ + + if(--ac){ + str = *++av; + if(cmd[1] == 'n'){ + if(cmd[2] == 'f') + pico_nfcolor(str); + else if(cmd[2] == 'b') + pico_nbcolor(str); + } + else if(cmd[1] == 'r'){ + if(cmd[2] == 'f') + pico_rfcolor(str); + else if(cmd[2] == 'b') + pico_rbcolor(str); + } + } + else{ + sprintf(tmp_1k_buf, args_pilot_missing_color, cmd); + pilot_display_args_err(tmp_1k_buf, NULL, 1); + usage++; + } + + goto Loop; + } +#endif + + /* + * Single char options. + */ + switch(c = **av){ + /* + * These don't take arguments. + */ + case 'a': + gmode ^= MDDOTSOK; /* show dot files */ + break; + case 'f': /* -f for function key use */ + gmode ^= MDFKEY; + break; + case 'j': /* allow "Goto" in file browser */ + gmode ^= MDGOTO; + break; + case 'g': /* show-cursor in file browser */ + gmode ^= MDSHOCUR; + break; + case 'm': /* turn on mouse support */ + gmode ^= MDMOUSE; + break; + case 'v': /* single column display */ + gmode ^= MDONECOL; + break; /* break back to inner-while */ + case 'x': /* suppress keyhelp */ + sup_keyhelp = !sup_keyhelp; + break; + case 'q': /* -q for termcap takes precedence */ + gmode ^= MDTCAPWINS; + break; + case 'z': /* -z to suspend */ + gmode ^= MDSSPD; + break; + case 'h': + usage++; + break; + + /* + * These do take arguments. + */ + case 'n': /* -n for new mail notification */ + case 'o' : /* operating tree */ + if(*++*av) + str = *av; + else if(--ac) + str = *++av; + else{ + sprintf(tmp_1k_buf, args_pilot_missing_arg, c); + pilot_display_args_err(tmp_1k_buf, NULL, 1); + usage++; + goto Loop; + } + + switch(c){ + case 'o': + strncpy(opertree, str, NLINE); + gmode ^= MDTREE; + break; + + /* numeric args */ + case 'n': + if(!isdigit((unsigned char)str[0])){ + sprintf(tmp_1k_buf, args_pilot_missing_num, c); + pilot_display_args_err(tmp_1k_buf, NULL, 1); + usage++; + } + + timeo = 180; + if((timeo = atoi(str)) < 30) + timeo = 180; + + break; + } + + goto Loop; + + default: /* huh? */ + sprintf(tmp_1k_buf, args_pilot_missing_flag, c); + pilot_display_args_err(tmp_1k_buf, NULL, 1); + usage++; + break; + } + } + } + + if(usage) + pilot_args_help(); + + /* return the directory */ + if(ac > 0) + return(*av); + else + return(NULL); +} + + +/*---------------------------------------------------------------------- + print a few lines of help for command line arguments + + Args: none + + Result: prints help messages + ----------------------------------------------------------------------*/ +void +pilot_args_help() +{ + /** print out possible starting arguments... **/ + pilot_display_args_err(NULL, args_pilot_args, 0); + exit(1); +} + + +/*---------------------------------------------------------------------- + write argument error to the display... + + Args: none + + Result: prints help messages + ----------------------------------------------------------------------*/ +void +pilot_display_args_err(s, a, err) + char *s; + char **a; + int err; +{ + char errstr[256], *errp; + FILE *fp = err ? stderr : stdout; + + if(err && s) + sprintf(errp = errstr, "Argument Error: %.200s", s); + else + errp = s; + + if(errp) + fprintf(fp, "%s\n", errp); + + while(a && *a) + fprintf(fp, "%s\n", *a++); +} diff --git a/random.c b/random.c new file mode 100644 index 0000000..aa59f25 --- /dev/null +++ b/random.c @@ -0,0 +1,469 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: random.c 13654 2004-05-07 21:43:40Z jpf $"; +#endif +/* + * Program: Random routines + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* + * This file contains the command processing functions for a number of random + * commands. There is no functional grouping here, for sure. + */ + +#include "headers.h" + +#ifdef ANSI + int getccol(int); +#else + int getccol(); +#endif + +int tabsize; /* Tab size (0: use real tabs) */ + + +/* + * Display the current position of the cursor, in origin 1 X-Y coordinates, + * the character that is under the cursor (in octal), and the fraction of the + * text that is before the cursor. The displayed column is not the current + * column, but the column that would be used on an infinite width display. + * Normally this is bound to "C-X =". + */ +showcpos(f, n) +int f, n; +{ + register LINE *clp; + register long nch; + register int cbo; + register long nbc; + register int lines; + register int thisline; + char buffer[80]; + + clp = lforw(curbp->b_linep); /* Grovel the data. */ + cbo = 0; + nch = 0L; + lines = 0; + for (;;) { + if (clp==curwp->w_dotp && cbo==curwp->w_doto) { + thisline = lines; + nbc = nch; + } + if (cbo == llength(clp)) { + if (clp == curbp->b_linep) + break; + clp = lforw(clp); + cbo = 0; + lines++; + } else + ++cbo; + ++nch; + } + + sprintf(buffer,"line %d of %d (%d%%%%), character %ld of %ld (%d%%%%)", + thisline+1, lines+1, (int)((100L*(thisline+1))/(lines+1)), + nbc, nch, (nch) ? (int)((100L*nbc)/nch) : 0); + + emlwrite(buffer, NULL); + return (TRUE); +} + + +/* + * Return current column. Stop at first non-blank given TRUE argument. + */ +getccol(bflg) +int bflg; +{ + register int c, i, col; + + col = 0; + for (i=0; iw_doto; ++i) { + c = lgetc(curwp->w_dotp, i).c; + if (c!=' ' && c!='\t' && bflg) + break; + + if (c == '\t') + col |= 0x07; + else if (c<0x20 || c==0x7F) + ++col; + + ++col; + } + + return(col); +} + + + +/* + * Set tab size if given non-default argument (n <> 1). Otherwise, insert a + * tab into file. If given argument, n, of zero, change to true tabs. + * If n > 1, simulate tab stop every n-characters using spaces. This has to be + * done in this slightly funny way because the tab (in ASCII) has been turned + * into "C-I" (in 10 bit code) already. Bound to "C-I". + */ +tab(f, n) + int f, n; +{ + if (n < 0) + return (FALSE); + + if (n == 0 || n > 1) { + tabsize = n; + return(TRUE); + } + + if (! tabsize) + return(linsert(1, '\t')); + + return(linsert(tabsize - (getccol(FALSE) % tabsize), ' ')); +} + + +/* + * Insert a newline. Bound to "C-M". + */ +newline(f, n) + int f, n; +{ + register int s; + + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + + if (n < 0) + return (FALSE); + + if(optimize && (curwp->w_dotp != curwp->w_bufp->b_linep)){ + int l; + + if(worthit(&l)){ + if(curwp->w_doto != 0) + l++; + scrolldown(curwp, l, n); + } + } + + /* if we are in C mode and this is a default */ + /* pico's never in C mode */ + + if(Pmaster && Pmaster->allow_flowed_text && curwp->w_doto + && isspace(lgetc(curwp->w_dotp, curwp->w_doto - 1).c) + && !(curwp->w_doto == 3 + && lgetc(curwp->w_dotp, 0).c == '-' + && lgetc(curwp->w_dotp, 1).c == '-' + && lgetc(curwp->w_dotp, 2).c == ' ')){ + /* + * flowed mode, make the newline a hard one by + * stripping trailing space. + */ + int i, dellen; + for(i = curwp->w_doto - 1; + i && isspace(lgetc(curwp->w_dotp, i - 1).c); + i--); + dellen = curwp->w_doto - i; + curwp->w_doto = i; + ldelete(dellen, NULL); + } + /* insert some lines */ + while (n--) { + if ((s=lnewline()) != TRUE) + return (s); + } + return (TRUE); +} + + + +/* + * Delete forward. This is real easy, because the basic delete routine does + * all of the work. Watches for negative arguments, and does the right thing. + * If any argument is present, it kills rather than deletes, to prevent loss + * of text if typed with a big argument. Normally bound to "C-D". + */ +forwdel(f, n) + int f, n; +{ + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + + if (n < 0) + return (backdel(f, -n)); + + if(optimize && (curwp->w_dotp != curwp->w_bufp->b_linep)){ + int l; + + if(worthit(&l) && curwp->w_doto == llength(curwp->w_dotp)) + scrollup(curwp, l+1, 1); + } + + if (f != FALSE) { /* Really a kill. */ + if ((lastflag&CFKILL) == 0) + kdelete(); + thisflag |= CFKILL; + } + + return (ldelete((long) n, f ? kinsert : NULL)); +} + + + +/* + * Delete backwards. This is quite easy too, because it's all done with other + * functions. Just move the cursor back, and delete forwards. Like delete + * forward, this actually does a kill if presented with an argument. Bound to + * both "RUBOUT" and "C-H". + */ +backdel(f, n) + int f, n; +{ + register int s; + + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + + if (n < 0) + return (forwdel(f, -n)); + + if(optimize && curwp->w_dotp != curwp->w_bufp->b_linep){ + int l; + + if(worthit(&l) && curwp->w_doto == 0 && + lback(curwp->w_dotp) != curwp->w_bufp->b_linep){ + if(l == curwp->w_toprow) + scrollup(curwp, l+1, 1); + else if(llength(lback(curwp->w_dotp)) == 0) + scrollup(curwp, l-1, 1); + else + scrollup(curwp, l, 1); + } + } + + if (f != FALSE) { /* Really a kill. */ + if ((lastflag&CFKILL) == 0) + kdelete(); + + thisflag |= CFKILL; + } + + if ((s=backchar(f, n)) == TRUE) + s = ldelete((long) n, f ? kinsert : NULL); + + return (s); +} + + + +/* + * killtext - delete the line that the cursor is currently in. + * a greatly pared down version of its former self. + */ +killtext(f, n) +int f, n; +{ + register int chunk; + int opt_scroll = 0; + + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + + if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */ + kdelete(); /* last wasn't a kill. */ + + if(gmode & MDDTKILL){ /* */ + if((chunk = llength(curwp->w_dotp) - curwp->w_doto) == 0){ + chunk = 1; + if(optimize) + opt_scroll = 1; + } + } + else{ + gotobol(FALSE, 1); /* wack from bol past newline */ + chunk = llength(curwp->w_dotp) + 1; + if(optimize) + opt_scroll = 1; + } + + /* optimize what motion we can */ + if(opt_scroll && (curwp->w_dotp != curwp->w_bufp->b_linep)){ + int l; + + if(worthit(&l)) + scrollup(curwp, l, 1); + } + + thisflag |= CFKILL; + return(ldelete((long) chunk, kinsert)); +} + + +/* + * Yank text back from the kill buffer. This is really easy. All of the work + * is done by the standard insert routines. All you do is run the loop, and + * check for errors. Bound to "C-Y". + */ +yank(f, n) +int f, n; +{ + register int c; + register int i; + + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + + if (n < 0) + return (FALSE); + + if(optimize && (curwp->w_dotp != curwp->w_bufp->b_linep)){ + int l; + + if(worthit(&l) && !(lastflag&CFFILL)){ + register int t = 0; + register int i = 0; + register int ch; + + while((ch=fremove(i++)) >= 0) + if(ch == '\n') + t++; + if(t+l < curwp->w_toprow+curwp->w_ntrows) + scrolldown(curwp, l, t); + } + } + + if(lastflag & CFFILL){ /* if last command was fillpara() */ + REGION region; + LINE *dotp; + + if(lastflag & CFFLBF){ + gotoeob(FALSE, 1); + dotp = curwp->w_dotp; + gotobob(FALSE, 1); + } + else{ + backchar(FALSE, 1); + dotp = curwp->w_dotp; + gotobop(FALSE, 1); /* then go to the top of the para */ + } + + curwp->w_doto = 0; + getregion(®ion, dotp, llength(dotp)); + if(!ldelete(region.r_size, NULL)) + return(FALSE); + } /* then splat out the saved buffer */ + + while (n--) { + i = 0; + while ((c = ((lastflag&CFFILL) + ? ((lastflag & CFFLBF) ? kremove(i) : fremove(i)) + : kremove(i))) >= 0) { + if (c == '\n') { + if (lnewline() == FALSE) + return (FALSE); + } else { + if (linsert(1, c) == FALSE) + return (FALSE); + } + + ++i; + } + } + + if(lastflag&CFFILL){ /* if last command was fillpara() */ + curwp->w_dotp = lforw(curwp->w_dotp); + curwp->w_doto = 0; + + curwp->w_flag |= WFMODE; + + if(!Pmaster){ + sgarbk = TRUE; + emlwrite("", NULL); + } + } + + return (TRUE); +} + + +/* + * Original idea from Stephen Casner . + * + * Apply the appropriate reverse color transformation to the given + * color pair and return a new color pair. The caller should free the + * color pair. + * + */ +COLOR_PAIR * +pico_apply_rev_color(cp, style) + COLOR_PAIR *cp; + int style; +{ + COLOR_PAIR *rc = pico_get_rev_color(); + + if(rc){ + if(style == IND_COL_REV){ + /* just use Reverse color regardless */ + return(new_color_pair(rc->fg, rc->bg)); + } + else if(style == IND_COL_FG){ + /* + * If changing to Rev fg is readable and different + * from what it already is, do it. + */ + if(strcmp(rc->fg, cp->bg) && strcmp(rc->fg, cp->fg)) + return(new_color_pair(rc->fg, cp->bg)); + } + else if(style == IND_COL_BG){ + /* + * If changing to Rev bg is readable and different + * from what it already is, do it. + */ + if(strcmp(rc->bg, cp->fg) && strcmp(rc->bg, cp->bg)) + return(new_color_pair(cp->fg, rc->bg)); + } + else if(style == IND_COL_FG_NOAMBIG){ + /* + * If changing to Rev fg is readable, different + * from what it already is, and not the same as + * the Rev color, do it. + */ + if(strcmp(rc->fg, cp->bg) && strcmp(rc->fg, cp->fg) && + strcmp(rc->bg, cp->bg)) + return(new_color_pair(rc->fg, cp->bg)); + } + else if(style == IND_COL_BG_NOAMBIG){ + /* + * If changing to Rev bg is readable, different + * from what it already is, and not the same as + * the Rev color, do it. + */ + if(strcmp(rc->bg, cp->fg) && strcmp(rc->bg, cp->bg) && + strcmp(rc->fg, cp->fg)) + return(new_color_pair(cp->fg, rc->bg)); + } + } + + /* come here for IND_COL_FLIP and for the cases which fail the tests */ + return(new_color_pair(cp->bg, cp->fg)); /* flip the colors */ +} diff --git a/region.c b/region.c new file mode 100644 index 0000000..e7c3637 --- /dev/null +++ b/region.c @@ -0,0 +1,373 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: region.c 11688 2001-06-21 17:54:43Z hubert $"; +#endif +/* + * Program: Region management routines + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2001 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* + * The routines in this file + * deal with the region, that magic space + * between "." and mark. Some functions are + * commands. Some functions are just for + * internal use. + */ +#include "headers.h" + +/* + * Kill the region. Ask "getregion" + * to figure out the bounds of the region. + * Move "." to the start, and kill the characters. + * Bound to "C-W". + */ +killregion(f, n) + int f, n; +{ + REGION region; + + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + + if (getregion(®ion, curwp->w_markp, curwp->w_marko) != TRUE){ + return (killtext(f, n)); + }else { + mlerase(); + } + + if ((lastflag&CFKILL) == 0) /* This is a kill type */ + kdelete(); /* command, so do magic */ + + thisflag |= CFKILL; /* kill buffer stuff. */ + curwp->w_dotp = region.r_linep; + curwp->w_doto = region.r_offset; + curwp->w_markp = NULL; +#ifdef _WINDOWS + mswin_allowcopycut(NULL); +#endif + + if(ldelete(region.r_size, kinsert)){ + if(curwp->w_dotp == curwp->w_linep && curwp->w_dotp == curbp->b_linep){ + curwp->w_force = 0; /* Center dot. */ + curwp->w_flag |= WFFORCE; + } + + return(TRUE); + } + + return (FALSE); +} + + +/* + * Blast the region without saving . Ask "getregion" + * to figure out the bounds of the region. + * Move "." to the start, and kill the characters. + * Bound to "C-W". + */ +deleteregion(f, n) + int f, n; +{ + REGION region; + + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + + if (getregion(®ion, curwp->w_markp, curwp->w_marko) == TRUE){ + curwp->w_dotp = region.r_linep; + curwp->w_doto = region.r_offset; + curwp->w_markp = NULL; +#ifdef _WINDOWS + mswin_allowcopycut(NULL); +#endif + if(ldelete(region.r_size, NULL)){ + if(curwp->w_dotp == curwp->w_linep + && curwp->w_dotp == curbp->b_linep){ + curwp->w_force = 0; /* Center dot. */ + curwp->w_flag |= WFFORCE; + } + + return(TRUE); + } + } + + return (FALSE); +} + + +/* + * Copy all of the characters in the + * region to the kill buffer. Don't move dot + * at all. This is a bit like a kill region followed + * by a yank. Bound to "M-W". + */ +copyregion(f, n) +{ + register LINE *linep; + register int loffs; + register int s; + REGION region; + + if ((s=getregion(®ion, curwp->w_markp, curwp->w_marko)) != TRUE) + return (s); + + if ((lastflag&CFKILL) == 0) /* Kill type command. */ + kdelete(); + + thisflag |= CFKILL; + linep = region.r_linep; /* Current line. */ + loffs = region.r_offset; /* Current offset. */ + while (region.r_size--) { + if (loffs == llength(linep)) { /* End of line. */ + if ((s=kinsert('\n')) != TRUE) + return (s); + linep = lforw(linep); + loffs = 0; + } else { /* Middle of line. */ + if ((s=kinsert(lgetc(linep, loffs).c)) != TRUE) + return (s); + ++loffs; + } + } + + return (TRUE); +} + + +/* + * Lower case region. Zap all of the upper + * case characters in the region to lower case. Use + * the region code to set the limits. Scan the buffer, + * doing the changes. Call "lchange" to ensure that + * redisplay is done in all buffers. Bound to + * "C-X C-L". + */ +lowerregion(f, n) +{ + register LINE *linep; + register int loffs; + register int c; + register int s; + REGION region; + CELL ac; + + ac.a = 0; + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + + if ((s=getregion(®ion, curwp->w_markp, curwp->w_marko)) != TRUE) + return (s); + + lchange(WFHARD); + linep = region.r_linep; + loffs = region.r_offset; + while (region.r_size--) { + if (loffs == llength(linep)) { + linep = lforw(linep); + loffs = 0; + } else { + c = lgetc(linep, loffs).c; + if (c>='A' && c<='Z'){ + ac.c = c+'a'-'A'; + lputc(linep, loffs, ac); + } + ++loffs; + } + } + + return (TRUE); +} + +/* + * Upper case region. Zap all of the lower + * case characters in the region to upper case. Use + * the region code to set the limits. Scan the buffer, + * doing the changes. Call "lchange" to ensure that + * redisplay is done in all buffers. Bound to + * "C-X C-L". + */ +upperregion(f, n) +{ + register LINE *linep; + register int loffs; + register int c; + register int s; + REGION region; + CELL ac; + + ac.a = 0; + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + + if ((s=getregion(®ion, curwp->w_markp, curwp->w_marko)) != TRUE) + return (s); + + lchange(WFHARD); + linep = region.r_linep; + loffs = region.r_offset; + while (region.r_size--) { + if (loffs == llength(linep)) { + linep = lforw(linep); + loffs = 0; + } else { + c = lgetc(linep, loffs).c; + if (c>='a' && c<='z'){ + ac.c = c - 'a' + 'A'; + lputc(linep, loffs, ac); + } + ++loffs; + } + } + + return (TRUE); +} + +/* + * This routine figures out the + * bounds of the region in the current window, and + * fills in the fields of the "REGION" structure pointed + * to by "rp". Because the dot and mark are usually very + * close together, we scan outward from dot looking for + * mark. This should save time. Return a standard code. + * Callers of this routine should be prepared to get + * an "ABORT" status; we might make this have the + * conform thing later. + */ +getregion(rp, markp, marko) +register REGION *rp; +register LINE *markp; +register int marko; +{ + register LINE *flp; + register LINE *blp; + long fsize; + register long bsize; + + if (markp == NULL) { + return (FALSE); + } + + if (curwp->w_dotp == markp) { + rp->r_linep = curwp->w_dotp; + if (curwp->w_doto < marko) { + rp->r_offset = curwp->w_doto; + rp->r_size = marko - curwp->w_doto; + } else { + rp->r_offset = marko; + rp->r_size = curwp->w_doto - marko; + } + return (TRUE); + } + + blp = curwp->w_dotp; + bsize = curwp->w_doto; + flp = curwp->w_dotp; + fsize = llength(flp)-curwp->w_doto+1; + while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) { + if (flp != curbp->b_linep) { + flp = lforw(flp); + if (flp == markp) { + rp->r_linep = curwp->w_dotp; + rp->r_offset = curwp->w_doto; + rp->r_size = fsize + marko; + return (TRUE); + } + + fsize += llength(flp) + 1; + } + + if (lback(blp) != curbp->b_linep) { + blp = lback(blp); + bsize += llength(blp)+1; + if (blp == markp) { + rp->r_linep = blp; + rp->r_offset = marko; + rp->r_size = bsize - marko; + return (TRUE); + } + } + } + + emlwrite("Bug: lost mark", NULL); + return (FALSE); +} + + +/* + * set the highlight attribute accordingly on all characters in region + */ +markregion(attr) + int attr; +{ + register LINE *linep; + register int loffs; + register int s; + REGION region; + CELL ac; + + if ((s=getregion(®ion, curwp->w_markp, curwp->w_marko)) != TRUE) + return (s); + + lchange(WFHARD); + linep = region.r_linep; + loffs = region.r_offset; + while (region.r_size--) { + if (loffs == llength(linep)) { + linep = lforw(linep); + loffs = 0; + } else { + ac = lgetc(linep, loffs); + ac.a = attr; + lputc(linep, loffs, ac); + ++loffs; + } + } + + return (TRUE); +} + + +/* + * clear all the attributes of all the characters in the buffer? + * this is real dumb. Movement with mark set needs to be smarter! + */ +void +unmarkbuffer() +{ + register LINE *linep; + register int n; + CELL c; + + linep = curwp->w_linep; + while(lforw(linep) != curwp->w_linep){ + n = llength(linep); + for(n=0; n < llength(linep); n++){ + c = lgetc(linep, n); + c.a = 0; + lputc(linep, n, c); + } + + linep = lforw(linep); + } +} diff --git a/resource.h b/resource.h new file mode 100644 index 0000000..c01516b --- /dev/null +++ b/resource.h @@ -0,0 +1,134 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by mswin.rc +// +#define IDD_OK 1 +#define ABOUTDLGBOX 100 +#define SPLASHDLGBOX 101 +#define IDM_OPT_SETFONT 103 +#define IDM_ABOUT 104 +#define IDM_EDIT_CUT 105 +#define IDM_EDIT_COPY 106 +#define IDM_EDIT_PASTE 107 +#define TEXTWINMENU 108 +#define IDM_EDIT_CANCEL_PASTE 109 +#define IDM_HELP 110 +#define IDD_TOOLBAR 110 +#define IDM_EDIT_COPY_APPEND 111 +#define IDD_COMPOSER_TB 111 +#define IDM_FILE_EXIT 112 +#define IDD_OPTIONALYENTER 112 +#define IDM_OPT_FONTSAMEAS 113 +#define IDD_SELECT 113 +#define IDM_OPT_SETPRINTFONT 114 +#define IDD_SELECTSORT 114 +#define IDM_FILE_CLOSE 115 +#define IDR_ACCEL_PINE 115 +#define IDD_SELECTFLAG 115 +#define IDM_FILE_PRINT 116 +#define IDM_OPT_TOOLBAR 117 +#define IDM_OPT_TOOLBARPOS 118 +#define IDM_OPT_USEDIALOGS 119 +#define IDM_OPT_USEACCEL 120 +#define IDM_OPT_IMAPTELEM 121 +#define IDM_EDIT_SEL_ALL 122 +#define IDM_MI_SORTSUBJECT 123 +#define IDM_MI_SORTARRIVAL 124 +#define IDM_MI_SORTFROM 125 +#define IDM_MI_SORTTO 126 +#define IDM_MI_SORTCC 127 +#define IDM_MI_SORTDATE 128 +#define IDM_MI_SORTSIZE 129 +#define IDM_MI_SORTORDERSUB 130 +#define IDM_MI_SORTSCORE 131 +#define IDM_MI_SORTTHREAD 132 +#define IDM_MI_SORTREVERSE 133 +#define IDM_MI_FLAGIMPORTANT 134 +#define IDM_MI_FLAGNEW 135 +#define IDM_MI_FLAGANSWERED 136 +#define IDM_MI_FLAGDELETED 137 +#define IDM_MI_VIEW 150 +#define IDM_MI_EXPUNGE 151 +#define IDM_MI_ZOOM 152 +#define IDM_MI_SORT 153 +#define IDM_MI_HDRMODE 154 +#define IDM_MI_MAINMENU 155 +#define IDM_MI_FLDRLIST 156 +#define IDM_MI_FLDRINDEX 157 +#define IDM_MI_COMPOSER 158 +#define IDM_MI_PREVPAGE 159 +#define IDM_MI_PREVMSG 160 +#define IDM_MI_NEXTMSG 161 +#define IDM_MI_ADDRBOOK 162 +#define IDM_MI_WHEREIS 163 +#define IDM_MI_PRINT 164 +#define IDM_MI_REPLY 165 +#define IDM_MI_FORWARD 166 +#define IDM_MI_BOUNCE 167 +#define IDM_MI_DELETE 168 +#define IDM_MI_UNDELETE 169 +#define IDM_MI_FLAG 170 +#define IDM_MI_SAVE 171 +#define IDM_MI_EXPORT 172 +#define IDM_MI_TAKEADDR 173 +#define IDM_MI_SELECT 174 +#define IDM_MI_APPLY 175 +#define IDM_MI_POSTPONE 176 +#define IDM_MI_SEND 177 +#define IDM_MI_CANCEL 178 +#define IDM_MI_ATTACH 179 +#define IDM_MI_TOADDRBOOK 180 +#define IDM_MI_READFILE 181 +#define IDM_MI_JUSTIFY 182 +#define IDM_MI_ALTEDITOR 183 +#define IDM_MI_GENERALHELP 184 +#define IDM_MI_SCREENHELP 185 +#define IDM_MI_EXIT 186 +#define IDM_MI_NEXTPAGE 187 +#define IDM_MI_SAVEFILE 188 +#define IDM_MI_CURPOSITION 189 +#define IDM_MI_GOTOFLDR 190 +#define IDM_MI_JUMPTOMSG 191 +#define IDM_MI_RICHHDR 192 +#define IDM_MI_EXITMODE 193 +#define IDM_MI_REVIEW 194 +#define IDM_MI_KEYMENU 195 +#define IDM_MI_SELECTCUR 196 +#define IDM_MI_UNDO 197 +#define IDM_MI_SPELLCHK 198 +#define IDM_OPT_CARETBLOCK 200 +#define IDM_OPT_CARETSMALLBLOCK 201 +#define IDM_OPT_CARETHBAR 202 +#define IDM_OPT_CARETVBAR 203 +#define IDM_OPT_NEWMAILWIN 204 +#define PINEMENU 300 +#define COMPOSERMENU 301 +#define PINEICON 400 +#define NEWMAILICON 401 +#define PICOHAND 402 +#define MCLOSEDICON 403 +#define PINEBITMAP 500 +#define PINESPLASH 501 +#define IDD_ABOUTICON 0x210 +#define IDD_VERSION 0x212 +#define IDD_BYLINE 0x213 +#define IDS_BYLINE 773 +#define IDS_APPNAME 774 +#define IDS_APPIDENT 775 +#define IDC_RESPONCE 1002 +#define IDC_PROMPT 1003 +#define IDC_GETHELP 1004 +#define IDC_FLAGCOL1 1016 +#define IDC_FLAGCOL2 1017 +#define IDC_BUTTON2 1018 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 116 +#define _APS_NEXT_COMMAND_VALUE 122 +#define _APS_NEXT_CONTROL_VALUE 1018 +#define _APS_NEXT_SYMED_VALUE 103 +#endif +#endif diff --git a/search.c b/search.c new file mode 100644 index 0000000..068e5a2 --- /dev/null +++ b/search.c @@ -0,0 +1,874 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: search.c 13728 2004-07-01 21:33:30Z jpf $"; +#endif +/* + * Program: Searching routines + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* + * The functions in this file implement commands that search in the forward + * and backward directions. There are no special characters in the search + * strings. Probably should have a regular expression search, or something + * like that. + * + */ + +#include "headers.h" + +int eq PROTO((int, int)); +int expandp PROTO((char *, char *, int)); +int readnumpat PROTO((char *)); +void get_pat_cases PROTO((char *, char *)); + + +#define FWS_RETURN(RV) { \ + thisflag |= CFSRCH; \ + curwp->w_flag |= WFMODE; \ + sgarbk = TRUE; \ + return(RV); \ + } + + +/* + * Search forward. Get a search string from the user, and search, beginning at + * ".", for the string. If found, reset the "." to be just after the match + * string, and [perhaps] repaint the display. Bound to "C-S". + */ + +/* string search input parameters */ + +#define PTBEG 1 /* leave the point at the begining on search */ +#define PTEND 2 /* leave the point at the end on search */ + + + +static char *SearchHelpText[] = { +"Help for Search Command", +" ", +"\tEnter the words or characters you would like to search", +"~\tfor, then press ~R~e~t~u~r~n. The search then takes place.", +"\tWhen the characters or words that you entered ", +"\tare found, the buffer will be redisplayed with the cursor ", +"\tat the beginning of the selected text.", +" ", +"\tThe most recent string for which a search was made is", +"\tdisplayed in the \"Search\" prompt between the square", +"\tbrackets. This string is the default search prompt.", +"~ Hitting only ~R~e~t~u~r~n or at the prompt will cause the", +"\tsearch to be made with the default value.", +" ", +"\tThe text search is not case sensitive, and will examine the", +"\tentire message.", +" ", +"\tShould the search fail, a message will be displayed.", +" ", +"End of Search Help.", +" ", +NULL +}; + + +/* + * Compare two characters. The "bc" comes from the buffer. It has it's case + * folded out. The "pc" is from the pattern. + */ +eq(bc, pc) +int bc; +int pc; +{ + if ((curwp->w_bufp->b_mode & MDEXACT) == 0){ + if (bc>='a' && bc<='z') + bc -= 0x20; + + if (pc>='a' && pc<='z') + pc -= 0x20; + } + + return(bc == pc); +} + + +forwsearch(f, n) + int f, n; +{ + register int status; + int wrapt = FALSE, wrapt2 = FALSE; + int repl_mode = FALSE; + char defpat[NPAT]; + int search = FALSE; + + /* resolve the repeat count */ + if (n == 0) + n = 1; + + if (n < 1) /* search backwards */ + FWS_RETURN(0); + + defpat[0] = '\0'; + + /* ask the user for the text of a pattern */ + while(1){ + + if (gmode & MDREPLACE) + status = srpat("Search", defpat, repl_mode); + else + status = readpattern("Search", TRUE); + + switch(status){ + case TRUE: /* user typed something */ + search = TRUE; + break; + + case HELPCH: /* help requested */ + if(Pmaster){ + VARS_TO_SAVE *saved_state; + + saved_state = save_pico_state(); + (*Pmaster->helper)(Pmaster->search_help, + "Help for Searching", 1); + if(saved_state){ + restore_pico_state(saved_state); + free_pico_state(saved_state); + } + } + else + pico_help(SearchHelpText, "Help for Searching", 1); + + case (CTRL|'L'): /* redraw requested */ + pico_refresh(FALSE, 1); + update(); + break; + + case (CTRL|'V'): + gotoeob(0, 1); + mlerase(); + FWS_RETURN(TRUE); + + case (CTRL|'Y'): + gotobob(0, 1); + mlerase(); + FWS_RETURN(TRUE); + + case (CTRL|'T') : + switch(status = readnumpat("Search to Line Number : ")){ + case -1 : + emlwrite("Search to Line Number Cancelled", NULL); + FWS_RETURN(FALSE); + + case 0 : + emlwrite("Line number must be greater than zero", NULL); + FWS_RETURN(FALSE); + + case -2 : + emlwrite("Line number must contain only digits", NULL); + FWS_RETURN(FALSE); + + case -3 : + continue; + + default : + gotoline(0, status); + mlerase(); + FWS_RETURN(TRUE); + } + + break; + + case (CTRL|'W'): + { + LINE *linep = curwp->w_dotp; + int offset = curwp->w_doto; + + gotobop(0, 1); + gotobol(0, 1); + + /* + * if we're asked to backup and we're already + * + */ + if((lastflag & CFSRCH) + && linep == curwp->w_dotp + && offset == curwp->w_doto + && !(offset == 0 && lback(linep) == curbp->b_linep)){ + backchar(0, 1); + gotobop(0, 1); + gotobol(0, 1); + } + } + + mlerase(); + FWS_RETURN(TRUE); + + case (CTRL|'O'): + if(curwp->w_dotp != curbp->b_linep){ + gotoeop(0, 1); + forwchar(0, 1); + } + + mlerase(); + FWS_RETURN(TRUE); + + case (CTRL|'U'): + fillbuf(0, 1); + mlerase(); + FWS_RETURN(TRUE); + + case (CTRL|'R'): /* toggle replacement option */ + repl_mode = !repl_mode; + break; + + default: + if(status == ABORT) + emlwrite("Search Cancelled", NULL); + else + mlerase(); + + FWS_RETURN(FALSE); + } + + /* replace option is disabled */ + if (!(gmode & MDREPLACE)){ + strcpy(defpat, pat); + break; + } + else if (search){ /* search now */ + strcpy(pat, defpat); /* remember this search for the future */ + break; + } + } + + /* + * This code is kind of dumb. What I want is successive C-W 's to + * move dot to successive occurences of the pattern. So, if dot is + * already sitting at the beginning of the pattern, then we'll move + * forward a char before beginning the search. We'll let the + * automatic wrapping handle putting the dot back in the right + * place... + */ + status = 0; /* using "status" as int temporarily! */ + while(1){ + if(defpat[status] == '\0'){ + forwchar(0, 1); + break; /* find next occurence! */ + } + + if(status + curwp->w_doto >= llength(curwp->w_dotp) || + !eq(defpat[status],lgetc(curwp->w_dotp, curwp->w_doto + status).c)) + break; /* do nothing! */ + status++; + } + + /* search for the pattern */ + + while (n-- > 0) { + if((status = forscan(&wrapt,&defpat[0],NULL,0,PTBEG)) == FALSE) + break; + } + + /* and complain if not there */ + if (status == FALSE){ + emlwrite("\"%s\" not found", defpat); + } + else if((gmode & MDREPLACE) && repl_mode == TRUE){ + status = replace_pat(defpat, &wrapt2); /* replace pattern */ + if (wrapt == TRUE || wrapt2 == TRUE) + emlwrite("Replacement %srapped", + (status == ABORT) ? "cancelled but w" : "W"); + } + else if(wrapt == TRUE){ + emlwrite("Search Wrapped", NULL); + } + else if(status == TRUE){ + emlwrite("", NULL); + } + + FWS_RETURN(status); +} + + + +/* Replace a pattern with the pattern the user types in one or more times. */ +int replace_pat(defpat, wrapt) +char *defpat; +int *wrapt; +{ + register int status; + char lpat[NPAT], origpat[NPAT]; /* case sensitive pattern */ + EXTRAKEYS menu_pat[2]; + int repl_all = FALSE; + char prompt[2*NLINE+32]; + + forscan(wrapt, defpat, NULL, 0, PTBEG); /* go to word to be replaced */ + + lpat[0] = '\0'; + + /* additional 'replace all' menu option */ + menu_pat[0].name = "^X"; + menu_pat[0].key = (CTRL|'X'); + menu_pat[0].label = "Repl All"; + KS_OSDATASET(&menu_pat[0], KS_NONE); + menu_pat[1].name = NULL; + + while(1) { + + update(); + (*term.t_rev)(1); + get_pat_cases(origpat, defpat); + pputs(origpat, 1); /* highlight word */ + (*term.t_rev)(0); + + sprintf(prompt, "Replace%s \"", repl_all ? " every" : ""); + + expandp(&defpat[0], &prompt[strlen(prompt)], NPAT/2); + strcat(prompt, "\" with"); + if(rpat[0] != 0){ + strcat(prompt, " ["); + expandp(rpat, &prompt[strlen(prompt)], NPAT/2); + strcat(prompt, "]"); + } + + strcat(prompt, " : "); + + status = mlreplyd(prompt, lpat, NPAT, QDEFLT, menu_pat); + + curwp->w_flag |= WFMOVE; + + switch(status){ + + case TRUE : + case FALSE : + if(lpat[0]) + strcpy(rpat, lpat); /* remember default */ + else + strcpy(lpat, rpat); /* use default */ + + if (repl_all){ + status = replace_all(defpat, lpat); + } + else{ + chword(defpat, lpat); /* replace word */ + update(); + status = TRUE; + } + + if(status == TRUE) + emlwrite("", NULL); + + return(status); + + case HELPCH: /* help requested */ + if(Pmaster){ + VARS_TO_SAVE *saved_state; + + saved_state = save_pico_state(); + (*Pmaster->helper)(Pmaster->search_help, + "Help for Searching", 1); + if(saved_state){ + restore_pico_state(saved_state); + free_pico_state(saved_state); + } + } + else + pico_help(SearchHelpText, "Help for Searching", 1); + + case (CTRL|'L'): /* redraw requested */ + pico_refresh(FALSE, 1); + update(); + break; + + case (CTRL|'X'): /* toggle replace all option */ + if (repl_all){ + repl_all = FALSE; + menu_pat[0].label = "Repl All"; + } + else{ + repl_all = TRUE; + menu_pat[0].label = "Repl One"; + } + + break; + + default: + if(status == ABORT) + emlwrite("Replacement Cancelled", NULL); + else + mlerase(); + chword(defpat, origpat); + update(); + return(FALSE); + } + } +} + +/* Since the search is not case sensitive, we must obtain the actual pattern + that appears in the text, so that we can highlight (and unhighlight) it + without using the wrong cases */ +void +get_pat_cases(realpat, searchpat) +char *searchpat, *realpat; +{ + int i, searchpatlen, curoff; + + curoff = curwp->w_doto; + searchpatlen = strlen(searchpat); + + for (i = 0; i < searchpatlen; i++) + realpat[i] = lgetc(curwp->w_dotp, curoff++).c; + realpat[searchpatlen] = '\0'; +} + +/* Ask the user about every occurence of orig pattern and replace it with a + repl pattern if the response is affirmative. */ +int replace_all(orig, repl) +char *orig; +char *repl; +{ + register int status = 0; + char prompt[NLINE], realpat[NPAT]; + int wrapt, n = 0; + LINE *stop_line = curwp->w_dotp; + int stop_offset = curwp->w_doto; + + while (1) + if (forscan(&wrapt, orig, stop_line, stop_offset, PTBEG)){ + curwp->w_flag |= WFMOVE; /* put cursor back */ + + update(); + (*term.t_rev)(1); + get_pat_cases(realpat, orig); + pputs(realpat, 1); /* highlight word */ + (*term.t_rev)(0); + fflush(stdout); + + strcpy(prompt, "Replace \""); + expandp(&orig[0], &prompt[strlen(prompt)], NPAT/2); + strcat(prompt, "\" with \""); + expandp(&repl[0], &prompt[strlen(prompt)], NPAT/2); + strcat(prompt, "\""); + + status = mlyesno(prompt, TRUE); /* ask user */ + + if (status == TRUE){ + n++; + chword(realpat, repl); /* replace word */ + update(); + }else{ + chword(realpat, realpat); /* replace word by itself */ + update(); + if(status == ABORT){ /* if cancelled return */ + emlwrite("Replace All cancelled after %d changes", (char *) n); + return (ABORT); /* ... else keep looking */ + } + } + } + else{ + emlwrite("No more matches for \"%s\"", orig); + return (FALSE); + } +} + + +/* Read a replacement pattern. Modeled after readpattern(). */ +srpat(prompt, defpat, repl_mode) +char *prompt; +char *defpat; +int repl_mode; +{ + register int s; + int i = 0; + char tpat[NPAT+20]; + EXTRAKEYS menu_pat[8]; + + menu_pat[i = 0].name = "^Y"; + menu_pat[i].label = "FirstLine"; + menu_pat[i].key = (CTRL|'Y'); + KS_OSDATASET(&menu_pat[i], KS_NONE); + + menu_pat[++i].name = "^V"; + menu_pat[i].label = "LastLine"; + menu_pat[i].key = (CTRL|'V'); + KS_OSDATASET(&menu_pat[i], KS_NONE); + + menu_pat[++i].name = "^R"; + menu_pat[i].label = repl_mode ? "No Replace" : "Replace"; + menu_pat[i].key = (CTRL|'R'); + KS_OSDATASET(&menu_pat[i], KS_NONE); + + if(!repl_mode){ + menu_pat[++i].name = "^T"; + menu_pat[i].label = "LineNumber"; + menu_pat[i].key = (CTRL|'T'); + KS_OSDATASET(&menu_pat[i], KS_NONE); + + menu_pat[++i].name = "^W"; + menu_pat[i].label = "Start of Para"; + menu_pat[i].key = (CTRL|'W'); + KS_OSDATASET(&menu_pat[i], KS_NONE); + + menu_pat[++i].name = "^O"; + menu_pat[i].label = "End of Para"; + menu_pat[i].key = (CTRL|'O'); + KS_OSDATASET(&menu_pat[i], KS_NONE); + + menu_pat[++i].name = "^U"; + menu_pat[i].label = "FullJustify"; + menu_pat[i].key = (CTRL|'U'); + KS_OSDATASET(&menu_pat[i], KS_NONE); + } + + menu_pat[++i].name = NULL; + + strcpy(tpat, prompt); /* copy prompt to output string */ + if (repl_mode){ + strcat(tpat, " (to replace)"); + } + if(pat[0] != '\0'){ + strcat(tpat, " ["); /* build new prompt string */ + expandp(&pat[0], &tpat[strlen(tpat)], NPAT/2); /*add old pattern*/ + strcat(tpat, "]"); + } + + strcat(tpat, ": "); + + s = mlreplyd(tpat, defpat, NLINE, QDEFLT, menu_pat); + + if (s == TRUE || s == FALSE){ /* changed or not, they're done */ + if(!defpat[0]){ /* use default */ + strcpy(defpat, pat); + } + else if(strcmp(pat, defpat)){ /* Specified */ + strcpy(pat, defpat); + rpat[0] = '\0'; + } + + s = TRUE; /* let caller know to proceed */ + } + + return(s); +} + + + +/* + * Read a pattern. Stash it in the external variable "pat". The "pat" is not + * updated if the user types in an empty line. If the user typed an empty line, + * and there is no old pattern, it is an error. Display the old pattern, in the + * style of Jeff Lomicka. There is some do-it-yourself control expansion. + * change to using to delemit the end-of-pattern to allow s in + * the search string. + */ + +readnumpat(prompt) +char *prompt; +{ + int i, n; + char tpat[NPAT+20]; + EXTRAKEYS menu_pat[2]; + + menu_pat[i = 0].name = "^T"; + menu_pat[i].label = "No Line Number"; + menu_pat[i].key = (CTRL|'T'); + KS_OSDATASET(&menu_pat[i++], KS_NONE); + + menu_pat[i].name = NULL; + + tpat[0] = '\0'; + while(1) + switch(mlreplyd(prompt, tpat, NPAT, QNORML, menu_pat)){ + case TRUE : + if(*tpat){ + for(i = n = 0; tpat[i]; i++) + if(strchr("0123456789", tpat[i])){ + n = (n * 10) + (tpat[i] - '0'); + } + else + return(-2); + + return(n); + } + + case FALSE : + default : + return(-1); + + case (CTRL|'T') : + return(-3); + + case (CTRL|'L') : + case HELPCH : + break; + } +} + + +readpattern(prompt, text_mode) +char *prompt; +int text_mode; +{ + register int s; + int i; + char tpat[NPAT+20]; + EXTRAKEYS menu_pat[7]; + + menu_pat[i = 0].name = "^Y"; + menu_pat[i].label = "FirstLine"; + menu_pat[i].key = (CTRL|'Y'); + KS_OSDATASET(&menu_pat[i], KS_NONE); + + menu_pat[++i].name = "^V"; + menu_pat[i].label = "LastLine"; + menu_pat[i].key = (CTRL|'V'); + KS_OSDATASET(&menu_pat[i], KS_NONE); + + if(text_mode){ + menu_pat[++i].name = "^T"; + menu_pat[i].label = "LineNumber"; + menu_pat[i].key = (CTRL|'T'); + KS_OSDATASET(&menu_pat[i], KS_NONE); + + menu_pat[++i].name = "^W"; + menu_pat[i].label = "Start of Para"; + menu_pat[i].key = (CTRL|'W'); + KS_OSDATASET(&menu_pat[i], KS_NONE); + + menu_pat[++i].name = "^O"; + menu_pat[i].label = "End of Para"; + menu_pat[i].key = (CTRL|'O'); + KS_OSDATASET(&menu_pat[i], KS_NONE); + + menu_pat[++i].name = "^U"; + menu_pat[i].label = "FullJustify"; + menu_pat[i].key = (CTRL|'U'); + KS_OSDATASET(&menu_pat[i], KS_NONE); + } + + menu_pat[++i].name = NULL; + + strcpy(tpat, prompt); /* copy prompt to output string */ + if(pat[0] != '\0'){ + strcat(tpat, " ["); /* build new prompt string */ + expandp(&pat[0], &tpat[strlen(tpat)], NPAT/2); /* add old pattern */ + strcat(tpat, "]"); + } + strcat(tpat, " : "); + + s = mlreplyd(tpat, tpat, NPAT, QNORML, menu_pat); + + if ((s == TRUE) && strcmp(pat,tpat)){ /* Specified */ + strcpy(pat, tpat); + rpat[0] = '\0'; + } + else if (s == FALSE && pat[0] != 0) /* CR, but old one */ + s = TRUE; + + return(s); +} + + +/* search forward for a */ +forscan(wrapt,patrn,limitp,limito,leavep) +int *wrapt; /* boolean indicating search wrapped */ +char *patrn; /* string to scan for */ +LINE *limitp; /* stop searching if reached */ +int limito; /* stop searching if reached */ +int leavep; /* place to leave point + PTBEG = begining of match + PTEND = at end of match */ + +{ + register LINE *curline; /* current line during scan */ + register int curoff; /* position within current line */ + register LINE *lastline; /* last line position during scan */ + register int lastoff; /* position within last line */ + register int c; /* character at current position */ + register LINE *matchline; /* current line during matching */ + register int matchoff; /* position in matching line */ + register char *patptr; /* pointer into pattern */ + register int stopoff; /* offset to stop search */ + register LINE *stopline; /* line to stop search */ + + *wrapt = FALSE; + + /* + * the idea is to set the character to end the search at the + * next character in the buffer. thus, let the search wrap + * completely around the buffer. + * + * first, test to see if we are at the end of the line, + * otherwise start searching on the next character. + */ + if(curwp->w_doto == llength(curwp->w_dotp)){ + /* + * dot is not on end of a line + * start at 0 offset of the next line + */ + stopoff = curoff = 0; + stopline = curline = lforw(curwp->w_dotp); + if (curwp->w_dotp == curbp->b_linep) + *wrapt = TRUE; + } + else{ + stopoff = curoff = curwp->w_doto; + stopline = curline = curwp->w_dotp; + } + + /* scan each character until we hit the head link record */ + + /* + * maybe wrapping is a good idea + */ + while (curline){ + + if (curline == curbp->b_linep) + *wrapt = TRUE; + + /* save the current position in case we need to + restore it on a match */ + + lastline = curline; + lastoff = curoff; + + /* get the current character resolving EOLs */ + if (curoff == llength(curline)) { /* if at EOL */ + curline = lforw(curline); /* skip to next line */ + curoff = 0; + c = '\n'; /* and return a */ + } + else + c = lgetc(curline, curoff++).c; /* get the char */ + + /* test it against first char in pattern */ + if (eq(c, patrn[0]) != FALSE) { /* if we find it..*/ + /* setup match pointers */ + matchline = curline; + matchoff = curoff; + patptr = &patrn[0]; + + /* scan through patrn for a match */ + while (*++patptr != 0) { + /* advance all the pointers */ + if (matchoff == llength(matchline)) { + /* advance past EOL */ + matchline = lforw(matchline); + matchoff = 0; + c = '\n'; + } else + c = lgetc(matchline, matchoff++).c; + + if(matchline == limitp && matchoff == limito) + return(FALSE); + + /* and test it against the pattern */ + if (eq(*patptr, c) == FALSE) + goto fail; + } + + /* A SUCCESSFULL MATCH!!! */ + /* reset the global "." pointers */ + if (leavep == PTEND) { /* at end of string */ + curwp->w_dotp = matchline; + curwp->w_doto = matchoff; + } + else { /* at begining of string */ + curwp->w_dotp = lastline; + curwp->w_doto = lastoff; + } + + curwp->w_flag |= WFMOVE; /* flag that we have moved */ + return(TRUE); + + } + +fail:; /* continue to search */ + if(((curline == stopline) && (curoff == stopoff)) + || (curline == limitp && curoff == limito)) + break; /* searched everywhere... */ + } + /* we could not find a match */ + + return(FALSE); +} + +/* expandp: expand control key sequences for output */ + +expandp(srcstr, deststr, maxlength) + +char *srcstr; /* string to expand */ +char *deststr; /* destination of expanded string */ +int maxlength; /* maximum chars in destination */ + +{ + char c; /* current char to translate */ + + /* scan through the string */ + while ((c = *srcstr++) != 0) { + if (c == '\n') { /* its an EOL */ + *deststr++ = '<'; + *deststr++ = 'N'; + *deststr++ = 'L'; + *deststr++ = '>'; + maxlength -= 4; + } else if (c < 0x20 || c == 0x7f) { /* control character */ + *deststr++ = '^'; + *deststr++ = c ^ 0x40; + maxlength -= 2; + } else if (c == '%') { + *deststr++ = '%'; + *deststr++ = '%'; + maxlength -= 2; + + } else { /* any other character */ + *deststr++ = c; + maxlength--; + } + + /* check for maxlength */ + if (maxlength < 4) { + *deststr++ = '$'; + *deststr = '\0'; + return(FALSE); + } + } + *deststr = '\0'; + return(TRUE); +} + + + +/* + * chword() - change the given word, wp, pointed to by the curwp->w_dot + * pointers to the word in cb + */ +void +chword(wb, cb) + char *wb; /* word buffer */ + char *cb; /* changed buffer */ +{ + ldelete((long) strlen(wb), NULL); /* not saved in kill buffer */ + while(*cb != '\0') + linsert(1, *cb++); + + curwp->w_flag |= WFEDIT; +} diff --git a/vmsbuild.com b/vmsbuild.com new file mode 100755 index 0000000..3485ac8 --- /dev/null +++ b/vmsbuild.com @@ -0,0 +1,62 @@ +$! $Id: vmsbuild.com 5467 1996-03-15 07:41:11Z hubert $ +$! +$! Yehavi Bourvine +$! Hebrew University of Jeruselem +$! +972-2-585684 +$! YEHAVI@vms.huji.ac.il +$! +$! Please address all bugs and comments to "pine-bugs@cac.washington.edu" +$! +$! Pine and Pico are registered trademarks of the University of Washington. +$! No commercial use of these trademarks may be made without prior written +$! permission of the University of Washington. +$! +$! Pine, Pico, and Pilot software and its included text are Copyright +$! 1989-1996 by the University of Washington. +$! +$! The full text of our legal notices is contained in the file called +$! CPYRIGHT, included with this distribution. +$! +$! +$ COPY/LOG OS_VMS.H OSDEP.H; +$ CC_DEF = "/define=(ANSI_DRIVER,ATTACHMENTS)" +$ IF F$LOCATE("VAX", F$GETSYI("HW_NAME")) .EQS. F$LENGTH(F$GETSYI("HW_NAME")) +$ THEN +$ CC_DEF = "''CC_DEF'/STANDARD=VAXC" +$ ELSE +$ DEFINE SYS SYS$LIBRARY ! For the Include to not fail on VAX. +$! +$ ENDIF +$ SET VERIFY +$ CC/NOOPTIMIZE'CC_DEF' attach +$ CC/NOOPTIMIZE'CC_DEF' ansi +$ CC/NOOPTIMIZE'CC_DEF' basic +$ CC/NOOPTIMIZE'CC_DEF' bind +$ CC/NOOPTIMIZE'CC_DEF' browse +$ CC/NOOPTIMIZE'CC_DEF' buffer +$ CC/NOOPTIMIZE'CC_DEF' composer +$ CC/NOOPTIMIZE'CC_DEF' display +$ CC/NOOPTIMIZE'CC_DEF' file +$ CC/NOOPTIMIZE'CC_DEF' fileio +$ CC/NOOPTIMIZE'CC_DEF' line +$ CC/NOOPTIMIZE'CC_DEF' pico +$ CC/NOOPTIMIZE'CC_DEF' random +$ CC/NOOPTIMIZE'CC_DEF' region +$ CC/NOOPTIMIZE'CC_DEF' search +$ CC/NOOPTIMIZE'CC_DEF' spell +$ CC/NOOPTIMIZE'CC_DEF' window +$ CC/NOOPTIMIZE'CC_DEF' word +$ CC/NOOPTIMIZE'CC_DEF' main +$ CC/NOOPTIMIZE'CC_DEF' os_VMS +$! +$ LIBRARY/OBJECT/CREATE/INSERT PICO *.OBJ +$! +$ IF F$EXTRACT(0, 3, F$GETSYI("HW_NAME")) .EQS. "VAX" +$ THEN +$ LINK/EXE=PICO MAIN,PICO/LIBR,SYS$INPUT:/OPT + SYS$SHARE:VAXCRTL/SHARE +$ ELSE +$ LINK/EXE=PICO MAIN,PICO/LIBR +$ ENDIF +$ DELETE *.OBJ;* +$ SET NOVER diff --git a/window.c b/window.c new file mode 100644 index 0000000..27e46bb --- /dev/null +++ b/window.c @@ -0,0 +1,60 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: window.c 13655 2004-05-07 21:45:04Z jpf $"; +#endif +/* + * Program: Window management routines + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* + * Window management. Some of the functions are internal, and some are + * attached to keys that the user actually types. + */ + +#include "headers.h" + + +/* + * Refresh the screen. With no argument, it just does the refresh. With an + * argument it recenters "." in the current window. Bound to "C-L". + */ +pico_refresh(f, n) + int f, n; +{ + /* + * since pine mode isn't using the traditional mode line, sgarbf isn't + * enough. + */ + if(Pmaster && curwp) + curwp->w_flag |= WFMODE; + + if (f == FALSE) + sgarbf = TRUE; + else if(curwp){ + curwp->w_force = 0; /* Center dot. */ + curwp->w_flag |= WFFORCE; + } + + return (TRUE); +} diff --git a/word.c b/word.c new file mode 100644 index 0000000..f00b875 --- /dev/null +++ b/word.c @@ -0,0 +1,644 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: word.c 13655 2004-05-07 21:45:04Z jpf $"; +#endif +/* + * Program: Word at a time routines + * + * + * Michael Seibel + * Networks and Distributed Computing + * Computing and Communications + * University of Washington + * Administration Builiding, AG-44 + * Seattle, Washington, 98195, USA + * Internet: mikes@cac.washington.edu + * + * Please address all bugs and comments to "pine-bugs@cac.washington.edu" + * + * + * Pine and Pico are registered trademarks of the University of Washington. + * No commercial use of these trademarks may be made without prior written + * permission of the University of Washington. + * + * Pine, Pico, and Pilot software and its included text are Copyright + * 1989-2004 by the University of Washington. + * + * The full text of our legal notices is contained in the file called + * CPYRIGHT, included with this distribution. + * + */ +/* + * The routines in this file implement commands that work word at a time. + * There are all sorts of word mode commands. If I do any sentence and/or + * paragraph mode commands, they are likely to be put in this file. + */ + +#include "headers.h" + + +/* Word wrap on n-spaces. Back-over whatever precedes the point on the current + * line and stop on the first word-break or the beginning of the line. If we + * reach the beginning of the line, jump back to the end of the word and start + * a new line. Otherwise, break the line at the word-break, eat it, and jump + * back to the end of the word. + * Returns TRUE on success, FALSE on errors. + */ +wrapword() +{ + register int cnt; /* size of word wrapped to next line */ + register int bp; /* index to wrap on */ + register int first = -1; + register int i; + + if(curwp->w_doto <= 0) /* no line to wrap? */ + return(FALSE); + + for(bp = cnt = i = 0; cnt < llength(curwp->w_dotp) && !bp; cnt++, i++){ + if(isspace((unsigned char) lgetc(curwp->w_dotp, cnt).c)){ + first = 0; + if(lgetc(curwp->w_dotp, cnt).c == TAB) + while(i+1 & 0x07) + i++; + } + else if(!first) + first = cnt; + + if(first > 0 && i >= fillcol) + bp = first; + } + + if(!bp) + return(FALSE); + + /* bp now points to the first character of the next line */ + cnt = curwp->w_doto - bp; + curwp->w_doto = bp; + + if(!lnewline()) /* break the line */ + return(FALSE); + + /* + * if there's a line below, it doesn't start with whitespace + * and there's room for this line... + */ + if(!(curbp->b_flag & BFWRAPOPEN) + && lforw(curwp->w_dotp) != curbp->b_linep + && llength(lforw(curwp->w_dotp)) + && !isspace((unsigned char) lgetc(lforw(curwp->w_dotp), 0).c) + && (llength(curwp->w_dotp) + llength(lforw(curwp->w_dotp)) < fillcol)){ + gotoeol(0, 1); /* then pull text up from below */ + if(lgetc(curwp->w_dotp, curwp->w_doto - 1).c != ' ') + linsert(1, ' '); + + forwdel(0, 1); + gotobol(0, 1); + } + + curbp->b_flag &= ~BFWRAPOPEN; /* don't open new line next wrap */ + /* restore dot (account for NL) */ + if(cnt && !forwchar(0, cnt < 0 ? cnt-1 : cnt)) + return(FALSE); + + return(TRUE); +} + + +/* + * Move the cursor backward by "n" words. All of the details of motion are + * performed by the "backchar" and "forwchar" routines. Error if you try to + * move beyond the buffers. + */ +backword(f, n) + int f, n; +{ + if (n < 0) + return (forwword(f, -n)); + if (backchar(FALSE, 1) == FALSE) + return (FALSE); + while (n--) { + while (inword() == FALSE) { + if (backchar(FALSE, 1) == FALSE) + return (FALSE); + } + while (inword() != FALSE) { + if (backchar(FALSE, 1) == FALSE) + return (FALSE); + } + } + return (forwchar(FALSE, 1)); +} + +/* + * Move the cursor forward by the specified number of words. All of the motion + * is done by "forwchar". Error if you try and move beyond the buffer's end. + */ +forwword(f, n) + int f, n; +{ + if (n < 0) + return (backword(f, -n)); + while (n--) { +#if NFWORD + while (inword() != FALSE) { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } +#endif + while (inword() == FALSE) { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } +#if NFWORD == 0 + while (inword() != FALSE) { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } +#endif + } + return(TRUE); +} + +#ifdef MAYBELATER +/* + * Move the cursor forward by the specified number of words. As you move, + * convert any characters to upper case. Error if you try and move beyond the + * end of the buffer. Bound to "M-U". + */ +upperword(f, n) +{ + register int c; + CELL ac; + + ac.a = 0; + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + if (n < 0) + return (FALSE); + while (n--) { + while (inword() == FALSE) { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + while (inword() != FALSE) { + c = lgetc(curwp->w_dotp, curwp->w_doto).c; + if (c>='a' && c<='z') { + ac.c = (c -= 'a'-'A'); + lputc(curwp->w_dotp, curwp->w_doto, ac); + lchange(WFHARD); + } + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + } + return (TRUE); +} + +/* + * Move the cursor forward by the specified number of words. As you move + * convert characters to lower case. Error if you try and move over the end of + * the buffer. Bound to "M-L". + */ +lowerword(f, n) +{ + register int c; + CELL ac; + + ac.a = 0; + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + if (n < 0) + return (FALSE); + while (n--) { + while (inword() == FALSE) { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + while (inword() != FALSE) { + c = lgetc(curwp->w_dotp, curwp->w_doto).c; + if (c>='A' && c<='Z') { + ac.c (c += 'a'-'A'); + lputc(curwp->w_dotp, curwp->w_doto, ac); + lchange(WFHARD); + } + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + } + return (TRUE); +} + +/* + * Move the cursor forward by the specified number of words. As you move + * convert the first character of the word to upper case, and subsequent + * characters to lower case. Error if you try and move past the end of the + * buffer. Bound to "M-C". + */ +capword(f, n) +{ + register int c; + CELL ac; + + ac.a = 0; + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + if (n < 0) + return (FALSE); + while (n--) { + while (inword() == FALSE) { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + if (inword() != FALSE) { + c = lgetc(curwp->w_dotp, curwp->w_doto).c; + if (c>='a' && c<='z') { + ac.c = (c -= 'a'-'A'); + lputc(curwp->w_dotp, curwp->w_doto, ac); + lchange(WFHARD); + } + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + while (inword() != FALSE) { + c = lgetc(curwp->w_dotp, curwp->w_doto).c; + if (c>='A' && c<='Z') { + ac.c = (c += 'a'-'A'); + lputc(curwp->w_dotp, curwp->w_doto, ac); + lchange(WFHARD); + } + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + } + } + } + return (TRUE); +} + +/* + * Kill forward by "n" words. Remember the location of dot. Move forward by + * the right number of words. Put dot back where it was and issue the kill + * command for the right number of characters. Bound to "M-D". + */ +delfword(f, n) +{ + register long size; + register LINE *dotp; + register int doto; + + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + if (n < 0) + return (FALSE); + dotp = curwp->w_dotp; + doto = curwp->w_doto; + size = 0L; + while (n--) { +#if NFWORD + while (inword() != FALSE) { + if (forwchar(FALSE,1) == FALSE) + return(FALSE); + ++size; + } +#endif + while (inword() == FALSE) { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + ++size; + } +#if NFWORD == 0 + while (inword() != FALSE) { + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + ++size; + } +#endif + } + curwp->w_dotp = dotp; + curwp->w_doto = doto; + return (ldelete(size, kinsert)); +} + +/* + * Kill backwards by "n" words. Move backwards by the desired number of words, + * counting the characters. When dot is finally moved to its resting place, + * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace". + */ +delbword(f, n) +{ + register long size; + + if (curbp->b_mode&MDVIEW) /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + if (n < 0) + return (FALSE); + if (backchar(FALSE, 1) == FALSE) + return (FALSE); + size = 0L; + while (n--) { + while (inword() == FALSE) { + if (backchar(FALSE, 1) == FALSE) + return (FALSE); + ++size; + } + while (inword() != FALSE) { + if (backchar(FALSE, 1) == FALSE) + return (FALSE); + ++size; + } + } + if (forwchar(FALSE, 1) == FALSE) + return (FALSE); + return (ldelete(size, kinsert)); +} +#endif /* MAYBELATER */ + +/* + * Return TRUE if the character at dot is a character that is considered to be + * part of a word. The word character list is hard coded. Should be setable. + */ +inword() +{ + return(curwp->w_doto < llength(curwp->w_dotp) + && isalnum((unsigned char)lgetc(curwp->w_dotp, curwp->w_doto).c)); +} + + +/* + * Return number of quotes if whatever starts the line matches the quote string + */ +quote_match(q, l, buf, buflen) + char *q; + LINE *l; + char *buf; + int buflen; +{ + register int i, n, j, qb; + + *buf = '\0'; + if(*q == '\0') + return(1); + + qb = (strlen(q) > 1 && q[strlen(q)-1] == ' ') ? 1 : 0; + for(n = 0, j = 0; ;){ + for(i = 0; j <= llength(l) && qb ? q[i+1] : q[i]; i++, j++) + if(q[i] != lgetc(l, j).c) + return(n); + + n++; + if((!qb && q[i] == '\0') || (qb && q[i+1] == '\0')){ + if(strlen(buf) + strlen(q) + 1 < buflen){ + strcat(buf,q); + if(qb && (j > llength(l) || lgetc(l, j).c != ' ')) + buf[strlen(buf)-1] = '\0'; + } + } + if(j > llength(l)) + return(n); + else if(qb && lgetc(l, j).c == ' ') + j++; + } + return(n); /* never reached */ +} + + +/* Justify the entire buffer instead of just a paragraph */ +fillbuf(f, n) +int f, n; +{ + int i, lastflagsave; + LINE *eobline; + REGION region; + + if(curbp->b_mode&MDVIEW){ /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + } + else if (fillcol == 0) { /* no fill column set */ + mlwrite("No fill column set", NULL); + return(FALSE); + } + + if((lastflag & CFFILL) && (lastflag & CFFLBF)){ + /* no use doing a full justify twice */ + thisflag |= (CFFLBF | CFFILL); + return(TRUE); + } + + /* record the pointer of the last line */ + if(gotoeob(FALSE, 1) == FALSE) + return(FALSE); + + eobline = curwp->w_dotp; /* last line of buffer */ + if(!llength(eobline)) + eobline = lback(eobline); + + /* and back to the beginning of the buffer */ + gotobob(FALSE, 1); + + thisflag |= CFFLBF; /* CFFILL also gets set in fillpara */ + + if(!Pmaster) + sgarbk = TRUE; + + curwp->w_flag |= WFMODE; + + /* + * clear the kill buffer, that's where we'll store undo + * information, we can't do the fill buffer because + * fillpara relies on its contents + */ + kdelete(); + curwp->w_doto = 0; + getregion(®ion, eobline, llength(eobline)); + + /* Put full message in the kill buffer for undo */ + if(!ldelete(region.r_size, kinsert)) + return(FALSE); + + /* before yank'ing, clear lastflag so we don't just unjustify */ + lastflag &= ~(CFFLBF | CFFILL); + + /* Now in kill buffer, bring back text to use in fillpara */ + yank(FALSE, 1); + + gotobob(FALSE, 1); + + /* call fillpara until we're at the end of the buffer */ + while(curwp->w_dotp != curbp->b_linep) + if(!(fillpara(FALSE, 1))) + return(FALSE); + + return(TRUE); +} + + +fillpara(f, n) /* Fill the current paragraph according to the current + fill column */ + +int f, n; /* deFault flag and Numeric argument */ + +{ + int i, j, c, qlen, word[NSTRING], same_word, + spaces, word_len, line_len, line_last, qn; + char *qstr, qstr2[NSTRING]; + LINE *eopline; + REGION region; + + if(curbp->b_mode&MDVIEW){ /* don't allow this command if */ + return(rdonly()); /* we are in read only mode */ + } + else if (fillcol == 0) { /* no fill column set */ + mlwrite("No fill column set", NULL); + return(FALSE); + } + else if(curwp->w_dotp == curbp->b_linep) /* don't wrap! */ + return(FALSE); + + /* record the pointer to the line just past the EOP */ + if(gotoeop(FALSE, 1) == FALSE) + return(FALSE); + + eopline = curwp->w_dotp; /* first line of para */ + + /* and back to the beginning of the paragraph */ + gotobop(FALSE, 1); + + /* determine if we're justifying quoted text or not */ + qstr = ((glo_quote_str || (Pmaster && Pmaster->quote_str)) + && quote_match(glo_quote_str ? glo_quote_str + : Pmaster->quote_str, + curwp->w_dotp, qstr2, NSTRING) + && *qstr2) ? qstr2 : NULL; + qlen = qstr ? strlen(qstr) : 0; + + /* let yank() know that it may be restoring a paragraph */ + thisflag |= CFFILL; + + if(!Pmaster) + sgarbk = TRUE; + + curwp->w_flag |= WFMODE; + + /* cut the paragraph into our fill buffer */ + fdelete(); + curwp->w_doto = 0; + getregion(®ion, eopline, llength(eopline)); + if(!ldelete(region.r_size, finsert)) + return(FALSE); + + /* Now insert it back wrapped */ + spaces = word_len = line_len = same_word = 0; + + /* Beginning with leading quoting... */ + if(qstr){ + while(qstr[line_len]) + linsert(1, qstr[line_len++]); + + line_last = ' '; /* no word-flush space! */ + } + + /* ...and leading white space */ + for(i = qlen; (c = fremove(i)) == ' ' || c == TAB; i++){ + linsert(1, line_last = c); + line_len += ((c == TAB) ? (~line_len & 0x07) + 1 : 1); + } + + /* then digest the rest... */ + while((c = fremove(i++)) > 0){ + switch(c){ + case '\n' : + i += qlen; /* skip next quote string */ + if(!spaces) + spaces++; + same_word = 0; + break; + + case TAB : + case ' ' : + spaces++; + same_word = 0; + break; + + default : + if(spaces){ /* flush word? */ + if((line_len - qlen > 0) + && line_len + word_len + 1 > fillcol + && ((isspace((unsigned char)line_last)) + || (linsert(1, ' '))) + && (line_len = fpnewline(qstr))) + line_last = ' '; /* no word-flush space! */ + + if(word_len){ /* word to write? */ + if(line_len && !isspace((unsigned char) line_last)){ + linsert(1, ' '); /* need padding? */ + line_len++; + } + + line_len += word_len; + for(j = 0; j < word_len; j++) + linsert(1, line_last = word[j]); + + if(spaces > 1 && strchr(".?!:;\")", line_last)){ + linsert(2, line_last = ' '); + line_len += 2; + } + + word_len = 0; + } + + spaces = 0; + } + + if(word_len + 1 >= NSTRING){ + /* Magic! Fake that we output a wrapped word */ + if((line_len - qlen > 0) && !same_word++){ + if(!isspace((unsigned char) line_last)) + linsert(1, ' '); + line_len = fpnewline(qstr); + } + + line_len += word_len; + for(j = 0; j < word_len; j++) + linsert(1, word[j]); + + word_len = 0; + line_last = ' '; + } + + word[word_len++] = c; + break; + } + } + + if(word_len){ + if((line_len - qlen > 0) && (line_len + word_len + 1 > fillcol)){ + if(!isspace((unsigned char) line_last)) + linsert(1, ' '); + (void) fpnewline(qstr); + } + else if(line_len && !isspace((unsigned char) line_last)) + linsert(1, ' '); + + for(j = 0; j < word_len; j++) + linsert(1, word[j]); + } + + /* Leave cursor on first char of first line after paragraph */ + curwp->w_dotp = lforw(curwp->w_dotp); + curwp->w_doto = 0; + + return(TRUE); +} + + +/* + * fpnewline - output a fill paragraph newline mindful of quote string + */ +fpnewline(quote) +char *quote; +{ + int len; + + lnewline(); + for(len = 0; quote && *quote; quote++, len++) + linsert(1, *quote); + + return(len); +}