################################################################## ## Text Based Install Team ## ## Ryan Holden, Mark Godwin, Thea Gabb, Danny Pearson ## ## Colorado School of Mines, 2009 ## ## Sun MicroSystems Inc. ## ################################################################## ----[DEPENDENCIES]------------------------------------------------ - curses and menu library (compiled with -lmenu & -lcurses). - liborchestrator.so.1 must exist in /usr/lib (see pre-build.sh) - Terminal capable of using color. Try exporting "TERM=xterm-color". - data/ directory must exist in same directory as executable. ----[BUILD INSTRUCTIONS]------------------------------------------ 1.) tar -xvf text-installer.tar 2.) cd install/ 3.) tar -xvf lib.tar 4.) make 5.) ./a.out ----[TECHNICAL DETAILS]------------------------------------------- ################################ < SECTION 0 - General Settings > ################################ installation_screen.h: TEXTINFOPATH: This variable specifies the full path to which the data/ directory resides. install.h: _PRETEND_INSTALLATION_: This variable specifies whether the installer is in real or pretend mode. (TRUE = Pretend Mode) ################################## < SECTION 1 - Text based screens > ################################## Our API allows a user to easily create and customize text based screens on the fly. A basic text screen is the building block for all other screens that are supported by this system. The primary methods for creating a text based screen are defined in (text_screen.h/.c), these include: ----> void init_text_screen(char * title, int n_lines, struct TEXT_DESCRIPTOR text[]); [ DESCRIPTION ] This function is used to initialize all data for a basic text screen. [ FUNCTION PARAMETERS] Argument 1 - Set the screen's title in the header window to the specified string value. Argument 2 - Specifies the number of lines to print (index 0 to n_lines of Argument 3 will be printed to the screen) Argument 3 - Defines the specific text that should be printed to the window. (See section 1A.) ----> int show_text_screen(); [ DESCRIPTION ] This function is used to construct the actual screen using curses. ################################################
################################################ The TEXT_DESCRIPTOR struct allows for percise text placement on a screen. The reader module can be used to build an array of TEXT_DESCRIPTOR structs from an external file such as a .txt file using the predefined format which can then be passed to argument 3 of init_text_screen (See section 1C.) struct TEXT_DESCRIPTOR { int x; //Text's beginning x position. int y; //Text's beginning y position. char * line; //String value of the text. }; #######################################
####################################### [ SUPPORTED EXTERNAL FILE FORMAT ] (row,col) this line of text would be placed at row/col as defined above EXAMPLE (data/users.txt): (1,2) Define a root password for the system and user account for yourself. (3,2) System Root Password (5,4) Root Password: (6,4) Confirm Password: (8,2) Create a User Account (10,4) Your real name: (11,4) Username: (12,4) User Password: (13,4) Confirm Password: (15,2) Enter a name for this computer (17,4) Computer Name: [ USING THE READER ] EXAMPLE: // Number of lines available in the returned array of TEXT_DESCRIPTOR structs int n_lines; // An array of TEXT_DESCRIPTOR struct's (can be passed to init_text_screen) struct TEXT_DESCRIPTOR * users_lines = readInNScreen("data/users.txt", &n_lines); /* * MORE CODE */ free_reader(users_lines,n_lines); ############################################# < SECTION 1D - Creating a text based screen > ############################################# [EXAMPLE 1 (internal data)]: int n_lines = 1; struct TEXT_DESCRIPTOR lines[n_lines]; lines[0].x=10; lines[0].y=2; lines[0].line="Test line 1"; init_text_screen("Title Here",n_lines,lines); return show_text_screen(); [EXAMPLE 2 (external data)]: int n_lines; struct TEXT_DESCRIPTOR * lines = readInNScreen("data/filename.txt", &n_lines); init_text_screen("Title Here",n_lines,lines); //IMPORTANT NOTE: Must be called before next line! free_reader(users_lines,n_lines); return show_text_screen(); ############################################ < SECTION 2 - Menu based screens > ############################################ Our API allows for the easy creation and customization of menu screens on the fly. A menu screen is overlayed over a basic text screen by making an internal call to show_text_screen(). This means that you must initialize the basic text screen before using the API to construct a menu screen. The primary methods for creating a menu based screen are defined in (menu_screen.h/.c), these include: PLEASE NOTE: A menu screen cannot be combined with a form screen. (See Section 3) ----> init_menu_screen(bool multi_select, char * marker, char * items[], char * descs[], int rows, int cols, int y, int x); [ DESCRIPTION ] This function is used to initialize all data for a basic menu screen. [ FUNCTION PARAMETERS] Argument 1 - Enable/Disable multi-select mode for menus. Argument 2 - Marker to indicate current selection (Not used in this installer.) Argument 3 - The names of each item that appears in the menu. Argument 4 - The description of each item that appears in the menu. Argument 5 - Number of rows in the menu. Argument 6 - Number of columns in the menu. Argument 7 - Upper left corner Y position Argument 8 - Upper left corner X position IMPORTANT NOTE: INIT_MENU_SCREEN EXPECTS THAT NUMBER OF ITEMS (ARG3) IS EQUAL TO NUMBER OF DESCRIPTIONS (ARG4) ----> int show_menu_screen(); [ DESCRIPTION ] This function is used to construct the actual menu screen using curses. IMPORTANT NOTE: YOU MUST CALL INIT_TEXT_SCREEN BEFORE USING THIS FUNCTION, SHOW_MENU_SCREEN MAKES AN INTERNAL CALL TO SHOW_TEXT_SCREE. THE SHOW_TEXT_SCREEN FUNCTION SHOULD NEVER BE EXPLICITLY CALLED WHEN USING A MENU SCREEN. ############################################# < SECTION 2A - Creating a menu based screen > ############################################# [EXAMPLE]: int n_lines; struct TEXT_DESCRIPTOR * lines = readInNScreen("data/filename.txt", &n_lines); init_text_screen("Title Here",n_lines,lines); free_reader(users_lines,n_lines); char * items[] = { "TEST ITEM1", "TEST ITEM2", (char *)NULL, }; char * descs[] = { "DESCRIPTION 1", "DESCRIPTION 2", (char *)NULL, }; init_menu_screen(FALSE,"-->",items,descs,5,35,14,22); return show_menu_screen(); //IMPORTANT NOTE: This function makes an internal call to show_text_screen(); ############################################ < SECTION 2B - Accessing menu selections > ############################################ Menu selections are captured and stored in the menu_content struct. The selection for a menu in single-select mode is accessible through "menu_content.selection[0];". In multi-select mode, the selections are accessible at index "0 - menu_content.n_items". ############################################ < SECTION 3 - Form based screens > ############################################ Our API allows for the easy creation and customization of form screens on the fly. A form screen is overlayed over a basic text screen by making an internal call to show_text_screen(). This means that you must initialize the basic text screen before using the API to construct a form screen. The primary methods for creating a form based screen are defined in (form_screen.h/.c), these include: PLEASE NOTE: A form screen cannot be combined with a menu screen. (See Section 2) ----> void init_form_screen(int n_fields, struct FORM_DESCRIPTOR field[]); [ DESCRIPTION ] This function is used to initialize all data for a basic form screen. [ FUNCTION PARAMETERS] Argument 1 - Number of fields defined in the form. Argument 2 - An array of FORM_DESCRIPTORS that define each specific form field. (See Section 3A.) ----> int show_form_screen(); IMPORTANT NOTE: YOU MUST CALL INIT_TEXT_SCREEN BEFORE USING THIS FUNCTION, SHOW_FORM_SCREEN MAKES AN INTERNAL CALL TO SHOW_TEXT_SCREEN. THE SHOW_TEXT_SCREEN FUNCTION SHOULD NEVER BE EXPLICITLY CALLED WHEN USING A FORM SCREEN. ################################################
################################################ The FORM_DESCRIPTOR struct allows a user to define a strict set of criteria for a field, along with the percise coordinates of the field within the curses window. struct FORM_DESCRIPTOR { int x; //The upper left corner x coordinate of the field. int y; //The upper left corner y coordinate of the field. int min_length; //Minimum allowed field length. int max_length; //Maximum allowed field length. bool masked; //Masks field values with an asterisk (Ex. Password Fields) char * init_value; //Inital value for the field. }; ############################################# < SECTION 3B - Creating a form based screen > ############################################# [EXAMPLE]: int n_lines; struct TEXT_DESCRIPTOR * lines = readInNScreen("data/filename.txt", &n_lines); init_text_screen("Title Here",n_lines,lines); free_reader(users_lines,n_lines); int n_fields = 1; struct FORM_DESCRIPTOR fields[n_fields]; fields[0].x=10 fields[0].y=10; fields[0].masked=TRUE; //Mask password fields fields[0].min_length=1; fields[0].max_length=15; fields[0].init_value = "TEST FIELD"; init_form_screen(n_fields,fields); return show_form_screen(); //IMPORTANT NOTE: This function makes an internal call to show_text_screen(); #################################### < SECTION 4 - Notification screens > #################################### Our API allows for the easy creation of notification windows that can be used to alert the end-user of any important information or mistakes during the installation sequence. Notification screens are a subwindow to the global main window, and can be used with every screen. The primary methods for creating a notification screen are defined in (notification_screen.h/.c), these include: ----> void init_notification_screen(); [ DESCRIPTION ] This function is used to initialize all data for a notification screen. ----> int show_notification_screen(char * message); [ DESCRIPTION ] This function is used to display a notification screen. [ FUNCTION PARAMETERS] Argument 1 - Specifies the message to be displayed to the end-user. ----> void destroy_notification_screen(); [ DESCRIPTION ] This function is used to destory an active notification screen. ####################################################### < SECTION 6 - Popup dialogs (confirmation screens) > ####################################################### Our API allows for the easy creation of popup dialogs that can be used to provide confirmation dialogs to the end-user. Popup dialogs are a subwindow to the global main window, and can be used with every screen. The primary methods for creating a popup dialog are defined in (popup_dialog.h/.c), these include: ----> int show_popup_dialog(char * title, char * message, char * button1, char * button2); [ DESCRIPTION ] This function is used to display a popup dialog. [ FUNCTION PARAMETERS] Argument 1 - Specifies the confirmation title to be displayed to the end-user. Argument 2 - Specifies the confirmation message to be displayed to the end-user. Argument 3 - Specifies the left button text to be displayed to the end-user. Argument 4 - Specifies the right button text to be displayed to the end-user. ########################################### < SECTION 7 - Key Listeners > ########################################### Each type of screen supported by our API contains their own key listener implementation that provides specific functionality for that screen. Because many of the screen types are built upon eachother in a layered approach, each listener implimentation has the option to be silenced. For example: The show_menu_screen function call, before making an internal call to show_text_screen silences the text screen listener. Each key listener has been implemented as a while loop that waits for character input from the active curses window. Case statements for the captured key codes within the while loop control the specific instructions executed for each key press. As previously noted, this varies between each different type of supported screen. ######################################### < SECTION 8 - Notify Callback Functions > ######################################### Notify callback functions are used extensively to provide communicatation between the curses API and visible screens throughout the installation sequence. Each visual screen in the installer has it's own notify function that is used to handle any specific instructions that must occur during a particular key code event. The global notify callback (global.CallerNotifyFunct) is called from within the key listener implimentation to notify it's parent visual screen of every key code event that occurs in the curses backend. Every time a new visible screen is instantiated, the global notify callback function is reset to the correct notify screen function for the new visible screen. ############################################## < SECTION 9 - Show Screen Callback Functions > ############################################## Each visual screen in the installer has it's own show function, that it used to initialize specific curses API methods that must be called to construct the display. Every visual screen in the installer is assigned a unique identity. Every time a new visible screen is instantiated, the global show screen callback function (global.ptrFunction) is reset to the correct show screen function for the new visible screen. The return value of this callback may corresponds to the identity of a visual screen. This provides control over which visual screen in the installation sequence is next in line to be instantiated.