::requires 'ooSQLite.cls' ::requires "rxunixsys" LIBRARY ::requires 'ncurses.cls' ::requires 'app/utils.rex' ::class AddressBookUI public ::method init expose win mainMenu db use arg db return ::method initialize expose win mainMenu db win = self~DrawMainPanel(0, .false) /* default colour, no main border */ self~setupMainMenu(win) return ::METHOD DrawMainPanel use arg clrset, with_box win = .window~new() /* The first invocation must be with no arguments */ win~curs_set(0) /* Hide the cursor by default */ win~keypad(1) /* Enable function keys and arrow keys */ win~raw win~noecho win~clear win~cbreak self~SetPanelColor(win, clrset) if with_box = .true then DO win~box(0, 0) /* Draw box with default ACS characters */ win~refresh END return win ::METHOD DrawSubPanel use arg height, width, starty, startx, clrset, title, with_box new_win = .window~new(height, width, starty, startx) new_win~curs_set(0) /* Set the panel color */ self~SetPanelColor(new_win, clrset) /* Display title */ new_win~attron(new_win~A_BOLD) new_win~mvaddstr(starty-(starty-2), (width - title~length) % 2, title) new_win~attroff(new_win~A_BOLD) new_win~refresh if with_box = .true then DO new_win~box(0,0) new_win~refresh END return new_win ::METHOD SetPanelColor use arg panel, clrset panel~start_color() SELECT /* white text on blue background */ when clrset = 1 then panel~init_pair(2, panel~COLOR_WHITE, panel~COLOR_BLUE) /* white text on grey background */ when clrset = 2 then panel~init_pair(3, panel~COLOR_WHITE, panel~COLOR_GREEN) /* yellow text on red background */ when clrset = 3 then panel~init_pair(4, panel~COLOR_YELLOW, panel~COLOR_RED) /* black text on white background */ when clrset = 4 then panel~init_pair(5, panel~COLOR_BLACK, panel~COLOR_WHITE) /* black text on green background */ when clrset = 5 then panel~init_pair(6, panel~COLOR_BLACK, panel~COLOR_GREEN) /* black text on cyan background */ when clrset = 6 then panel~init_pair(7, panel~COLOR_BLACK, panel~COLOR_CYAN) /* Yellow text on blue background */ when clrset = 7 then panel~init_pair(8, panel~COLOR_YELLOW, panel~COLOR_BLUE) /* Cyan text on black background */ when clrset = 8 then panel~init_pair(9, panel~COLOR_CYAN, panel~COLOR_BLACK) /* blacken everything to give the appearance of disappearance */ when clrset = 9 then panel~init_pair(10, panel~COLOR_BLACK, panel~COLOR_BLACK) /* red on black */ when clrset = 10 then panel~init_pair(11, panel~COLOR_RED, panel~COLOR_BLACK) /* yellow on black */ when clrset = 11 then panel~init_pair(12, panel~COLOR_YELLOW, panel~COLOR_BLACK) /* green on black */ when clrset = 12 then panel~init_pair(13, panel~COLOR_GREEN, panel~COLOR_BLACK) /* Default to white text on black background */ OTHERWISE DO clrset=0 panel~init_pair(1, panel~COLOR_WHITE, panel~COLOR_BLACK) END END panel~bkgd(panel~color_pair(clrset+1)) panel~refresh RETURN /*********************** * SETUP MAIN MENU * ***********************/ ::method setupMainMenu expose mainMenu menuwin menu_items menu_keys selected use arg win max_y = win~lines max_x = win~cols menu_height = 16 menu_width = 30 start_y = (max_y - menu_height) % 2 start_x = (max_x - menu_width) % 2 clrset=1 title = "Rexx Address Book" with_box = .true menuwin = self~DrawSubPanel(menu_height, menu_width, start_y, start_x, clrset, title, with_box) menu_items = .array~of("[V]iew Contact", "[A]dd Contact", "[D]elete Contact", "[E]dit Contact", "[S]earch", "[L]ist All", "[Q]uit") menu_keys = .array~of("v", "a", "d", "e", "s", "l", "q") .environment~selected = 1 self~DrawMenu(menuwin, menu_items, .environment~selected, win) menuwin~refresh RETURN /*********************** * DRAW MENU * ***********************/ ::method DrawMenu expose win menu_items menu_keys selected mainwin use arg menuwin, items, selected, mainwin do i = 1 to items~items if i = .environment~selected then do menuwin~attron(menuwin~attron(menuwin~A_REVERSE)) menuwin~attron(menuwin~A_BOLD) menuwin~mvaddstr(i+3, 2, items[i]) menuwin~attroff(menuwin~A_REVERSE) menuwin~attroff(menuwin~A_BOLD) end else do menuwin~mvaddstr(i+3, 2, items[i]) end end menuwin~refresh return /*********************** * DROP WINDOW * ***********************/ ::method dropWindow expose win menuwin use arg window self~SetPanelColor(window, 9) window~erase() window~delwin() win~refresh self~setupMainMenu(win) menuwin~refresh() RETURN /************************************* ADD CONTACT **************************************/ /********************** * Add new contact * **********************/ ::method addContactPanel expose win db menuwin formwin /* Create a form panel */ max_y = win~lines max_x = win~cols form_height = 15 form_width = 60 start_y = (max_y - form_height) % 2 start_x = (max_x - form_width) % 2 formwin = self~DrawSubPanel(form_height, form_width, start_y, start_x, 12, "Add New Contact", .true) /* Create form fields */ formwin~mvaddstr(3, 2, "First Name: ") formwin~mvaddstr(4, 2, "Last Name: ") formwin~mvaddstr(5, 2, "Phone: "); formwin~mvaddstr(5, 42, "Type: "); formwin~mvaddstr(6, 2, "Email: "); formwin~mvaddstr(6, 42, "Type: "); formwin~mvaddstr(7, 2, "Street: ") formwin~mvaddstr(8, 2, "City: "); formwin~mvaddstr(8, 28, "State: "); formwin~mvaddstr(8, 40, "PostCode: ") formwin~mvaddstr(9, 2, "Country: ") formwin~mvaddstr(form_height-2, 2, "[Enter] to save, [Esc] to cancel") formwin~refresh() /* Input fields */ firstName = self~getInputField(formwin, 3, 14, 30, '') if firstName = .nil then do self~dropWindow(formwin) RETURN END lastName = self~getInputField(formwin, 4, 14, 30, '') if lastName = .nil then do self~dropWindow(formwin) RETURN END phone = self~getInputField(formwin, 5, 10, 15, '') if phone = .nil then do self~dropWindow(formwin) RETURN END phone_type = self~getInputField(formwin, 5, 48, 15, '') if phone_type = .nil then do self~dropWindow(formwin) RETURN END email = self~getInputField(formwin, 6, 10, 30, '') if email = .nil then do self~dropWindow(formwin) RETURN END email_type = self~getInputField(formwin, 6, 48, 15, '') if email_type = .nil then do self~dropWindow(formwin) RETURN END street = self~getInputField(formwin, 7, 10, 35, '') if street = .nil then do self~dropWindow(formwin) RETURN END city = self~getInputField(formwin, 8, 10, 15, '') if city = .nil then do self~dropWindow(formwin) RETURN END state = self~getInputField(formwin, 8, 35, 2, '') if state = .nil then do self~dropWindow(formwin) RETURN END postCode = self~getInputField(formwin, 8, 50, 10, '') if postCode = .nil then do self~dropWindow(formwin) RETURN END country = self~getInputField(formwin, 9, 10, 15, '') if country = .nil then do self~dropWindow(formwin) RETURN END if firstname = "" | lastname = "" then do formwin~mvaddstr(8, 2, "First and Last names are required.") formwin~refresh() call SysWait 0.5 END /* don't add contact */ else DO /* Add to database */ contactDict = .Directory~new() contactDict["FIRST_NAME"] = firstName contactDict["LAST_NAME"] = lastName contactDict["PHONE_NUMBER"] = phone contactDict["PHONE_TYPE"] = phone_type contactDict["EMAIL_ADDRESS"] = email contactDict["EMAIL_TYPE"] = email_type contactDict["STREET"] = street contactDict["CITY"] = city contactDict["STATE"] = state contactDict["POSTCODE"] = postCode contactDict["COUNTRY"] = country result = db~addContact(contactDict) /* Display result message */ if result > 0 then do /* should be a result id number */ formwin~mvaddstr(11, 2, "Contact ID ["result"] added successfully!") formwin~refresh() call SysWait 0.5 end else do formwin~mvaddstr(11, 2, "Failed to add contact.") formwin~refresh() call SysWait 0.5 end end /* add contact */ self~dropWindow(formwin) RETURN /************************************* EDIT CONTACT **************************************/ /***************************** * Edit Contact Select Panel * *****************************/ ::METHOD editContactSelectPanel expose win db menuwin ewin /* Create a form panel */ max_y = win~lines max_x = win~cols form_height = 12 form_width = 35 start_y = (max_y - form_height) % 2 start_x = (max_x - form_width) % 2 ewin = self~DrawSubPanel(form_height, form_width, start_y, start_x, 11, "Select A Contact To Edit", .true) ewin~mvaddstr(4, 2, "Contact ID: ") ewin~mvaddstr(form_height-1, 2, "[Enter] to edit, [Esc] to cancel") ewin~refresh() contactId = self~getInputField(ewin, 4, 14, 10, '') if contactId = .nil then do self~dropWindow(ewin) RETURN END result = db~getContact(contactId) if result = .nil then do /* should be a result id number */ ewin~mvaddstr(8, 2, "Contact not found.") ewin~refresh() call SysWait 0.5 self~dropWindow(ewin) RETURN end /* launch a view panel with full contact details */ self~dropWindow(ewin) self~editContactDetailsPanel(contactId) RETURN /************************* * Edit Existing Contact * *************************/ ::METHOD editContactDetailsPanel expose win db menuwin editwin use arg contactId /* Create a form panel */ max_y = win~lines max_x = win~cols form_height = 15 form_width = 60 start_y = (max_y - form_height) % 2 start_x = (max_x - form_width) % 2 editwin = self~DrawSubPanel(form_height, form_width, start_y, start_x, 11, "Edit Contact Details", .true) /* Create form fields */ editwin~mvaddstr(3, 2, "First Name: ") editwin~mvaddstr(4, 2, "Last Name: ") editwin~mvaddstr(5, 2, "Phone: "); editwin~mvaddstr(5, 42, "Type: "); editwin~mvaddstr(6, 2, "Email: "); editwin~mvaddstr(6, 42, "Type: "); editwin~mvaddstr(7, 2, "Street: ") editwin~mvaddstr(8, 2, "City: "); editwin~mvaddstr(8, 28, "State: "); editwin~mvaddstr(8, 40, "PostCode: ") editwin~mvaddstr(9, 2, "Country: ") editwin~mvaddstr(form_height-1, 2, "[Enter] to save, [Esc] to cancel") editwin~refresh() /* Get existing details */ contactDetails = db~getContactDetails(contactId) editwin~mvaddstr(3, 14, contactDetails~first_name); editwin~mvaddstr(4, 14, contactDetails~last_name); editwin~mvaddstr(5, 10, contactDetails~phone_number); editwin~mvaddstr(5, 48, contactDetails~phone_type); editwin~mvaddstr(6, 10, contactDetails~email_address); editwin~mvaddstr(6, 48, contactDetails~email_type); editwin~mvaddstr(7, 10, contactDetails~street); editwin~mvaddstr(8, 10, contactDetails~city); editwin~mvaddstr(8, 35, contactDetails~state); editwin~mvaddstr(8, 50, contactDetails~postal_code); editwin~mvaddstr(9, 10, contactDetails~country); /* Prepopulate the input fields */ firstNameInit = contactDetails~first_name lastNameInit = contactDetails~last_name phoneInit = contactDetails~phone_number phone_typeInit = contactDetails~phone_type emailInit = contactDetails~email_address email_typeInit = contactDetails~email_type streetInit = contactDetails~street cityInit = contactDetails~city stateInit = contactDetails~state postCodeInit = contactDetails~postal_code countryInit = contactDetails~country /* Input fields */ firstName = self~getInputField(editwin, 3, 14, 30, firstNameInit) if firstName = .nil then do self~dropWindow(editwin) RETURN END lastName = self~getInputField(editwin, 4, 14, 30, lastNameInit) if lastName = .nil then do self~dropWindow(editwin) RETURN END phone = self~getInputField(editwin, 5, 10, 15, phoneInit) if phone = .nil then do self~dropWindow(editwin) RETURN END phone_type = self~getInputField(editwin, 5, 48, 15, phone_typeInit) if phone_type = .nil then do self~dropWindow(editwin) RETURN END email = self~getInputField(editwin, 6, 10, 30, emailInit) if email = .nil then do self~dropWindow(editwin) RETURN END email_type = self~getInputField(editwin, 6, 48, 15, email_typeInit) if email_type = .nil then do self~dropWindow(editwin) RETURN END street = self~getInputField(editwin, 7, 10, 35, streetInit) if street = .nil then do self~dropWindow(editwin) RETURN END city = self~getInputField(editwin, 8, 10, 15, cityInit) if city = .nil then do self~dropWindow(editwin) RETURN END state = self~getInputField(editwin, 8, 35, 2, stateInit) if state = .nil then do self~dropWindow(editwin) RETURN END postCode = self~getInputField(editwin, 8, 50, 10, postCodeInit) if postCode = .nil then do self~dropWindow(editwin) RETURN END country = self~getInputField(editwin, 9, 10, 15, countryInit) if country = .nil then do self~dropWindow(editwin) RETURN END /* Add to database */ contactDict = .Directory~new() contactDict["FIRST_NAME"] = firstName contactDict["LAST_NAME"] = lastName contactDict["PHONE_NUMBER"] = phone contactDict["PHONE_TYPE"] = phone_type contactDict["EMAIL_ADDRESS"] = email contactDict["EMAIL_TYPE"] = email_type contactDict["STREET"] = street contactDict["CITY"] = city contactDict["STATE"] = state contactDict["POSTCODE"] = postCode contactDict["COUNTRY"] = country result = db~updateContact(contactId, contactDict) /* Display result message */ if result = 0 then do /* should be a result id number */ editwin~mvaddstr(11, 2, "Contact edited successfully!") editwin~refresh() call SysWait 1.5 end else do editwin~mvaddstr(11, 2, "Failed to edit contact.") editwin~refresh() call SysWait 1.5 end self~dropWindow(editwin) RETURN /************************************* DELETE CONTACT **************************************/ /**************************** * Delete Contact Panel * ****************************/ ::METHOD deleteContactPanel expose win db menuwin delwin /* Create a form panel */ max_y = win~lines max_x = win~cols form_height = 12 form_width = 35 start_y = (max_y - form_height) % 2 start_x = (max_x - form_width) % 2 delwin = self~DrawSubPanel(form_height, form_width, start_y, start_x, 10, "Delete A Contact", .true) delwin~mvaddstr(4, 2, "Contact ID: ") delwin~mvaddstr(form_height-1, 2, "[Enter] to del, [Esc] to cancel") delwin~refresh() contactId = self~getInputField(delwin, 4, 14, 10, '') if contactId = .nil then do self~dropWindow(delwin) RETURN END result = db~deleteContact(contactId) if result = 0 then do /* should be a result id number */ delwin~mvaddstr(8, 2, "Contact deleted successfully!") delwin~refresh() call SysWait 0.5 end else do delwin~mvaddstr(8, 2, "Failed to add contact.") delwin~refresh() call SysWait 0.5 end self~dropWindow(delwin) RETURN /************************************* VIEW CONTACT **************************************/ /******************************** * View Contact Selection Panel * ********************************/ ::METHOD viewContactSelectPanel expose win db menuwin viewselectwin /* Create a form panel */ max_y = win~lines max_x = win~cols form_height = 12 form_width = 35 start_y = (max_y - form_height) % 2 start_x = (max_x - form_width) % 2 viewselectwin = self~DrawSubPanel(form_height, form_width, start_y, start_x, 8, "View A Contact", .true) viewselectwin~mvaddstr(4, 2, "Contact ID: ") viewselectwin~mvaddstr(form_height-1, 2, "[Enter] to sel., [Esc] to cancel") viewselectwin~refresh() contactId = self~getInputField(viewselectwin, 4, 14, 10, '') if contactId = .nil then do self~dropWindow(viewselectwin) RETURN END result = db~getContact(contactId) if result = .nil then do /* should be a result id number */ viewselectwin~mvaddstr(8, 2, "Contact not found.") viewselectwin~refresh() call SysWait 0.5 self~dropWindow(viewselectwin) RETURN end /* launch a view panel with full contact details */ self~dropWindow(viewselectwin) self~viewContactDetailPanel(contactId) RETURN /************************ * View Contact Details * ************************/ ::METHOD viewContactDetailPanel expose win db menuwin detailwin viewselectwin use arg contactID /* Create a form panel */ max_y = win~lines max_x = win~cols form_height = 14 form_width = 40 start_y = (max_y - form_height) % 2 start_x = (max_x - form_width) % 2 detailwin = self~DrawSubPanel(form_height, form_width, start_y, start_x, 1, "View Contact Details", .true) contactDetails = db~getContactDetails(contactId) /* Detail fields */ detailwin~mvaddstr(4, 3, contactDetails~first_name); detailwin~mvaddstr(4, LENGTH(contactDetails~first_name)+1+3, contactDetails~last_name); detailwin~mvaddstr(5, 3, contactDetails~street) detailwin~mvaddstr(6, 3, contactDetails~city); detailwin~mvaddstr(6, LENGTH(contactDetails~city)+4, contactDetails~state); detailwin~mvaddstr(6, LENGTH(contactDetails~city)+LENGTH(contactDetails~state)+5, contactDetails~postal_code); detailwin~mvaddstr(6, LENGTH(contactDetails~city)+LENGTH(contactDetails~state)+LENGTH(contactDetails~postal_code)+6, contactDetails~country) detailwin~mvaddstr(7, 3, contactDetails~email_address) detailwin~mvaddstr(8, 3, contactDetails~phone_number) detailwin~mvaddstr(form_height-1, 2, "[Esc] to cancel") detailwin~refresh() detailwin~getch() self~dropWindow(detailwin) RETURN RETURN /************************************* VIEW ALL CONTACTS **********************************/ /**************************** * List all contacts * ****************************/ ::METHOD listAllContactsPanel expose win db menuwin /* Create a list panel */ max_y = win~lines max_x = win~cols list_height = max_y - 10 list_width = max_x - 18 start_y = (max_y - list_height) % 2 start_x = (max_x - list_width) % 2 listwin = self~DrawSubPanel(list_height, list_width, start_y, start_x, 1, "All Contacts", .true) listwin~scrollok(.true) listwin~Setscrreg(4,18) /* Display column headers */ listwin~attron(listwin~A_BOLD) listwin~mvaddstr(4, 2, "ID") listwin~mvaddstr(4, 7, "First Name") listwin~mvaddstr(4, 21, "Last Name") listwin~mvaddstr(4, 36, "Phone") listwin~mvaddstr(4, 52, "Email") listwin~mvaddstr(5, 2, "---- ---------- ------------ --------------- -------------------------") listwin~attroff(listwin~A_BOLD) contacts = db~getAllContacts() /* Display contacts */ if contacts~items > 0 then do do i = 1 to contacts~items contact = contacts[i] listwin~mvaddstr(i+5, 2, contact['ID']) listwin~mvaddstr(i+5, 7, contact['FIRST_NAME']) listwin~mvaddstr(i+5, 21, contact['LAST_NAME']) listwin~mvaddstr(i+5, 36, contact['PHONE_NUMBER']) listwin~mvaddstr(i+5, 52, contact['EMAIL_ADDRESS']) /* Break if we run out of screen space */ if i > list_height-7 then LEAVE end end else do listwin~mvaddstr(6, 5, "No contacts found.") end listwin~getch() self~dropWindow(listwin) RETURN Return /************************************* SEARCH ALL CONTACTS ***********************************/ /**************************** * Search for contact * ****************************/ ::METHOD searchContactPanel expose win db menuwin menu_items /* Create a search panel */ max_y = win~lines max_x = win~cols search_height = 6 search_width = 50 start_y = (max_y - search_height) % 2 start_x = (max_x - search_width) % 2 searchwin = self~DrawSubPanel(search_height, search_width, start_y, start_x, 7, "Search Contacts (First, Last)", .true) searchwin~mvaddstr(3, 2, "Search term: ") searchwin~refresh() /* Get search term */ term = self~getInputField(searchwin, 3, 15, 30, '') /* If canceled, return to main menu */ if term = .nil then do self~DropWindow(searchwin) return end /* Perform search */ searchwin~erase() searchwin~refresh() /* Display results in a new window */ self~displaySearchResults(term) self~dropWindow(searchwin) return /************************** * DISPLAY SEARCH RESULTS * **************************/ ::METHOD displaySearchResults expose win menuwin db use arg term /* Create a list panel */ max_y = win~lines max_x = win~cols list_height = max_y - 15 list_width = max_x - 18 start_y = (max_y - list_height) % 2 start_x = (max_x - list_width) % 2 searchoutwin = self~DrawSubPanel(list_height, list_width, start_y, start_x, 1, "Search Results", .true) /* searchoutwin~scrollok(.true) searchoutwin~Setscrreg(4,18) */ /* Display column headers */ searchoutwin~attron(searchoutwin~A_BOLD) searchoutwin~mvaddstr(4, 2, "ID") searchoutwin~mvaddstr(4, 7, "First Name") searchoutwin~mvaddstr(4, 21, "Last Name") searchoutwin~mvaddstr(4, 36, "Phone") searchoutwin~mvaddstr(4, 52, "Email") searchoutwin~mvaddstr(5, 2, "---- ---------- ------------ --------------- -------------------------") searchoutwin~attroff(searchoutwin~A_BOLD) contacts = db~searchContacts(term) /* Display contacts */ if contacts~items > 0 then do do i = 1 to contacts~items contact = contacts[i] searchoutwin~mvaddstr(i+5, 2, contact['ID']) searchoutwin~mvaddstr(i+5, 7, contact['FIRST_NAME']) searchoutwin~mvaddstr(i+5, 21, contact['LAST_NAME']) searchoutwin~mvaddstr(i+5, 36, contact['PHONE_NUMBER']) searchoutwin~mvaddstr(i+5, 52, contact['EMAIL_ADDRESS']) /* Break if we run out of screen space */ if i > list_height-7 then LEAVE end end else do searchoutwin~mvaddstr(6, 5, "No contacts found.") end searchoutwin~getch() self~dropWindow(searchoutwin) RETURN /************************************* UTILITIY METHODS **************************************/ /************************ * Get Input From Field * ************************/ ::method getInputField use arg win, y, x, maxlen, bufferContent win~curs_set(1) /* Show cursor */ win~keypad(1) /* Enable function keys and arrow keys */ win~echo() /* Show typed characters */ win~raw if LENGTH(bufferContent) > 0 then DO buffer = bufferContent win~move(y, x + buffer~length) END Else DO buffer = "" win~move(y, x) END blank_line = copies(" ", maxlen) /* String of spaces for clearing the line */ do forever key = win~getch() decimalKey = C2D(key) select when key = D2C(27) then do /* ESC key */ win~curs_set(0) /* Hide cursor */ win~noecho() /* Stop showing typed characters */ return .nil /* Return nil to indicate cancellation */ end when key = D2C(10) | key = D2C(13) then do /* Enter key */ win~curs_set(0) /* Hide cursor */ win~noecho() /* Stop showing typed characters */ return buffer /* Return the entered text */ end when decimalKey = 3290675 then do /* when key = D2C(8) | key = D2C(26) | key = D2C(127) */ /* I don't know why the standard ASCII codes don't work! */ if buffer~length > 0 then do buffer = buffer~left(buffer~length - 1) win~move(y, x) win~addstr(buffer || " ") win~move(y, x + buffer~length) end end otherwise do if buffer~length < maxlen then do ch = key buffer = buffer || ch end end end end return buffer /***************/ /** MAIN LOOP **/ /***************/ ::method mainLoop expose win mainMenu menuwin selected menu_items menu_keys menuwin~refresh running = .true do while running key = win~getch old_selected = .environment~selected select when key = menuwin~KEY_UP then do if .environment~selected > 1 then .environment~selected = .environment~selected - 1 self~DrawMenu(menuwin, menu_items, .environment~selected, win) menuwin~refresh end when key = menuwin~KEY_DOWN then do if .environment~selected < menu_items~items then .environment~selected = .environment~selected + 1 self~DrawMenu(menuwin, menu_items, .environment~selected, win) menuwin~refresh end when key = D2C(81) | key = D2C(113) then do /* Q for quit */ .environment~selected = self~findInArray(menu_keys, key) self~ProcessSelection(menuwin, menu_keys[.environment~selected]) RETURN END when key = D2C(10) | key = D2C(13) then do /* Enter key - numeric codes only */ menuwin~mvaddstr(19 - 1, 18, "Letter selection ["||menu_keys[.environment~selected]||"]") menuwin~refresh self~ProcessSelection(menuwin, menu_keys[.environment~selected]) return end otherwise do key = lower(key) poz = self~findInArray(menu_keys, key) if poz > 0 then do .environment~selected = poz self~DrawMenu(menuwin, menu_items, .environment~selected, win) menuwin~mvaddstr(19 - 1, 18, "Letter selection ["||key||"]") menuwin~refresh self~ProcessSelection(menuwin, key) end /* if pos > 0 */ end /* otherwise */ end /* select */ /* Only redraw if selection changed */ if old_selected \= .environment~selected then do self~DrawMenu(menuwin, menu_items, .environment~selected, win) end end /* do while running */ return /*********************** * PROCESS SELECTION * ***********************/ ::METHOD ProcessSelection expose menu_items menu_keys use arg menuwin, key_char select when key_char = 'a' then do self~addContactPanel() END when key_char = 'd' then do self~deleteContactPanel() END when key_char = 'e' then do self~editContactSelectPanel() END when key_char = 's' then do self~searchContactPanel() END when key_char = 'l' then do self~listAllContactsPanel() END when key_char = 'v' then do self~viewContactSelectPanel() END when key_char = 'q' then do menuwin~mvaddstr(19 - 3, 5, "Exiting the application... ") menuwin~refresh menuwin~endwin .environment['STOPNOW'] = 1 END otherwise nop end return ::METHOD findInArray use arg array, item do i = 1 to array~items if array[i] = item then return i end return 0 /* Not found */ ::METHOD cleanup expose win menuwin /* Clean up ncurses */ menuwin~endwin win~endwin exit 0 return