home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 337_01 / l_list.c < prev    next >
C/C++ Source or Header  |  1991-01-14  |  11KB  |  299 lines

  1. /* Copyright (c) James L. Pinson 1990,1991  */
  2.  
  3. /**********************   L_LIST.C   ***************************/
  4.  
  5. #include "mydef.h"   /* always include this */
  6. #include "stddef.h"  /* we need the definition of NULL from here */
  7. #include "dos.h"     /* directory related header files */
  8.  
  9. #include "stdio.h"
  10. #include "string.h"
  11.  
  12. /* load memory allocation header files for specific compiler */
  13.  
  14. #if defined QUICKC
  15.  
  16. #include "malloc.h"
  17. #include "memory.h"
  18.  
  19. #endif
  20.  
  21. #if defined TURBOC
  22.  
  23. #include "alloc.h"
  24. #include "mem.h"
  25. #include "stdlib.h"
  26. #include "dir.h"
  27.  
  28. #endif
  29.  
  30.  
  31. /*****************************************************************
  32.  
  33.  Usage: int list_select (char *ptr[]);
  34.  
  35.  
  36.         char *ptr[]= Array of pointers, each of which points to
  37.                      to a option. The pointer following the last
  38.                      option must be NULL.
  39.  
  40.  This function allows selection from a list of options.  The user
  41.  may point to the option using the Up/Down cursor keys, and select
  42.  by pressing Enter.   Pressing Escape exits without making a
  43.  selection.
  44.  
  45.  The user may also Speed Search by typing in the option. As the
  46.  user types in the text, the option most closely matching the typed
  47.  text is highlighted.  Actual selection must still be made by
  48.  pressing Enter.
  49.  
  50.  The number corresponding to the selection is returned.  A -1
  51.  indicates the user pressed Escape without making a selection.
  52.  
  53. *****************************************************************/
  54.  
  55. int list_select (char *ptr[])
  56. {
  57. extern struct  screen_structure scr;
  58. extern struct window_structure w[];
  59.  
  60. int current_opt=0;    /* highlighted current option */
  61. int top_opt=0;        /* first option in window */
  62. int offset=0;         /* distance between top_opt and current_opt */
  63. int last_opt;         /* the last option which was highlighted */
  64. int height;           /* height of the window */
  65. int last=0;           /* last element in pointer array */
  66. int i=0,y,j=0;        /* general purpose */
  67. char ch,ext;          /* character and extension*/
  68. int sub_search=0;     /* index for location within search string */
  69. int sub_option=0 ;    /* index for location within list options */
  70. char search[MAX_STRING];  /* holds the speedsearch characters */
  71. int redraw=TRUE;          /* flag which forces a redraw of selection
  72.                              window */
  73. int start,end;            /* pre-existing start end scan lines */
  74. height = scr.bottom-scr.top +1;   /* height of selection window */
  75.  
  76. /* find out how many options are in the NULL terminated
  77.    array of pointers */
  78.  
  79. for(last=0;ptr[last++]!=NULL;);
  80. last-=2;     /* decrease by one so "last"
  81.                 now indicates the last option */
  82.  
  83. scr.current=scr.normal;
  84. what_cursor(&start,&end);
  85.  
  86. /* draw initial window */
  87.  
  88. cursor(NO_CURSOR); /* turn off cursor */
  89. y=1;
  90.  
  91. /* begin loop to process use selection */
  92.  
  93.  for(;;){
  94.  
  95.   if(redraw){     /* redraw the window contents */
  96.    alt_screen(ON); /* turn on alternate screen so that
  97.                       redraw appears to be instantaneous */
  98.    cls();
  99.    y=1;    /* y location (row) to print option */
  100.    scr.current=scr.normal;      /* start with normal attribute */
  101.  
  102.     for(i=top_opt;i<top_opt+height;i++){
  103.     if (ptr[i]==NULL) break;     /* stop if we go too far */
  104.      if (i==current_opt)scr.current=scr.inverse;
  105.  
  106.       /* highlight current option */
  107.       print (1,y++,ptr[i]);
  108.       scr.current=scr.normal;   /* reset to normal */
  109.     }
  110.    alt_screen(OFF);
  111.    redraw=FALSE;
  112.   } /* end if (redraw) */
  113.  
  114.   ch='\0';ext='\0';       /* reset character and extension */
  115.   get_key( &ch, &ext);    /* get character and extension */
  116.  
  117.   /* scan list of options match search key */
  118.  
  119.   /* make sure we have a valid letter, number or punctuation */
  120.   if (ch>=32 && ch <=126 ) {
  121.  
  122.    /* here we search to find match for speed search letters */
  123.    last_opt=current_opt;     /* save the highlight position */
  124.  
  125.    if(sub_search==0){     /* are we looking for the first letter
  126.                              of the word? */
  127.      for(i=0;i<=last;i++){  /* scan each list option */
  128.        sub_option=0;    /* look for the first letter within option */
  129.        while(ptr[i][sub_option]==' ') sub_option++; /* skip spaces */
  130.  
  131.        if(toupper(ptr[i][sub_option])==toupper(ch)){ /* match*/
  132.             search[sub_search]=ch;  /* add it to the speed search
  133.                                        string */
  134.             offset=current_opt-top_opt;  /* difference between window
  135.                                             top and highlighter */
  136.             current_opt=i;      /* set current_opt to option found */
  137.             sub_search++;       /* reposition indexes within search */
  138.             sub_option++;       /* string and option */
  139.  
  140.             break;
  141.        }
  142.      }  /* end scan each list option */
  143.    } /* end first letter */
  144.    else{    /* No longer the first letter.
  145.                The next loop examines further letters within the
  146.                current highlighted option to see if they still
  147.                match ch.*/
  148.  
  149.    if(toupper(ptr[current_opt][sub_option]) != toupper(ch)){
  150.       /* Match with current highlighted option fails.
  151.          Scan list to see if we can match string elsewhere. */
  152.  
  153.      search[sub_search]=ch;  /* finish building string */
  154.      search[sub_search+1]='\0';
  155.      sub_search=0;    /* reset to begin search at first letter */
  156.  
  157.       /* see if a match exists anywhere else */
  158.  
  159.       for(i=0;i<=last;i++){   /* examine each option */
  160.        sub_option=0;          /* start at beginning of
  161.                                  each option */
  162.        while(ptr[i][sub_option]==' ') /* skip space */
  163.            sub_option++;
  164.  
  165.            j=pos(&ptr[i][sub_option],search); /* is search string
  166.                                                  in option? */
  167.            if (j==0){                     /* search string found */
  168.             offset=current_opt-top_opt;  /* calculate distance
  169.                                             (top to current)*/
  170.             current_opt=i;
  171.             sub_search=strlen(search);
  172.             sub_option=j+strlen(search);
  173.             break;
  174.            }
  175.       } /* end (examine each option) */
  176.  
  177.    } /* end failed to match within current option */
  178.      else
  179.       {   /* current option still matches search key */
  180.        search[sub_search]=ch;
  181.        sub_search++;
  182.       }
  183.    } /* end of (not first letter) */
  184.  
  185. /* the following code moves the highlighter or
  186.    requests a redraw as needed */
  187.  
  188.  
  189.   /* is new selection beyond window?  */
  190.  
  191.   if(current_opt >top_opt+ height-1 || current_opt < top_opt){
  192.     top_opt=current_opt-offset;   /* keep the offset the same */
  193.     if (top_opt <0) top_opt=0;    /* correct if off top of window */
  194.     redraw=TRUE;                  /* redraw window */
  195.   } else{
  196.                /* new option is within displayed page */
  197.                /* un-highlight old position and redraw highlight */
  198.      scr.current=scr.normal;  /* over-write highlighter with
  199.                                  normal attribute */
  200.      print(1,last_opt-top_opt+1,ptr[last_opt]);
  201.  
  202.      scr.current=scr.inverse;  /* print new highlighter */
  203.      print(1,current_opt-top_opt+1,ptr[current_opt]);
  204.     }
  205.  
  206.   } /* end valid letter */
  207.  
  208.   else /* not valid letter */
  209.   {
  210.    sub_search=0;  /* reset sub_search to look for first letter */
  211.  
  212.     if(ch==RETURN || ch==ESCAPE){ /* selection made or Escape key */
  213.       scr.current= scr.normal;
  214.       set_cursor(start,end);
  215.      if (ch==RETURN) return(current_opt); /* item selected */
  216.       else
  217.        return(-1);         /* no selection */
  218.     }
  219.      y=current_opt-top_opt+1;   /* y = distance from top of window
  220.                                    to highlighter */
  221.  
  222.    /* down arrow and not at bottom of window */
  223.    if (ext==DOWN && y<height && current_opt<last ){
  224.      /* overwrite highlighter with normal attribute */
  225.      scr.current=scr.normal;
  226.      print(1,y,ptr[current_opt]);
  227.  
  228.      scr.current=scr.inverse;
  229.      current_opt++;                  /* increment list pointer */
  230.      print(1,y+1,ptr[current_opt]);  /* print new highlighter */
  231.    }
  232.     else  /* down arrow and bottom of window */
  233.  
  234.    if (ext==DOWN && y==height && current_opt<last){
  235.  
  236.     /* rewrite current line with normal attribute */
  237.     scr.current=scr.normal;
  238.     print(1,y,ptr[current_opt]);
  239.     scroll_up (1);                    /* scroll window up */
  240.     current_opt++;                    /* increment positions */
  241.     top_opt++;
  242.     scr.current=scr.inverse;       /* print a new highlighter */
  243.     print(1,y,ptr[current_opt]);
  244.    }
  245.    if (ext==UP && y>1){   /* up arrow and not at top of window */
  246.      /* rewrite current line with normal attribute */
  247.      scr.current=scr.normal;
  248.      print(1,y,ptr[current_opt]);
  249.  
  250.      scr.current=scr.inverse;
  251.      current_opt--;               /* increment list pointer */
  252.      print(1,y-1,ptr[current_opt]); /* print new highlighter */
  253.    } else
  254.    if (ext==UP && y==1 && current_opt>0){  /* up arrow and top
  255.                                               of window */
  256.    /* rewrite current line with normal attribute */
  257.     scr.current=scr.normal;
  258.     print(1,y,ptr[current_opt]);
  259.     scroll_down (1);                 /* scroll window down */
  260.     current_opt--;                   /* move current_opt back */
  261.     top_opt--;
  262.  
  263.       scr.current=scr.inverse;       /* print new highlighter */
  264.      print(1,y-1,ptr[current_opt]);
  265.    }
  266.  
  267.   /* page down and not at end of selection list */
  268.   if(ext==PGDN && top_opt!= last) {
  269.     offset=current_opt-top_opt; /* how far is the highlighter
  270.                                    from the top of window? */
  271.     top_opt+=height;            /* increase top_opt by the height
  272.                                    of screen */
  273.     current_opt=top_opt+offset; /* increase current_opt for
  274.                                    new location */
  275.      /* check for boundary errors */
  276.     if(top_opt>last) top_opt=last;
  277.     if(current_opt>last) current_opt=last;
  278.  
  279.     redraw=TRUE;  /* force a redraw of list options */
  280.  
  281.   }
  282.   if(ext==PGUP && top_opt !=0){  /* PgUp pressed and not at top
  283.                                     of window */
  284.     offset=current_opt-top_opt;  /* move all positions up */
  285.     top_opt-=height;
  286.     current_opt=top_opt+offset;
  287.  
  288.     if(top_opt<0){     /* out of bounds ?*/
  289.      top_opt=0;        /* reset */
  290.      current_opt=offset;
  291.     }
  292.     redraw=TRUE;
  293.  
  294.   } /* end ext==PGUP */
  295.   } /* end of not valid letter */
  296.  
  297.  } /* end of for(;;) loop which reads user selection*/
  298. }
  299.