Initial commit
[forms.git] / src / F_Linux_Console_Display.C
blob5b25965a2bb2017dff8bfb7e9f5c7de01b0238f1
2 #include <F_Linux_Console_Display.H>
3 #include <list>
5 using namespace F;
6 using namespace std;
8 // ËÏÐÉÒÕÅÍ Ó ÜËÒÁÎÁ
9 void F_Linux_Console_Display::get_line(coord_t x, coord_t y, dim_t len, F_Text_Symbol *dest)
11   fseek(vcsa_, 2 * (x + y * w()) + 4, SEEK_SET);
12   unsigned char buf[len * 2];
13   if (fread(buf, 2 * len, 1, vcsa_) != 1)
14     trace_bug();
15   for (register dim_t i = 0; i < (2 * len); i += 2)
16     *(dest++) = F_Text_Symbol(buf[i], buf[i + 1] & 0xF, buf[i + 1] >> 4); 
19 // ÒÉÓÕÅÍ ÎÁ ÜËÒÁÎÅ
20 void F_Linux_Console_Display::put_line(coord_t x, coord_t y, dim_t len, F_Text_Symbol *src)
22   fseek(vcsa_, 2 * (x + y * w()) + 4, SEEK_SET);
23   unsigned char buf[len * 2];
24   for (register dim_t i = 0; i < (2 * len); i += 2, src++) {
25     buf[i] = src->ch_;
26     buf[i + 1] = (src->fg() & 0xF) | (src->bg() << 4);
27  }
28   if (fwrite(buf, 2 * len, 1, vcsa_) != 1)
29     trace_bug();
30   fflush(vcsa_);
33 void F_Linux_Console_Display::cursor(coord_t x, coord_t y)
35  fseek(vcsa_, 2, SEEK_SET);
36  unsigned char cur[2] = { x, y };
37  cursor_x = x;
38  cursor_y = y;
39  if (fwrite(&cur, 2, 1, vcsa_) != 1)
40    trace_bug();
43 void F_Linux_Console_Display::cursor(coord_t *x, coord_t *y)
45  fseek(vcsa_, 2, SEEK_SET);
46  unsigned char cur[2];
47  if (fread(&cur, 2, 1, vcsa_) != 1)
48    trace_bug();
49  cursor_x = *x = cur[0];
50  cursor_y = *y = cur[1];
53 #include <sys/ioctl.h>
54 #include <errno.h>
56 // ÏÂÒÁÂÁÔÙ×ÁÅÔ ÓÏÂÙÔÉÑ ÓÐÅÃÉÆÉÞÅÓËÉÅ ÄÌÑ ËÏÎÓÏÌÉ - ÍÙÛØ, ÔÁÍ É ÐÒÏÞÅÅ
58 // ×ÓÅ ÏËÎÁ ÐÏÌÕÞÁÀÔ F_ENTER/F_LEAVE event'Ù
59 // ÏËÎÏ, ËÏÔÏÒÏÅ × ÆÏËÕÓÅ ÐÏÌÕÞÁÅÔ ×ÓÅ ÏÓÔÁÌØÎÙÅ event'Ù
61 bool F_Linux_Console_Display::handle(F_Event_t &ev)
63  F_Event_Type_t t;
64  switch (ev.dev) {
65    case F_DISPLAY:
66      if (ev.type != F_DISPLAY_FLUSH) {
67        debug("display event %d, wid - %d", ev.type, ev.display.window->id());
68 //       sync(ev.display.window);
69     } else {
70         debug("display flush event %d", ev.type);
71         sync();
72     }
73      // store new mouse pointer
74      if ((mouse_x != F_MAX_COORD_T) && (mouse_y != F_MAX_COORD_T))
75        get_line(mouse_x, mouse_y, 1, &symbol_under_mouse_);   
76      draw_mouse_pointer();
77      break;
78    case F_KEYBOARD:
79      debug("key is pressed - 0x%x (%c), modifiers - 0x%x", ev.kbd.key,
80        ((ev.kbd.key > 31) && (ev.kbd.key < 256)) ? ev.kbd.key : '?',
81        ev.kbd.modifiers);
82      // change FOCUS
83      if (ev.kbd.key == F_Tab) {
84        if (ev.kbd.modifiers & F_ALT) { // send FOCUS to next window
85          F_Window *w = 0;
86          if (!window_in_focus()) {
87            if (!windows.size()) // no windows
88              break;
89            else // pick up first window
90              w = windows[0];
91         } else {
92           if (windows.size() == 1) // only one window
93             break;
94           if (window_in_focus()->modal() && window_in_focus()->visible())
95             return window_in_focus()->handle(ev);
96           if (ev.kbd.modifiers & F_SHIFT)
97             w = windows.prev_id(window_in_focus());
98           else
99             w = windows.next_id(window_in_focus());
100         }
101          if (!w)
102            break;
103          if (!w->visible()) // TODO: fix this crap
104            break;
105          take_focus(w);
106          top(w);
107          ev.type = F_FOCUS;
108          w->handle(ev);
109       }
110     } // F_Tab
111      if (window_in_focus())
112        return window_in_focus()->handle(ev);
113      break;
114    case F_POINTER:
115      // ÍÏÖÎÏ ÄÏÂÁ×ÉÔØ ÐÏÌÅ "ÎÁÐÒÁ×ÌÅÎÉÅ" - ËÏÏÒÄÉÎÁÔÙ ÍÏÇÕÔ ÎÅ ÍÅÎÑÔÓÑ, ÎÏ
116      // ÍÙÛØ Ä×ÉÇÁÅÔÓÑ (× ÓÌÕÞÁÅ ÕÔÙËÁÎÉÑ × ËÒÁÊ ÜËÒÁÎÁ for ex.)
117      if (ev.mouse.x < 0)
118        ev.mouse.x = 0;
119      if (ev.mouse.y < 0)
120        ev.mouse.y = 0;
121      if (ev.mouse.x > (w() - 1))
122        ev.mouse.x = w() - 1;
123      if (ev.mouse.y > (h() - 1))
124        ev.mouse.y = h() - 1;
125      mouse_x = ev.mouse.x;
126      mouse_y = ev.mouse.y;
127      mouse_ev_c = ev.mouse.ev_c;
128      t = ev.type;
129      if ((ev.type == F_POINTER_DRAG) || (ev.type == F_POINTER_MOVE)) {
130        if (ev.type == F_POINTER_DRAG)
131          debug("dragging to new coordinates x - %d, y - %d, with buttons - 0x%x",
132          ev.mouse.x, ev.mouse.y, ev.mouse.buttons);
133        else if (ev.type == F_POINTER_MOVE)
134          debug("moved to new coordinates x - %d, y - %d", ev.mouse.x, ev.mouse.y);
135        mouse_ev_t = ev.type;
136        mouse_cursor(1);
137        draw_mouse_pointer();
138        // check for F_ENTER/F_LEAVE events
139        for (unsigned int i = 0; i < windows.size(); i++) {
140          if (windows[i]->visible()) {
141 //           debug("processing wid %d, bm - %d, wid_side - %d", (*w)->id(), window_belowmouse() ?
142 //             window_belowmouse()->id() : 0, (*w)->inside(F_Point(mouse_x, mouse_y)));
143            if ((window_belowmouse() == windows[i]) && !windows[i]->moving() &&
144              !windows[i]->inside(F_Point(mouse_x, mouse_y))) {
145 //               debug("not inside wid - %d", windows[i]->id());
146                ev.type = F_LEAVE;
147                window_belowmouse()->handle(ev);
148                ev.type = t;
149                window_belowmouse(0);
150                continue;
151           }
152            if (windows[i]->inside(F_Point(mouse_x, mouse_y))) {
153              if (window_belowmouse() == windows[i])
154                return window_belowmouse()->handle(ev);
155              else if (window_belowmouse() != windows[i]) {
156                  window_belowmouse(windows[i]);
157 //                 debug("wid %d side - %d", window_belowmouse()->id(), window_belowmouse()->inside(F_Point(mouse_x, mouse_y)));
158                  ev.type = F_ENTER;
159                  return window_belowmouse()->handle(ev);
160            }
161           }
162            // propagate F_POINTER_MOVE event
163            if ((window_belowmouse() == windows[i]) && (window_in_focus() == windows[i]))
164              return window_belowmouse()->handle(ev);
165         } // if (visible())
166        } // for
167          break;
168      } else if ((ev.type == F_POINTER_PRESS) || (ev.type == F_POINTER_RELEASE))
169        debug("button 0x%x is %s", ev.mouse.buttons,
170        (ev.type == F_POINTER_PRESS) ? "pressed" : "released");
171      else if ((ev.type == F_POINTER_WHEEL_INCR) || (ev.type == F_POINTER_WHEEL_DECR))
172        debug("mouse wheel is rolling");
173      if ((ev.type == F_POINTER_PRESS) && (ev.mouse.buttons & F_BUTTON2)) {
174        char c = 3;
175        if (ioctl(fileno(stdin), TIOCLINUX, &c) < 0)
176          debug("TIOCLINUX(3) ioctl error - %s", strerror(errno));
177     }
178      if (window_in_focus() != window_belowmouse()) { // ÓÍÅÎÁ ÆÏËÕÓÁ
179        if (window_in_focus()) {
180          if (window_in_focus()->modal() && window_in_focus()->visible())
181            break;
182          ev.type = F_UNFOCUS;
183          window_in_focus()->handle(ev);
184          ev.type = t;
185          take_focus(0);
186       }
187        if (window_belowmouse()) {
188          take_focus(window_belowmouse());
189          top(window_belowmouse());
190          ev.type = F_FOCUS;
191          window_belowmouse()->handle(ev);
192          ev.type = t;
193       }
194     }
195      if ((mouse_ev_t == F_POINTER_DRAG) && (ev.type == F_POINTER_RELEASE) &&
196        window_in_focus()) {
197          ev.type = mouse_ev_t = F_POINTER_DROP;
198          window_in_focus()->handle(ev);
199      } else {
200        mouse_ev_t = ev.type;
201        if (window_belowmouse())
202          window_belowmouse()->handle(ev);
203     }
204      return true;
205    default:
206      debug("unknown event dev %d, type %d received", ev.dev, ev.type);
207      trace_bug();
208      return false;
210   return F_Text_Display::handle(ev);