// text_reader.nvgt - Simple text document reader/editor using NVGT's audio_form // Provides accessible navigation through text documents with optional editing #include "form.nvgt" // Opens a text reader/editor window with string content // Parameters: // content: The text content to display (can be file contents or direct string) // title: Window title (default: "Text Reader") // readonly: If true, text cannot be edited (default: true) // Returns: The modified text if readonly=false and user presses OK, empty string if canceled or readonly=true string text_reader(string content, string title = "Text Reader", bool readonly = true) { audio_form f; f.create_window(title, false, true); // Create the multiline input box // In readonly mode, it's still navigable with arrows/home/end/etc // In edit mode, user can modify text int text_control = f.create_input_box( (readonly ? "Document (read only)" : "Document (editable)"), content, "", // no password mask 0, // no max length readonly, true, // multiline = true true // multiline_enter = true (Ctrl+Enter for newlines) ); int ok_button = -1; int close_button = -1; if (readonly) { // In readonly mode, just have a Close button close_button = f.create_button("&Close", true, true); } else { // In edit mode, have OK and Cancel buttons ok_button = f.create_button("&OK", true); close_button = f.create_button("&Cancel", false, true); } f.focus(text_control); // Monitor loop while (true) { f.monitor(); wait(5); // Check if user pressed OK (edit mode only) if (!readonly && ok_button != -1 && f.is_pressed(ok_button)) { return f.get_text(text_control); } // Check if user pressed Close/Cancel if (close_button != -1 && f.is_pressed(close_button)) { return ""; } // Check for Escape key as alternative close method if (key_pressed(KEY_ESCAPE)) { return ""; } } return ""; } // Opens a text reader/editor window with an array of lines // Parameters: // lines: Array of text lines to display // title: Window title (default: "Text Reader") // readonly: If true, text cannot be edited (default: true) // Returns: The modified text if readonly=false and user presses OK, empty string if canceled or readonly=true string text_reader_lines(string[] lines, string title = "Text Reader", bool readonly = true) { string content = join(lines, "\n"); return text_reader(content, title, readonly); } // Convenience function to read a file and display it in the text reader // Parameters: // file_path: Path to the file to read // title: Window title (default: uses file_path as title) // readonly: If true, text cannot be edited (default: true) // Returns: The modified text if readonly=false and user saves, empty string otherwise string text_reader_file(string file_path, string title = "", bool readonly = true) { file f; if (!f.open(file_path, "rb")) { screen_reader_speak("Failed to open file: " + file_path, true); return ""; } string content = f.read(); f.close(); // Use file_path as title if no custom title provided if (title == "") { title = file_path; } string result = text_reader(content, title, readonly); // If in edit mode and user pressed OK, save the file if (!readonly && result != "") { if (f.open(file_path, "wb")) { f.write(result); f.close(); screen_reader_speak("File saved successfully", true); return result; } else { screen_reader_speak("Failed to save file", true); } } return result; }