Quản lý chế độ Raw và cơ chế điều khiển Terminal trong NCurses

NCurses là một thư viện mạnh mẽ cho phép lập trình viên xây dựng giao diện người dùng dựa trên văn bản (TUI). Để tạo ra các ứng dụng có độ phản hồi cao và kiểm soát chi tiết tương tác người dùng, việc nắm vững các chế độ nhập liệu và cơ chế cập nhật màn hình là điều bắt buộc.

Chế độ Raw: Kiểm soát nhập liệu ở cấp độ thấp

Trong NCurses, chế độ mặc định thường sử dụng bộ đệm dòng, nghĩa là chương trình chỉ nhận được dữ liệu sau khi người dùng nhấn Enter. Để bỏ qua lớp đệm này, chúng ta sử dụng hàm raw(). Khi kích hoạt chế độ này, mọi ký tự từ bàn phím sẽ được chuyển trực tiếp đến ứng dụng ngay lập tức.

Một đặc điểm quan trọng của raw() là nó vô hiệu hóa các tổ hợp phím điều khiển hệ thống như Ctrl+C (ngắt tín hiệu) hoặc Ctrl+Z (tạm dừng). Điều này cho phép ứng dụng chiếm quyền kiểm soát hoàn toàn các phím bấm, nhưng cũng yêu cầu lập trình viên phải tự xử lý các logic thoát chương trình một cách thủ công.


#include <ncurses.h>

int main() {
    initscr();              // Khởi tạo cửa sổ ncurses
    raw();                  // Kích hoạt chế độ thô (raw mode)
    
    printw("Ung dung dang o che do Raw. Ctrl+C se khong hoat dong.\n");
    printw("Nhan mot phim bat ky de thoat...");
    
    getch();                // Doc ky tu ngay lap tuc
    noraw();                // Khoi phuc che do binh thuong
    endwin();               // Dong ncurses
    return 0;
}

Cơ chế làm mới màn hình với refresh()

Hiệu năng của NCurses đến từ việc nó không ghi trực tiếp lên terminal mỗi khi có thay đổi. Thay vào đó, nó duy trì một cấu trúc dữ liệu ảo mô tả trạng thái màn hình. Hàm refresh() đóng vai trò so sánh sự khác biệt giữa màn hình ảo này và những gì đang hiển thị thực tế trên terminal, sau đó chỉ cập nhật những phần đã thay đổi.

Đối với các ứng dụng đa cửa sổ, chúng ta sử dụng wrefresh() để chỉ định cụ thể cửa sổ cần được cập nhật:


WINDOW *app_win = newwin(10, 30, 5, 5);
mvwprintw(app_win, 1, 1, "Noi dung cua so moi");
wrefresh(app_win); // Cap nhat rieng cho cua so app_win

Xử lý nhiễu màn hình bằng redrawwin()

Trong một số trường hợp, nội dung trên màn hình terminal có thể bị hỏng hoặc bị ghi đè bởi các tiến trình bên ngoài (ví dụ: thông báo hệ thống xuất hiện bất ngờ). Khi đó, hàm refresh() có thể không nhận diện được sự sai lệch vì nó tin rằng dữ liệu trong bộ đệm vẫn khớp với terminal.

Hàm redrawwin() được sử dụng để giải quyết vấn đề này. Nó đánh dấu toàn bộ các dòng của một cửa sổ là "bị thay đổi", buộc NCurses phải vẽ lại toàn bộ nội dung từ đầu trong lần gọi refresh tiếp theo.


// Gia su cua so 'main_view' bi nhiễu hien thi
redrawwin(main_view); 
wrefresh(main_view); // Ve lai toan bo cua so de dam bao hien thi dung

Phân biệt giữa raw() và cbreak()

Bên cạnh raw(), NCurses còn cung cấp hàm cbreak(). Cả hai đều loại bỏ bộ đệm dòng, nhưng cbreak() vẫn cho phép terminal xử lý các phím điều khiển như tín hiệu ngắt. Tùy thuộc vào yêu cầu của ứng dụng (cần xử lý phím tắt hệ thống hay muốn tự định nghĩa hoàn toàn), lập trình viên sẽ lựa chọn chế độ phù hợp để tối ưu hóa trải nghiệm người dùng.

Thẻ: ncurses c-programming terminal-control tui-development linux-programming

Đăng vào ngày 21 tháng 6 lúc 01:12