static char rcsid[] = "$Id: ranger1.c,v 1.1 1992/09/06 19:31:32 mike Exp $";

/* $Log: ranger1.c,v $
 * Revision 1.1  1992/09/06  19:31:32  mike
 * Initial revision
 *
 */

/* ranger1.c
 * ranger1:
 *   This routine cruises through a list (sorted array of structures, one of
 *     which is a pointer to a string) and picks a range that word falls in.
 *   ???Blank ("") entries are skipped.  Depends.  Sometimes.  I don't think
 *     this part works all that well.
 *   "" does NOT match "".
 *
 * Input:
 *   start:  A pointer to the string (char *) in the first structure of the
 *     list.  Yes, a pointer to a pointer.
 *   blobs:  The number of elements in the list.  MUST be >= 0.
 *   blobsize:  sizeof() each structure in the list.
 *   word:  What we are looking for in the list.
 * Output:
 *   matched:  number of characters in word ALSO in at least one item in
 *     list.
 *   commonchars:  given the range word falls in, these are the letters in
 *     common in the range.
 * Returns: TRUE if word is in list else FALSE
 *
 * Fact: The number of letters in commonchars >= matched.
 *
 * Alg:
 *  1. find the max letters in word also in list (match-word)
 *  2. find the range of words in list that have match-word in them
 *  3. find max letters in common in range.
 * C Durland
 */

/* idea for ranger3:  pass in incit():  a routine to call when need to move
 * to next structure.  Can be used for linked lists, etc.  Note:  can't use
 * incptr as a default unless want to pass in blobsize (or could have
 * blobsize double as offset).  Note:  If I do this, start will have to
 * point to the start of the structure and ranger3 will have to know the
 * offset of (char *).  Could sleeze and subtract offset to find start of
 * structure.
 */

/* Copyright 1989, 1990 Craig Durland
 *   Distributed under the terms of the GNU General Public License.
 *   Distributed "as is", without warranties of any kind, but comments,
 *     suggestions and bug reports are welcome.
 */

#include <const.h>

	/* increment a (char **) n bytes */
#define incptr(ptr,n) (char**)((char *)ptr +n)

ranger1(start,blobs,blobsize,word,matched,commonchars)
  char **start, *word, *commonchars;  int *matched, blobs, blobsize;
{
  char **a = NULL, **b = NULL, c, **ptr;
  register int j, len, s;

  *commonchars = '\0'; *matched = 0;
  if (0 == (len = strlen(word))) return FALSE;	/* "" don't match nuthing */
tryagain:
  for (j = blobs, ptr = start; j--; ptr = incptr(ptr,blobsize))
  {
    if (**ptr == '\0') continue;		/* ignore blank entry */
    if ((s = strncmp(word,*ptr,len)) == 0)	/* len characters match */
      if (a == NULL) a = ptr;	/* the start of the matched words */
      else b = ptr;		/* the end of the range */
    else if (s < 0) break;  /* don't search entire list if don't have to */
  }

  if (a == NULL)			/* no match in the list */
    if (len > 0)	/* is there a match on the first n-1 characters? */
      { len--; goto tryagain; }
    else return FALSE;		/* no possible match */
  *matched = len;
  if (b == NULL)	/* only one instance of at least part of word */
  {
    strcpy(commonchars,*a);
    return (0 == strcmp(word,commonchars));	/* maybe a commplete match */
  }

	/* Have a range of words in list that match the first len chars of
	 *   word.
	 * All words in range have their first len chars in common.
	 * Now find the most characters that the words in range have in
	 *   common.  This can be lots more than len.
	 */
  for (len--; c = *(*a + len); len++)	/* ???remember "" entries */
    for (ptr = incptr(a,blobsize); ptr <= b; ptr = incptr(ptr,blobsize))
      if (**ptr != '\0' && *(*ptr+len) != c) goto done;	/* mismatch */

done:
  strcpy(commonchars,*a); commonchars[len] = '\0';
  return FALSE;
}
