#!/usr/bin/env rexx /* apps.rex - Menu-driven application launcher using Object Rexx with ncurses */ signal on halt name ProgramHalt .environment['STOPNOW'] = 0 stdwin = .window~new /* Initialize the standard screen - first call must have zero arguments */ do forever if .environment['STOPNOW'] = 1 then do stdwin~endwin /* Clean up before exiting */ address system 'clear' Say "Exiting Apps Menu." exit 0 end call menu stdwin end exit /**************/ ::routine tmemo dt = .DateTime~new yyyy = dt~year mm = right('0'||dt~month, 2) dd = right('0'||dt~day, 2) hh = right('0'||dt~hours, 2) min = right('0'||dt~minutes, 2) ss = right('0'||dt~seconds, 2) timestamp = 'memo-'||yyyy||'.'||mm||'.'||dd||'-'||hh||'.'||min||'.'||ss /* Use environment variable for HOME directly */ home = SysGetpwnam("gmgauthier", "d") filename = home || '/Documents/memos/' || timestamp || '.md' address system 'touch' filename address system 'tilde' filename return /* Output panel similar to dialog --msgbox */ ::routine output_panel use arg win, title, message win~raw win~noecho message_lines = .array~new do while message \== '' parse var message line '0a'x message message_lines~append(line) end if message_lines~items = 0 then message_lines~append(message) max_width = 0 do i = 1 to message_lines~items if message_lines[i]~length > max_width then max_width = message_lines[i]~length end box_height = message_lines~items + 4 box_width = max_width + 4 /* Center the box on screen */ max_y = win~lines max_x = win~cols start_y = (max_y - box_height) % 2 start_x = (max_x - box_width) % 2 /* Create a subwindow - subsequent .window~new calls need height, width, y, x */ subwin = .window~new(box_height, box_width, start_y, start_x) subwin~box /* Display title */ subwin~attron(win~A_BOLD) subwin~mvaddstr(0, (box_width - title~length) % 2, title) subwin~attroff(win~A_BOLD) /* Display message */ do i = 1 to message_lines~items subwin~mvaddstr(i+1, 2, message_lines[i]) end subwin~mvaddstr(box_height - 2, (box_width - 15) % 2, "Press any key") subwin~refresh key = win~getch win~refresh return /* Function to find position of an item in an array */ ::routine findInArray use arg array, item do i = 1 to array~items if array[i] = item then return i end return 0 /* Not found */ /* Menu function using ncurses */ ::routine menu use arg winm /* Get the HOME environment variable directly */ home = SysGetpwnam("gmgauthier", "d") winm~clear /* Clear the screen */ winm~refresh /* Update the screen */ winm~cbreak winm~noecho winm~keypad(1) /* Enable function keys and arrow keys */ winm~start_color winm~init_pair(1, winm~COLOR_WHITE, winm~COLOR_BLUE) winm~init_pair(2, winm~COLOR_BLACK, winm~COLOR_WHITE) /* Get screen dimensions */ max_y = winm~lines max_x = winm~cols /* Create menu window - using proper 4 arguments for subwindow */ menu_height = 19 menu_width = 40 start_y = (max_y - menu_height) % 2 start_x = (max_x - menu_width) % 2 menuwin = .window~new(menu_height, menu_width, start_y, start_x) menuwin~bkgd(winm~color_pair(1)) /* Set the entire background */ menuwin~box(0,0) /* Standard box characters */ /* Create title */ menuwin~attron(winm~A_BOLD) title = "TUI Command Center" menuwin~mvaddstr(2, (menu_width - title~length) % 2, title) menuwin~attroff(winm~A_BOLD) /* Menu items */ menu_items = .array~of(" w. WordPerfect 8", - " x. Lotus 1-2-3", - " e. Mutt Email", - " c. Calcurse Calendar", - " a. Abook Contacts", - " n. Tilde Notepad", - " t. Tudu Tasks", - " l. Terminal Calculator", - " f. MC File Manager", - " i. Weechat IRC Client", - " p. Castero Podcasts", - " m. VLC Music Player") menu_keys = .array~of("w", "x", "e", "c", "a", "n", "t", "l", "f", "i", "p", "m") /* Display menu items */ selected = 1 call DrawMenu menuwin, menu_items, selected, winm menuwin~mvaddstr(menu_height - 2, 3, "Q to exit") menuwin~refresh /* Menu interaction loop */ key = "" do forever menuwin~refresh key = winm~getch select when key = winm~KEY_UP then do if selected > 1 then selected = selected - 1 call DrawMenu menuwin, menu_items, selected, winm end when key = winm~KEY_DOWN then do if selected < menu_items~items then selected = selected + 1 call DrawMenu menuwin, menu_items, selected, winm end when key = D2C(10) | key = D2C(13) then do /* Enter key - numeric codes only */ menuwin~refresh call ProcessSelection menu_keys[selected], home return end when key = D2C(81) | key = D2C(113) | key = "q" | key = C2D("q") then do menuwin~endwin .environment['STOPNOW'] = 1 RETURN end otherwise do if datatype(key) = 'CHAR' then do key = lower(key) pos = findInArray(menu_keys, key) if pos > 0 then do menuwin~mvaddstr(menu_height - 1, 20, "Letter selection: "||key) menuwin~refresh call SysWait 0.5 winm~endwin call ProcessSelection key, home return end end end end end RETURN /* wait a specified number of seconds */ ::routine SysWait use arg seconds address system 'sleep' seconds return /* process menu selections */ ::routine ProcessSelection use arg key_char, home select when key_char = 'w' then address system 'wp' when key_char = 'x' then address system '123' when key_char = 'e' then address system 'neomutt -F' home'/.config/mutt/muttrc' when key_char = 'c' then address system 'calcurse -c' home'/.local/share/calcurse/calendar -C' home'/.config/calcurse' when key_char = 'a' then address system 'abook --datafile' home'/.local/share/abook/addressbook' when key_char = 'n' then call tmemo when key_char = 't' then address system 'tudu -f' home'/.local/share/tudu/tasks.xml -c' home'/.config/tudu/config' when key_char = 'l' then address system 'tcalc' when key_char = 'f' then address system 'mc' when key_char = 'i' then address system 'weechat' when key_char = 'p' then address system 'castero' when key_char = 'm' then address system 'vlc -Z -L -I ncurses --no-video --recursive expand' home'/Music' otherwise nop end return /* draw menu with selected item highlighted */ ::routine DrawMenu use arg win, items, selected, mainwin do i = 1 to items~items if i = selected then do win~attron(mainwin~COLOR_PAIR(2)) win~attron(mainwin~A_BOLD) win~mvaddstr(i+3, 2, items[i]) win~attroff(mainwin~COLOR_PAIR(2)) win~attroff(mainwin~A_BOLD) end else do win~mvaddstr(i+3, 2, items[i]) end end return /* Handle program termination */ ::ROUTINE ProgramHalt signal off halt exit 0 ::requires "ncurses.cls" ::requires "rxunixsys" LIBRARY