Xref: utzoo comp.emacs:6654 comp.sources.d:3958 Path: utzoo!attcan!uunet!tut.cis.ohio-state.edu!unmvax!ncar!ames!ucsd!orion.cf.uci.edu!uci-ics!zardoz!tgate!ka3ovk!drilex!axiom!insyte!m2 From: m2@insyte.UUCP (Mike Arena) Newsgroups: comp.emacs,comp.sources.d Subject: MicroEMACS 3.10 bugs, fixes and a MAJOR improvement to file completion Message-ID: <234@insyte.UUCP> Date: 10 Aug 89 16:20:57 GMT Reply-To: m2@insyte.UUCP (Michael J. Arena) Organization: Innovative Systems Techniques, Newton, MA Lines: 199 I like MicroEMACS 3.10. I am impressed with the level and scope of portability that has been achieved. However, I have a few complaints and fixes: 1) mlwrite() in display.c tries to do its own variable argument parsing based on STACK_GROWS_UP. This is ridiculous. Of all the systems I've ported this to (HPUX, VMS, SUNOS4, APOLLO, MSDOS), every one had and some handled the stack in strange ways (especially RISC machines and alignment). If you have a standard facility, then use it. 2) The file char.[co] seems to be left out of several makefiles. A minor nit but I would have assumed that these makefiles were tested. 3) The VMS DESCRIP.MMS is referencing SMG.OBJ and VMSVT.C. Where are these? It seems that VMSVT.C was incorporated into VMS.C but the SMG stuff is nowhere to be found (VMS4.7, VAXC2.3). 4) The file name completion routines were amazingly inefficient. It actually rescanned the entire directory for each CHARACTER that matched even if there was only one matching entry. Also, it would not complete directory names which mostly defeats the purpose of the function. The fixes below permit directory names to be completed and will scan a directory ONCE. While scanning, the longest possible match is remebered. If the match is a directory, then the DIRSEPCHAR is appended. 5) For tcap.c, it was a good idea to have function key parsing that standardized the names. However, it is now quite difficult to deal with application keypads. I use a VT100 like terminal with 8 function keys and an 18 key keypad. Most of the keypad is wasted since a standard termcap only allows for 10 function keys and a few special keys like delete character, page up/down, etc. I can't think of a solution so maybe I shouldn't complain. Below are the 2 functions in unix.c which were changed. Following these is the comp_file() function in input.c. ---------------------------------------------------------------------- char *PASCAL NEAR getffile(fspec) char *fspec; /* pattern to match */ { register int index; /* index into various strings */ register int point; /* index into other strings */ register int extflag; /* does the file have an extention? */ int currentdir = FALSE; /* first parse the file path off the file spec */ strcpy(path, fspec); index = strlen(path) - 1; while (index >= 0 && (path[index] != '/' && path[index] != '\\' && path[index] != ':')) --index; path[index+1] = 0; #if HPUX if (index < 0) { strcpy(path,"./"); index = 1; currentdir = TRUE; } #endif /* check for an extension */ point = strlen(fspec) - 1; extflag = FALSE; while (point >= 0) { if (fspec[point] == '.') { extflag = TRUE; break; } point--; } /* open the directory pointer */ if (dirptr != NULL) { closedir(dirptr); dirptr = NULL; } dirptr = opendir(path); if (dirptr == NULL) return(NULL); #if HPUX if (currentdir == TRUE) path[0] = '\0'; #endif strcpy(rbuf, path); nameptr = &rbuf[strlen(rbuf)]; /* and call for the first file */ return(getnfile()); } char *PASCAL NEAR getnfile() { register struct direct *dp; /* directory entry pointer */ register int index; /* index into various strings */ struct stat fstat; /* and call for the next file */ nxtdir: dp = readdir(dirptr); if (dp == NULL) return(NULL); /* check to make sure we skip directory entries */ strcpy(nameptr, dp->d_name); stat(rbuf, &fstat); if (((fstat.st_mode & S_IFMT) != S_IFREG) && ((fstat.st_mode & S_IFMT) != S_IFDIR)) goto nxtdir; if ((fstat.st_mode & S_IFMT) == S_IFDIR) strcat(rbuf,"/"); /* return the next file name! */ return(rbuf); } ---------------------------------------------------------------------- Here is the modified comp_file(): comp_file(name, cpos) char *name; /* file containing the current name to complete */ int *cpos; /* ptr to position of next character to insert */ { register char *fname; /* trial file to complete */ register int index; /* index into strings to compare */ register int matches; /* number of matches for name */ char longestmatch[NSTRING]; /* temp buffer for longest match */ int longestlen; /* length of longest match (always > *cpos) */ /* everything (or nothing) matches an empty string */ if (*cpos == 0) return; /* first, we start at the first file and scan the list */ matches = 0; name[*cpos] = 0; fname = getffile(name); while (fname) { /* is this a match? */ if (strncmp(name,fname,*cpos) == 0) { /* count the number of matches */ matches++; /* if this is the first match, simply record it */ if (matches == 1) { strcpy(longestmatch,fname); longestlen = strlen(longestmatch); } else { /* if there's a difference, stop here */ if (longestmatch[*cpos] != fname[*cpos]) return; for (index = (*cpos) + 1; index < longestlen; index++) if (longestmatch[index] != fname[index]) { longestlen = index; longestmatch[longestlen] = 0; } } } /* on to the next file */ fname = getnfile(); } /* beep if we never matched */ if (matches == 0) { TTbeep(); return; } /* the longestmatch array contains the longest match so copy and print it */ for ( ; (*cpos < (NSTRING-1)) && (*cpos < longestlen); (*cpos)++) { name[*cpos] = longestmatch[*cpos]; TTputc(name[*cpos]); } name[*cpos] = 0; /* if only one file matched then increment cpos to signal complete() */ /* that this was a complete match. If a directory was matched then */ /* last character will be the DIRSEPCHAR. In this case we do NOT * /* want to signal a complete match. */ if ((matches == 1) && (name[(*cpos)-1] != DIRSEPCHAR)) (*cpos)++; TTflush(); return; } -- Michael J. Arena (617) 965 8450 | UUCP: ...harvard!linus!axiom!insyte!m2 Innovative Systems Techniques | ...harvard!necntc!lpi!insyte!m2 1 Gateway Center, Newton, MA 02158 | ARPA: insyte!m2@harvard.harvard.edu