commit f3ea0095dfe20e97f061fedcf08693ec8405b775 Author: hellisabove <59116609+hellisabove@users.noreply.github.com> Date: Sat Mar 18 20:26:52 2023 +0200 Added source code 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); +}