home *** CD-ROM | disk | FTP | other *** search
-
- /*
-
- DEVELOPING A FILE SELECTION WINDOW IN TURBO C
- ----------------------------------------------
- Garry J. Vass [72307,3311]
-
- Copyright (c), 1987, Telemacus Software Associates
-
-
- This file contains the nucleus routines for developing
- a file selection window using Turbo C and QLIB (release
- 4 or above). File selection windows have the following
- advantages:
-
- - As can be seen here, they are VERY easy to develop.
-
- - The user is not burdened with having to remember
- file names;
-
- - The programmer has more control over the selection
- and processing of files; and
-
- - The overall presentation of the program is improved.
-
- GENERAL NOTES, CAVEATS, AND DRUNKEN RAMBLINGS
- ---------------------------------------------
-
- Use the LARGE memory model for compiling this program.
-
- Where possible, I tried to use the keyboard conventions (arrows,
- home, end, etc) in the file selection routines found in NU.EXE
- (viz., Norton Utility). The program does not have the feature
- of scrolling the entire screen display to accomodate an additional
- column.
-
- This prototype stubs in the error processing if the maximum
- number of files has been exceeded. These must be added
- according to the application.
-
- An array structure is used to store and present the file names.
- Arrays are handy because the members can be easily accessed. They
- are troublesome because they must be specified to an explicit size
- and must be contained within the data segment. Production quality
- and/or heavy duty directory processing routines should use
- linked lists, or related dynamic structures, for storing file names.
-
- This program was developed on an IBM AT with EGA under DOS 3.2 using
- Turbo C 1.0 and QLIB-4. The functions (modified for linked list
- structures and extended error processing logic) were incorporated
- into a production-level expert system - with hooks into Turbo Prolog.
- The application itself deals with the optimal allocation/assignment
- and PSA good delivery rules of wirable MBS pools (a Wall Street
- investment banking application). Thanks, Borland!!
-
- As might be expected, OS/2 users must use the dos box for this
- program. QLIB for OS/2 is currently in the works...
- */
-
- /*********************** BEGIN SOURCE FOR PICKFILE ********************/
- /*********************** INCLUDES FOR PICKFILE ************************/
- /* dir.h contains the directory get and file name parse functions */
- #include <dir.h>
- /* qtypes.c contains the requisite type declarations for this program */
- #include <qtypes.c>
- /* qkeys.c contains the qreadkbd translation tokens (optional) */
- #include <qkeys.c> /* can be found in go bor */
- /* qcolors.c contains the english tokens for screen attributes (optional)*/
- #include <qcolors.c> /* can be found in go bor */
- /*********************** END OF INCLUDES FOR PICKDIR *******************/
-
- /*********************** DEFINES FOR PICKFILE **************************/
- #define filename filefb.ff_name /* abbreviation */
- #define file_att filefb.ff_attrib /* abbreviation */
- #define filesize filefb.ff_fsize /* abbreviation */
- #define filedate filefb.ff_fdate /* abbreviation */
- #define filetime filefb.ff_ftime /* abbreviation */
- #define MAX_FILES 100 /* Max files before error logic */
- #define WINDOW_UL_X 0 /* Box coordinates for PICKFILE */
- #define WINDOW_UL_Y 0 /* window */
- #define WINDOW_LR_X 79 /* */
- #define WINDOW_LR_Y 22 /* */
- #define XINCREMENT 15 /* Horizontal increment */
- #define FILE_BACK black /* File name display background */
- #define FILE_FORE white /* File name display foreground */
- #define WINDOW_DEPTH WINDOW_LR_Y - WINDOW_UL_Y
- /************************ END OF DEFINES FOR PICKFILE ******************/
- /************************ STRUCTS AND TYPEDEFS FOR PICKFILE ************/
- struct ffblk filefb; /* see dir.h */
- typedef struct
- {
- qint sx; /* screen column for this file */
- qint sy; /* screen row for this file */
- struct ffblk file_info; /* nested structure */
- }
- full_file_record;
-
- /******************** END OF STRUCTS AND TYPES FOR PICKFILE ***************/
- /******************* GLOBAL VARIABLES FOR PICKFILE ***********************/
- full_file_record
- ffr[MAX_FILES]; /* Array for found files */
- int filesfound = 0; /* Count for found files */
- qint currentsx = 0; /* For screen save/restore */
- qint currentsy = 0; /* For screen save/restore */
- qint maincounter = 0; /* General index */
- qint originalx = 0; /* For screen save/restore */
- qint originaly = 0; /* For screen save/restore */
- qstring mainstring = ""; /* For return value */
-
- prompt_record filespecification =
- {
- "PLEASE ENTER A DIRECTORY SEARCH SPECIFICATION: ",/* tag qstring */
- "*.exe", /* tag value */
- 0, /* tag x*/
- 12, /* tag y*/
- 50, /* val x */
- 12, /* val y */
- 13, /* max chars */
- bright_white, /* tag fore */
- black, /* tag back */
- white, /* val fore */
- dark_blue, /* val back */
- 0, /* case conversion */
- " ", /* edit mask */
- " ", 0, " ", " ", " ", 0};
- /************************* END OF GLOBAL VARIABLES FOR PICKFILE ***********/
- /**************************************************************************/
- /************************* PICKFILE SUPPORT FUNCTIONS ********************/
- void initialize_coordinates()
- {
- /*
- This function simply initializes the screen coordinates to where
- the display of file names should begin.
- */
- currentsx = WINDOW_UL_X + 2;
- currentsy = WINDOW_UL_Y + 1;
- }
- /*************************************************************************/
- void update_current_coordinates()
- {
- /*
- This service function increments the screen coordinates
- in a verticle manner. As each column is filled, the next
- column is calculated using the XINCREMENT variable.
- */
- ++currentsy;
- if (currentsy >= WINDOW_LR_Y)
- {
- currentsy = WINDOW_UL_Y + 1;
- currentsx = currentsx + XINCREMENT;
- if (currentsx + XINCREMENT > WINDOW_LR_X)
- {
- printf("program limits exceeded\n");
- /* calls to error logic go here */
- abort();
- }
- }
- }
- /*************************************************************************/
- qint get_files
- (
- qstring search_specification
- )
- {
- /*
- This function accepts a search specification (such as *.*) and loops
- through the current directory, storing each match into an array.
- */
- int filerc = 0;
- filesfound = 0;
- filerc = findfirst(search_specification, &filefb, 0xff);
- while (!filerc)
- {
- if ((filename[0] != 46) && /* exclude those pesky periods... */
- (file_att != 0x10)) /* and subdirectories */
- {
- ffr[filesfound].sx = currentsx;
- ffr[filesfound].sy = currentsy;
- ffr[filesfound].file_info = filefb;
- update_current_coordinates();
- ++filesfound;
- }
- if (filesfound >= MAX_FILES)
- {
- printf("program limits exceeded\n");
- /* calls to error logic go here */
- abort();
- }
- filerc = findnext(&filefb);
- }
- return(filesfound - 1);
- }
- /*************************************************************************/
- void display_file_box()
- {
- /*
- This is the engine presentation routine. It draws a box then
- displays all the matched file names at the screen coordinates.
- */
- qint displaycounter;
- qdrawbox
- (WINDOW_UL_X,
- WINDOW_UL_Y,
- WINDOW_LR_X,
- WINDOW_LR_Y,
- "",
- "[ PRESS F1 FOR HELP ]",
- (dark_blue<<4) | white,
- bright_white,
- bright_white);
- for (displaycounter=0;displaycounter<=filesfound;++displaycounter)
- {
- qsnap
- (ffr[displaycounter].file_info.ff_name,
- ffr[displaycounter].sx,
- ffr[displaycounter].sy,
- bright_white);
- }
- }
- /*************************************************************************/
- void unhighlight_area
- (
- qint startx,
- qint starty,
- qint length
- )
- {
- qreset_box_attribute
- (startx,
- starty,
- startx + length,
- starty,
- (FILE_BACK<<4) | FILE_FORE);
- }
- /*************************************************************************/
- void highlight_area
- (
- qint startx,
- qint starty,
- qint length
- )
- {
- qreset_box_attribute
- (startx,
- starty,
- startx + length,
- starty,
- (FILE_FORE<<4) | FILE_BACK);
- }
- /*************************************************************************/
- void give_file_help()
- {
- /*
- This function displays the help window when the F1 key is hit.
- */
- qscreen file_help_screen;
- qint file_help_ul_x = 20;
- qint file_help_ul_y = 5;
- qint file_help_lr_x = 60;
- qint file_help_lr_y = 15;
- qint file_help_index;
- qstring file_help_text[9] =
- {
- "Use the arrow keys (Up, Down, Home, ",
- "and End, to orient the highlighted ",
- "area on the file you wish to select. ",
- "Press the Enter (Return, Advance, ",
- "etc) key to exit with your selection.",
- " ",
- "To exit without making a selection, ",
- "press the Escape key. ",
- " "
- };
- qwindow_save /* save the screen area */
- (file_help_ul_x,
- file_help_ul_y,
- file_help_lr_x,
- file_help_lr_y,
- file_help_screen);
- qdrawbox /* draw a box for the help window */
- (file_help_ul_x,
- file_help_ul_y,
- file_help_lr_x,
- file_help_lr_y,
- "",
- "[ hit any key to continue ]",
- bright_white,
- bright_white,
- bright_white | blink);
- for (file_help_index=0;file_help_index<9;++file_help_index)
- {
- qsnap /* display the help text */
- (file_help_text[file_help_index],
- file_help_ul_x + 2,
- file_help_ul_y + file_help_index + 1,
- bright_white);
- }
- file_help_index = qreadkbd(); /* wait for a key */
- qwindow_restore /* restore the screen area */
- (file_help_ul_x,
- file_help_ul_y,
- file_help_lr_x,
- file_help_lr_y,
- file_help_screen);
- }
- /*************************************************************************/
- qint pick_file_menu()
- {
- /*
- This is the driver function for the PICKFILE presentation. It is
- similar in form and structure to the qbounce(~~~) function (available
- at go bor).
- */
-
- qint menucounter;
- qint keypressed;
- keypressed = 0;
- menucounter = 0;
- qgotoxy(0, 25);
- highlight_area /* highlight the first file */
- (ffr[menucounter].sx,
- ffr[menucounter].sy,
- XINCREMENT - 1);
- while (keypressed != return_pressed)
- {
- keypressed = qreadkbd(); /* get a keystroke */
- if (keypressed != return_pressed)
- {
- unhighlight_area
- (ffr[menucounter].sx,
- ffr[menucounter].sy,
- XINCREMENT - 1);
- switch (keypressed)
- {
- case escape_pressed:
- { /* escape means exit with no file selection */
- return (filesfound + 1);
- }
- case f01pressed:
- { /* F1 means give help */
- give_file_help();
- break;
- }
- case home_pressed:
- { /* HOME means reset the pointer */
- menucounter = 0;
- }
- case up_arrow_pressed:
- { /* UP ARROW means go to previous file */
- menucounter = qmax(menucounter - 1, 0);
- break;
- }
- case end_pressed:
- { /* END means go to last file */
- menucounter = filesfound;
- break;
- }
- case down_arrow_pressed:
- { /* DOWN ARROW means go to next file */
- ++menucounter;
- if (menucounter > filesfound)
- {
- menucounter = 0;
- }
- break;
- }
- case right_arrow_pressed:
- { /* RIGHT ARROW means "move over one column" */
- menucounter = menucounter + WINDOW_DEPTH - 1;
- if (menucounter > filesfound)
- {
- menucounter = filesfound;
- }
- break;
- }
- case left_arrow_pressed:
- { /* LEFT ARROW means "move back one column" */
- menucounter = qmax(menucounter - WINDOW_DEPTH + 1, 0);
- break;
- }
- }
- highlight_area
- (ffr[menucounter].sx,
- ffr[menucounter].sy,
- XINCREMENT - 1);
- }
- }
- return(menucounter);
- }
- /*************************************************************************/
- void select_a_file
- (
- qstring search_specification,
- qstring file_that_was_selected
- )
- {
- /*
- This is the driver function for PICKFILE engine and presentation.
- */
- /*
- Set the screen coordinates to the upper left corner of the
- presentation box.*/
- initialize_coordinates();
- /* Initialize the parameter to be returned. */
- strcpy(file_that_was_selected, "");
- /* Load the file array with those that matched the specification */
- filesfound = get_files(search_specification);
- /* If anything was found, present the file selection window */
- if (filesfound >= 0)
- {
- /* file sort function goes here */
- display_file_box();
- initialize_coordinates();
- maincounter = 0;
- maincounter = pick_file_menu();
- if (maincounter <= filesfound)
- {
- strcpy(file_that_was_selected, ffr[maincounter].file_info.ff_name);
- }
- }
- qclrscr(bright_white);
- }
- /************************* BECIN MAINLINE *****************************/
- main()
- {
- qint anyint;
- qscreen mainscreen;
- qint mainx;
- qint mainy;
-
- /*
- Start off by saving the screen at invocation time
- */
- mainx = qwherex();
- mainy = qwherey();
- qwindow_save(0, 0, 79, 24, mainscreen);
-
- /*
- Clear the screen
- */
- qclrscr(bright_white);
-
- /*
- Get a file search specification from
- the user.
- */
- qprompt(&filespecification);
-
- /*
- If the user simply hit carraige return,
- then exit, otherwise process the specification.
- */
- while (filespecification.value[0] > 0)
- {
- qclrscr(bright_white);
- select_a_file(filespecification.value, mainstring);
- qgotoxy(0,25); /* hide the cursor */
- if (mainstring[0] > 0)
- {
- /*
- If the variable "mainstring" contains something,
- then a file was selected. Here it is simply
- printed out.
- */
- qsnap("You selected ", 29, 23, bright_white);
- qsnap(mainstring, 44, 23, bright_white);
- }
- else
- {
- /*
- if the variable "mainstring" contains nothing,
- one of two conditions occured:
- 1. Nothing matched the file specification; or
- 2. The user hit <Escape> in the selection process.
- */
- qcenter_line("Nothing found or selected", 23, bright_white);
- }
- /*
- Pause here to demonstrate result.
- */
- qcenter_line("Hit a key to continue", 24, bright_white);
- anyint = qreadkbd();
- /*
- Clear the screen, initialize the prompt, and start over.
- */
- qclrscr(bright_white);
- filespecification.value[0] = 0;
- qprompt(&filespecification);
- }
- /*
- Upon exiting, restore the invocation screen and
- cursor position.
- */
- qwindow_restore(0, 0, 79, 24, mainscreen);
- qgotoxy(mainx, mainy - 1);
- }
- /*********************** END OF PICKFILE ******************************/
-
- /*
- Misc files follow...
- */
-
- /***********************************************/
- /* This is the PROJECT file for PICKFILE. */
- /* Modify this in the IDE and use the */
- /* CONTROL KW sequence to save. */
- /*
- /*
- d:\qlib.lib
- pickfile.c
- */
- /* End of the PROJECT file for PICKFILE. */
- /***********************************************/
-
-
- /**********************************************************************/
- /* This is the QTYPES.C file for PICKFILE.C. Use this CONTROL KW */
- /* sequence to save this file into your include subdirectory. */
- /* The structures are documented elsewhere, and, in fact, this file */
- /* is optional if the typedefs are included in the 'main' program */
- /********************* begin type declarations ************************/
- /*
- typedef unsigned char qstring[79];
- typedef unsigned char qstring05[5];
- typedef unsigned char qstring20[20];
- typedef unsigned char qstring40[40];
- typedef unsigned char qstring60[60];
- typedef unsigned int qint;
- typedef unsigned long qlong;
- typedef unsigned char qbyte;
- typedef unsigned char qscreen[4096];
- typedef struct
- {
- qstring tag;
- qstring value;
- qint tagx;
- qint tagy;
- qint valx;
- qint valy;
- qint vall;
- qbyte tagf;
- qbyte tagb;
- qbyte valf;
- qbyte valb;
- qint valr;
- qstring valt;
- qstring vale;
- qbyte prmx;
- qstring mhea;
- qstring mtra;
- qstring stid;
- qint poid;
- }
- prompt_record;
-
- typedef struct qmenustructure
- {
- qint screen_x;
- qint screen_y;
- qint menu_width;
- qint foreground;
- qint background;
- int option_count;
- qint prior_choice;
- qstring title;
- qstring option_text[10];
- }
- qmenurecord;
- */
- /********************* end of type declarations ***********************/
- /* */
- /* End of the QTYPES.C file for PICKFILE */
- /**********************************************************************/