Initial commit
[forms.git] / src / F_Linux_Console_UI.C
blob8e83e4d0b3067b2d6415d0f77554a534634e162b
2 #include <F_Linux_Console_UI.H>
3 #include <errno.h>
5 using namespace F;
6 using namespace ost;
8 // ÏÓÔÁÌÓÑ ÐÏÓÌÅ probe()
9 FILE *vcsa;
11 // TODO: test if console in graphics mode (svgalib/etc.)
14 // ËÏÎÓÏÌØ ÄÏÌÖÎÁ ÉÍÅÔØ ÍÙÛØ É ËÌÁ×Õ - linux-2.6 input subsystem / gpm + kbd
15 // /dev/vcsa :
16 //  - 2 ÂÁÊÔÁ w/h
17 //  - 2 ÂÁÊÔÁ cursor position
18 //  - char / attr array
20 void F_Linux_Console_UI::initial()
22   mouse = new F_Gpm();
23   if (!mouse->good())
24     log("linux_console_ui", CHAT_LEVEL, "Gpm is missing.");
25   input = new F_Linux_Input;
26   if (!input->good()) {
27     log("linux_console_ui", CHAT_LEVEL, "Linux input subsystem is missing.");
28     // try to get working keyboard
29     delete input;
30     input = new F_Linux_Keyboard;
31     if (!input->good()) {
32       log("linux_console_ui", CHAT_LEVEL, "Linux keyboard is missing, giving up.");
33       ::exit(-1);
34     }
35   } else
36       mouse->disable(); // we do not need double mouse events
37   // try to know screen width & height
38   unsigned char b[2];
39   int err;
40   if ((err = read(fileno(vcsa), &b, 2)) != 2) {
41    if (err < 0)
42     log("linux_console_ui", ALERT_LEVEL, "vcsa read error: %s",
43       strerror(errno));
44    else
45     log("linux_console_ui", ALERT_LEVEL, "short read from vcsa (%d) !", err);
46   ::exit(-1);
47  }
48   log("linux_console_ui", CHAT_LEVEL, "w - %d, h - %d", b[1], b[0]);
49   display = new F_Linux_Console_Display(vcsa, b[1], b[0]);
50   // save display area to back_store
51   display->store();
52   display->cursor(0); // cursor off
53   display->sync();
54   init(); // user init
55   ui_started_.post();
58 // ÓÏÂÉÒÁÅÍ ÓÏÂÙÔÉÑ ÏÔ ÕÓÔÒÏÊÓÔ× ÕÐÒÁ×ÌÅÎÉÑ É ÐÅÒÅÄÁÅÍ ÐÏ ÃÅÐÏÞËÅ
60 void F_Linux_Console_UI::run()
62  F_Event_t iev;
63  bool need_flush = false;
65  while (1) {
66    mouse->check_for_events();
67    input->check_for_events();
68    if (mouse->get_event(&iev))
69      event_queue.push_back(iev);
70    if (input->get_event(&iev))
71      event_queue.push_back(iev);
72    while (display->get_event(&iev)) {
73      event_queue.push_back(iev);
74      need_flush = true;
75   }
76    if (need_flush) {
77      iev.dev = F_DISPLAY;
78      iev.type = F_DISPLAY_FLUSH;
79      iev.display.window = 0;
80      event_queue.push_back(iev);
81      need_flush = false;
82   }
83    if (event_queue.size()) {
84      while (event_queue.size()) { // process events
85        iev = event_queue[0];
86        display->handle(iev);
87        event_queue.erase(event_queue.begin());
88    }
89   } else
90          idle();
91  } // while(1)
94 bool F_Linux_Console_UI::exit_confirm(bool from_sighandler)
96  return true;
99 void F_Linux_Console_UI::refresh()
101  // refresh damaged windows
104 void F_Linux_Console_UI::sigcont()
106  debug("console continued");
107  input->sigcont();
108  display->sync();
111 void F_Linux_Console_UI::sigstop()
113  input->sigstop();
114  display->restore();
115  debug("console stopping");
118 void F_Linux_Console_UI::sigwinch()
120  exit_on_unimplemented("SIGWINCH");
123 #include <linux/vt.h>
124 #include <sys/ioctl.h>
126 bool F_Linux_Console_UI::probe()
128  if (strcmp(getenv("TERM"), "linux") && strcmp(getenv("TERM"), "linux"))
129    return false;
130  const char *tty = ttyname(fileno(stdout));
131  int tty_fd = open(tty, O_RDWR);
132  if (tty_fd < 0) { // can't open tty
133   debug("Can't open tty.");
134   return false;
136  vt_mode vtmode;
137  if (ioctl(tty_fd, VT_GETMODE, &vtmode) < 0) {
138    ::close(tty_fd);
139    debug("VT_GETMODE ioctl failed.");
140    return false;
142  if (!strstr(tty, "/dev/vc/")) {
143    debug("Looks like not a tty.");
144    return false;
146  char vcsa_n[32] = "/dev/vcsa";
147  strcat(vcsa_n, rindex(tty, '/') + 1);
148    vcsa = ::fopen(vcsa_n, "r+");
149  if (!vcsa) {
150    debug("Can't open /dev/vcsa.");
151    return false;
153  return true;
156 F_Linux_Console_UI::~F_Linux_Console_UI()
158  shutdown();