fbui | Framebuffer-based graphical environment |
| download: https://git.y1.nz/archives/fbui.tar.gz | |
| README | Files | Log | Refs |
drivers/video/fbui.c
1
2 /*=========================================================================
3 *
4 * Module name: fbui
5 * Module purpose: Provides in-kernel drawing routines to userland,
6 * supporting 8/16/24/32 bit packed pixels.
7 * Module originator: Zachary T Smith (fbui@comcast.net)
8 *
9 *=========================================================================
10 *
11 * FBUI, an in-kernel graphical user interface for applications
12 * Copyright (C) 2003-2005 Zachary T Smith, fbui@comcast.net
13 *
14 * This module is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This module is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this module; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 * (See the file COPYING in the main directory of this archive for
29 * more details.)
30 *
31 *=========================================================================
32 *
33 * Changes:
34 *
35 * Sep 12, 2004, fbui@comcast.net: added fbui_copy_area
36 * Sep 13, 2004, fbui@comcast.net: added fbui_draw_string
37 * Sep 13, 2004, fbui@comcast.net: added sharing of fbui between processes
38 * Sep 14, 2004, fbui@comcast.net: added fbui_switch
39 * Sep 16, 2004, fbui@comcast.net: added fbui_open/close
40 * Sep 16, 2004, fbui@comcast.net: use of KD_GRAPHICS
41 * Sep 16, 2004, fbui@comcast.net: return to KD_TEXT after all closed
42 * Sep 18, 2004, fbui@comcast.net: added event types
43 * Sep 20, 2004, fbui@comcast.net: added window-data semaphore
44 * Sep 21, 2004, fbui@comcast.net: added keyboard focus concept
45 * Sep 22, 2004, fbui@comcast.net: keyboard reading via tty->read_buf
46 * Sep 22, 2004, fbui@comcast.net: keyboard mode set to XLATE
47 * Sep 22, 2004, fbui@comcast.net: simple keyboard behavior achieved
48 * Sep 23, 2004, fbui@comcast.net: added implicit keyfocus when only 1 win
49 * Sep 24, 2004, fbui@comcast.net: fbui_open() now accepts target console#
50 * Sep 25, 2004, fbui@comcast.net: added read_point
51 * Sep 25, 2004, fbui@comcast.net: expanded role of window manager
52 * Sep 25, 2004, fbui@comcast.net: added fbui_put_rgb3
53 * Sep 25, 2004, fbui@comcast.net: coordinates now truly window-relative
54 * Sep 26, 2004, fbui@comcast.net: added per-console winlists
55 * Sep 27, 2004, fbui@comcast.net: keyfocus_stack
56 * Sep 28, 2004, fbui@comcast.net: control ioctl
57 * Sep 29, 2004, fbui@comcast.net: window semaphore; window resize, move
58 * Oct 01, 2004, fbui@comcast.net: all drawing commands now atomic
59 * Oct 01, 2004, fbui@comcast.net: fixed put_rgb bug
60 * Oct 02, 2004, fbui@comcast.net: added fbui_window_info()
61 * Oct 04, 2004, fbui@comcast.net: structural changes
62 * Oct 05, 2004, fbui@comcast.net: keyboard focus working
63 * Oct 05, 2004, fbui@comcast.net: added fbui_winptrs_change()
64 * Oct 05, 2004, fbui@comcast.net: added keyboard accelerators
65 * Oct 06, 2004, fbui@comcast.net: moved code to pixel_from_rgb
66 * Oct 06, 2004, fbui@comcast.net: removed read_point (mmap replaces it)
67 * Oct 06, 2004, fbui@comcast.net: created fb_hline
68 * Oct 06, 2004, fbui@comcast.net: fb_clear now supports info->bgcolor
69 * Oct 10, 2004, fbui@comcast.net: added support for retrieving mouse info
70 * Oct 12, 2004, fbui@comcast.net: resolved bug to do with multiple down's
71 * Oct 12, 2004, fbui@comcast.net: switched to rw_semaphores
72 * Oct 14, 2004, fbui@comcast.net: got fbui_input module working
73 * Oct 14, 2004, fbui@comcast.net: mouse data now available as events
74 * Oct 14, 2004, fbui@comcast.net: key data now available as events
75 * Oct 15, 2004, fbui@comcast.net: put in basic mouse-pointer logic
76 * Oct 16, 2004, fbui@comcast.net: fbui-inp now calls fbui to provide events
77 * Oct 17, 2004, fbui@comcast.net: perfected software mouse-pointer logic
78 * Oct 17, 2004, fbui@comcast.net: restructuring: now only fb_* in fbops.
79 * Oct 17, 2004, fbui@comcast.net: added window-moved event.
80 * Oct 18, 2004, fbui@comcast.net: fixed keyboard accelerators post inp-hand
81 * Oct 20, 2004, fbui@comcast.net: wait-for-event working
82 * Oct 20, 2004, fbui@comcast.net: accelerators are now for chars [32,128)
83 * Oct 21, 2004, fbui@comcast.net: revisions to support panel manager
84 * Oct 22, 2004, fbui@comcast.net: removed keyfocus stack
85 * Oct 23, 2004, fbui@comcast.net: fixed tty: NULL is now used
86 * Oct 25, 2004, fbui@comcast.net: key queue is now per-console
87 * Oct 26, 2004, fbui@comcast.net: putpixels now takes in-kernel data
88 * Oct 26, 2004, fbui@comcast.net: putpixels_rgb takes 0% & 100% transparency
89 * Oct 26, 2004, fbui@comcast.net: added fb_getpixels_rgb
90 * Oct 26, 2004, fbui@comcast.net: mouse pointer now drawn using putpixels
91 * Oct 26, 2004, fbui@comcast.net: conversion to multiple windows per process
92 * Oct 26, 2004, fbui@comcast.net: added cut/paste logic
93 * Nov 11, 2004, fbui@comcast.net: left-bearing for drawn characters!
94 * Nov 18, 2004, fbui@comcast.net: added mouse-motion event
95 * Nov 24, 2004, fbui@comcast.net: added fbui-specific logfile
96 * Nov 29, 2004, fbui@comcast.net: added proper event queues for windows.
97 * Dec 12, 2004, fbui@comcast.net: added ability to open hidden window
98 * Dec 13, 2004, fbui@comcast.net: event queues are now per-process
99 * Dec 13, 2004, fbui@comcast.net: Enter event now generated after switch
100 * Dec 13, 2004, fbui@comcast.net: added fbui_tinyblit
101 * Dec 14, 2004, fbui@comcast.net: Enter/Leave after ptr hide/unhide
102 * Dec 15, 2004, fbui@comcast.net: wait-for-event checks all pid's windows
103 * Dec 16, 2004, fbui@comcast.net: processentry nwindows now correct
104 * Dec 18, 2004, fbui@comcast.net: processentry now has event mask
105 * Dec 21, 2004, fbui@comcast.net: optimization for tinyblit
106 * Dec 28, 2004, fbui@comcast.net: added fbui_clean to remove zombie data
107 * Dec 31, 2004, fbui@comcast.net: added process_exists
108 * Jan 01, 2005, fbui@comcast.net: added PrtSc accelerator
109 * Jan 01, 2005, fbui@comcast.net: added SUBTITLE and SETFONT cmds
110 * Jan 02, 2005, fbui@comcast.net: unhide now performs overlap check
111 * Jan 03, 2005, fbui@comcast.net: added mode24 for slight speedup
112 * Jan 03, 2005, fbui@comcast.net: added pointerfocus and receive_all_motion
113 * Jan 04, 2005, fbui@comcast.net: fixed tinyblit bug
114 * Jan 05, 2005, fbui@comcast.net: separated button events from keys
115 * Jan 13, 2005, fbui@comcast.net: minor tweaks
116 */
117
118
119 /*
120 * Note:
121 *
122 * This code currently works for 8/16/24/32 little endian packed pixels only.
123 * I have some 4-bit VGA code which I may add later.
124 */
125
126 #include <linux/config.h>
127 #include <linux/module.h>
128 #include <linux/string.h>
129 #include <linux/fb.h>
130 #include <asm/types.h>
131 #include <asm/uaccess.h>
132 #include <linux/spinlock.h>
133 #include <linux/tty.h>
134 #include <linux/console.h>
135 #include <linux/kbd_kern.h>
136 #include <linux/vt_kern.h>
137 #include <linux/ctype.h>
138 #include <linux/input.h> /* struct input_event */
139 #include <linux/sem.h>
140 #include <linux/delay.h>
141 #include <linux/pid.h> /* find_pid */
142
143 /* Variables for input_handler */
144 static char fbui_handler_regd = 0;
145 static char got_rel_x = 0;
146 static char got_rel_y = 0;
147 static short incoming_x = 0;
148 static short incoming_y = 0;
149 static char altdown = 0;
150 static char intercepting_accel = 0;
151
152
153
154 #define FBUI_VERSION "0.9.14"
155
156
157
158 /* Mouse-pointer */
159 #define PTRWID 10
160 #define PTRHT 16
161 static unsigned long pointer_saveunder[256]; /* max 16x16 */
162
163
164 static void fbui_enable_pointer (struct fb_info *info);
165 static int fbui_clear (struct fb_info *info, struct fbui_window *win);
166 static int fbui_clear_area (struct fb_info *info, struct fbui_window *win,
167 short x0, short y0, short x1, short y1);
168 static int fbui_fill_area (struct fb_info *info, struct fbui_window *win,
169 short x0, short y0, short x1, short y1, u32 color);
170 static int fbui_draw_point (struct fb_info *info, struct fbui_window *win,
171 short x, short y, u32 color);
172 static int fbui_draw_line (struct fb_info *info, struct fbui_window *win,
173 short x0, short y0, short x1, short y1, u32 color);
174 static int fbui_copy_area (struct fb_info *info, struct fbui_window *win,
175 short xsrc,short ysrc,short w, short h, short xdest,short ydest);
176 static int fbui_draw_vline (struct fb_info *info, struct fbui_window *win,
177 short x, short y0, short y1, u32 color);
178 static int fbui_draw_hline (struct fb_info *info, struct fbui_window *win,
179 short x0, short x1, short y, u32 color);
180 static int fbui_draw_rect (struct fb_info *info, struct fbui_window *win,
181 short x0, short y0, short x1, short y1, u32 color);
182 static int fbui_put_rgb (struct fb_info *info, struct fbui_window *win,
183 short x, short y,short n, unsigned long *src);
184 static int fbui_put_rgb3 (struct fb_info *info, struct fbui_window *win,
185 short x,short y, short n, unsigned char *src);
186 static int fbui_put (struct fb_info *info, struct fbui_window *win,
187 short x,short y, short n, unsigned char *src);
188 static int fbui_copy_area (struct fb_info *info, struct fbui_window *win,
189 short xsrc,short ysrc,short w, short h,
190 short xdest,short ydest);
191 static int fbui_draw_string (struct fb_info *info, struct fbui_window *win,
192 struct fbui_font *font,
193 short x, short y, unsigned char *str, u32 color);
194 static int fbui_tinyblit (struct fb_info *info, struct fbui_window *win,
195 short x, short y, short width, u32 color, u32 bgcolor, u32 bitmap);
196 static struct fbui_processentry *alloc_processentry (struct fb_info *info, int pid, int cons);
197 static void free_processentry (struct fb_info *info, struct fbui_processentry *pre);
198 static struct fbui_window *get_pointer_window (struct fb_info *info);
199 static struct fbui_window *
200 accelerator_test (struct fb_info *info, int cons, unsigned char);
201 static int fbui_clean (struct fb_info *info, int cons);
202 static int fbui_remove_win (struct fb_info *info, short win_id, int);
203
204
205
206
207 static int process_exists (int pid)
208 {
209 struct pid *pidptr;
210 read_lock_irq(&tasklist_lock);
211 pidptr = find_pid (PIDTYPE_PID, pid);
212 read_unlock_irq(&tasklist_lock);
213 return pidptr != NULL;
214 }
215
216
217 #if 0
218 static struct fbui_processentry *lookup_processentry_by_pid (struct fb_info *info,int pid)
219 {
220 int i=0;
221 struct fbui_processentry *pre;
222
223 if (!info)
224 return NULL;
225 /*----------*/
226
227 while (i < FBUI_MAXCONSOLES * FBUI_MAXWINDOWSPERVC) {
228 pre = &info->processentries[i];
229 if (pre->in_use && pid == pre->pid)
230 return pre;
231 i++;
232 }
233 return NULL;
234 }
235 #endif
236
237
238 static void fbui_enqueue_event (struct fb_info *info, struct fbui_window *win,
239 struct fbui_event *ev, int inside_IH)
240 {
241 struct fbui_processentry *pre;
242 unsigned long flags = 0;
243 short head;
244 spinlock_t mylock = SPIN_LOCK_UNLOCKED;
245
246 if (!info || !win || !ev)
247 return;
248 pre = win->processentry;
249 if (!pre) {
250 printk (KERN_INFO "fbui_enqueue_event: no processentry\n");
251 return;
252 }
253 if (!pre->in_use) {
254 printk (KERN_INFO "fbui_enqueue_event: processentry not in use\n");
255 return;
256 }
257 if (pre->events_pending >= FBUI_MAXEVENTSPERPROCESS) {
258 /*printk (KERN_INFO "fbui_enqueue_event: event buffer overflow for process %d, event type %d\n", pre->pid, ev->type);*/
259 return;
260 }
261 /*----------*/
262
263 if (!inside_IH) {
264 down (&pre->queuesem);
265 spin_lock_irqsave(&mylock, flags);
266 }
267
268 ev->id = win->id;
269 ev->pid = win->pid;
270 head = pre->events_head;
271 memcpy (&pre->events[head], ev, sizeof (struct fbui_event));
272 pre->events_head = (head + 1) % FBUI_MAXEVENTSPERPROCESS;
273 pre->events_pending++;
274
275 /*printk(KERN_INFO "enqueue: window %d event %d pending=%d, enqueue at head %d\n", win->id, ev->type, pre->events_pending, head); */
276
277 if (!inside_IH) {
278 spin_unlock_irqrestore(&mylock, flags);
279 up (&pre->queuesem);
280 }
281
282 if (pre->waiting) {
283 pre->waiting = 0;
284 wake_up_interruptible (&pre->waitqueue);
285 }
286 }
287
288
289 static int fbui_dequeue_event (struct fb_info *info, struct fbui_processentry *pre,
290 struct fbui_event *ev)
291 {
292 short tail;
293 unsigned long flags;
294
295 if (!info || !pre || !ev)
296 return 0;
297
298 if (pre->events_pending <= 0) {
299 /* printk(KERN_INFO "fbui_dequeue_event: no events pending\n"); */
300 return 0;
301 }
302 /*----------*/
303
304 /* Remove an event from the event queue for this process,
305 * locking out input_handler which writes to the queue,
306 * and locking out via a semaphore any other process
307 * either reading or writing the queue.
308 */
309 down (&pre->queuesem);
310 spin_lock_irqsave(&pre->queuelock, flags);
311
312 tail = pre->events_tail;
313 memcpy (ev, &pre->events[tail], sizeof (struct fbui_event));
314 /* printk(KERN_INFO "dequeue for window %d: pending %d, tail %d\n", ev->id,pre->events_pending, tail); */
315 pre->events_tail = (tail + 1) % FBUI_MAXEVENTSPERPROCESS;
316 --pre->events_pending;
317
318 spin_unlock_irqrestore (&pre->queuelock, flags);
319 up (&pre->queuesem);
320
321 /* printk (KERN_INFO "dequeue: ev { type %d key %d pid %d id %d } current->pid %d pre { pid %d ix %d}\n",ev->type,ev->key,ev->pid,ev->id,current->pid,pre->pid,pre->index); */
322
323 return 1;
324 }
325
326
327 u32 pixel_from_rgb (struct fb_info *info, u32 value)
328 {
329 u32 r,g,b;
330 if (!info->mode24) {
331 unsigned char tmp = 0xff;
332 b = tmp & value;
333 value >>= 8;
334 g = tmp & value;
335 value >>= 8;
336 r = tmp & value;
337 tmp = 8;
338 r >>= (tmp - info->redsize);
339 g >>= (tmp - info->greensize);
340 b >>= (tmp - info->bluesize);
341 r <<= info->redshift;
342 g <<= info->greenshift;
343 b <<= info->blueshift;
344 return r | g | b;
345 } else {
346 return value & 0xffffff;
347 }
348 }
349
350 u32 pixel_to_rgb (struct fb_info *info, u32 value)
351 {
352 u32 r,g,b;
353 if (!info->mode24) {
354 unsigned char tmp = 8;
355 r = value >> info->redshift;
356 g = value >> info->greenshift;
357 b = value >> info->blueshift;
358 r &= (1 << info->redsize) - 1;
359 g &= (1 << info->bluesize) - 1;
360 b &= (1 << info->greensize) - 1;
361 r <<= (tmp - info->redsize);
362 g <<= (tmp - info->greensize);
363 b <<= (tmp - info->bluesize);
364 r <<= 16;
365 g <<= 8;
366 return r | g | b;
367 } else {
368 return value & 0xffffff;
369 }
370 }
371
372
373 void fb_point (struct fb_info *info, short x, short y, u32 color, char do_invert)
374 {
375 short xres, yres;
376 u32 bytes_per_pixel, offset;
377 unsigned char *ptr;
378
379 if (!info)
380 return;
381 xres = info->var.xres;
382 yres = info->var.yres;
383 if (x < 0 || y < 0 || x >= xres || y >= yres)
384 return;
385 /*----------*/
386
387 bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
388 offset = y * info->fix.line_length + x * bytes_per_pixel;
389 ptr = ((unsigned char*)info->screen_base);
390 if (!ptr)
391 return;
392
393 ptr += offset;
394
395 if (do_invert)
396 {
397 switch (bytes_per_pixel)
398 {
399 case 1: fb_writeb(0xff ^ fb_readb (ptr), ptr); break;
400 case 2: fb_writew(0xffff ^ fb_readw (ptr), ptr); break;
401 case 4: fb_writel(0xffffffff ^ fb_readl (ptr), ptr); break;
402 case 3:
403 fb_writeb(0xff ^ fb_readb (ptr), ptr); ptr++;
404 fb_writeb(0xff ^ fb_readb (ptr), ptr); ptr++;
405 fb_writeb(0xff ^ fb_readb (ptr), ptr);
406 break;
407 }
408 }
409 else
410 {
411 u32 c = pixel_from_rgb (info, color);
412 switch (bytes_per_pixel)
413 {
414 case 1: fb_writeb (c, ptr); break;
415 case 2: fb_writew (c, ptr); break;
416 case 4: fb_writel (c, ptr); break;
417 case 3:
418 fb_writeb (c, ptr); ptr++; c >>= 8;
419 fb_writeb (c, ptr); ptr++; c >>= 8;
420 fb_writeb (c, ptr);
421 break;
422 }
423 }
424 }
425
426
427 void fb_hline (struct fb_info *info, short x0, short x1, short y, u32 color)
428 {
429 u32 pixel, bytes_per_pixel, offset;
430 unsigned char *ptr;
431 int i;
432
433 if (!info)
434 return;
435
436 if (x0 > x1) {
437 short tmp = x0;
438 x0 = x1;
439 x1 = tmp;
440 }
441
442 bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
443 offset = y * info->fix.line_length + x0 * bytes_per_pixel;
444 ptr = ((unsigned char*)info->screen_base);
445 if (!ptr)
446 return;
447 ptr += offset;
448
449 i= x1-x0+1;
450 pixel = pixel_from_rgb (info, color);
451 switch (bytes_per_pixel) {
452 case 4: {
453 register unsigned long* ptr2 = (unsigned long*) ptr;
454 register u32 pix = pixel;
455 while (i) {
456 if (i > 8) {
457 /* useful on older processors */
458 fb_writel (pix, ptr2); ptr2++;
459 fb_writel (pix, ptr2); ptr2++;
460 fb_writel (pix, ptr2); ptr2++;
461 fb_writel (pix, ptr2); ptr2++;
462 fb_writel (pix, ptr2); ptr2++;
463 fb_writel (pix, ptr2); ptr2++;
464 fb_writel (pix, ptr2); ptr2++;
465 fb_writel (pix, ptr2); ptr2++;
466 i -= 8;
467 } else {
468 fb_writel (pix, ptr2); ptr2++;
469 i--;
470 }
471 }
472 break;
473 }
474
475 case 3: {
476 u32 r = 0xff & pixel;
477 u32 g = 0xff & (pixel >> 8);
478 u32 b = 0xff & (pixel >> 16);
479 register u32 long1,long2,long3;
480 register unsigned char third = x0 % 3;
481
482 long1 = r | (g<<8) | (b<<16) | (r<<24);
483 long2 = g | (b<<8) | (r<<16) | (g<<24);
484 long3 = b | (r<<8) | (g<<16) | (b<<24);
485 while (i) {
486 if (!third && i>=4) {
487 unsigned long *ptr2 = (unsigned long*) ptr;
488 while (i>=12) {
489 /* useful on older processors */
490 fb_writel (long1, ptr2); ptr2++;
491 fb_writel (long2, ptr2); ptr2++;
492 fb_writel (long3, ptr2); ptr2++;
493 fb_writel (long1, ptr2); ptr2++;
494 fb_writel (long2, ptr2); ptr2++;
495 fb_writel (long3, ptr2); ptr2++;
496 fb_writel (long1, ptr2); ptr2++;
497 fb_writel (long2, ptr2); ptr2++;
498 fb_writel (long3, ptr2); ptr2++;
499 i -= 12;
500 ptr += 36;
501 }
502 while (i>=4) {
503 fb_writel (long1, ptr2); ptr2++;
504 fb_writel (long2, ptr2); ptr2++;
505 fb_writel (long3, ptr2); ptr2++;
506 i -= 4;
507 ptr += 12;
508 }
509 } else {
510 u32 c = pixel;
511 fb_writeb (c, ptr); ptr++; c >>= 8;
512 fb_writeb (c, ptr); ptr++; c >>= 8;
513 fb_writeb (c, ptr); ptr++;
514 i--;
515 third++;
516 if (third==3) third=0;
517 }
518 }
519 break;
520 }
521
522 case 2: {
523 u32 c32 = (pixel & 0xffff) | (pixel << 16);
524 while (i) {
525 if (i>=2 && !(3 & (u32)ptr)) {
526 if (i>=16) {
527 u32 *ptr2 = (u32*)ptr;
528 /* useful on older processors */
529 fb_writel (c32, ptr2); ptr2++;
530 fb_writel (c32, ptr2); ptr2++;
531 fb_writel (c32, ptr2); ptr2++;
532 fb_writel (c32, ptr2); ptr2++;
533 fb_writel (c32, ptr2); ptr2++;
534 fb_writel (c32, ptr2); ptr2++;
535 fb_writel (c32, ptr2); ptr2++;
536 fb_writel (c32, ptr2); ptr2++;
537 ptr += 32;
538 i -= 16;
539 }
540 if (i>=2) {
541 fb_writel (c32, ptr);
542 ptr += 4;
543 i -= 2;
544 }
545 } else {
546 u32 c = pixel;
547 fb_writeb (c, ptr); ptr++; c >>= 8;
548 fb_writeb (c, ptr); ptr++;
549 i--;
550 }
551 }
552 break;
553 }
554
555 case 1: {
556 u32 c32;
557 pixel &= 0xff;
558 c32 = pixel | (pixel<<8) | (pixel<<16) || (pixel<<24);
559 while (i) {
560 if (!(3 & (u32)ptr)) {
561 if (i>=32) {
562 u32 *ptr2 = (u32 *)ptr;
563 /* useful on older processors */
564 fb_writel (c32, ptr2); ptr2++;
565 fb_writel (c32, ptr2); ptr2++;
566 fb_writel (c32, ptr2); ptr2++;
567 fb_writel (c32, ptr2); ptr2++;
568 fb_writel (c32, ptr2); ptr2++;
569 fb_writel (c32, ptr2); ptr2++;
570 fb_writel (c32, ptr2); ptr2++;
571 fb_writel (c32, ptr2); ptr2++;
572 ptr += 32;
573 i -= 32;
574 }
575 if (i>=4) {
576 fb_writel (c32, ptr);
577 ptr += 4;
578 i -= 4;
579 }
580 } else {
581 fb_writel (pixel, ptr); ptr++;
582 i--;
583 }
584 }
585 break;
586 }
587
588 }/*switch*/
589 }
590
591
592 void fb_vline (struct fb_info *info, short x, short y0, short y1, u32 color)
593 {
594 u32 pixel, linelen, bytes_per_pixel, offset;
595 unsigned char *ptr;
596 short i;
597 short xres,yres;
598
599 if (!info)
600 return;
601 xres = info->var.xres;
602 if (x < 0 || x >= xres)
603 return;
604 if (y0 > y1) {
605 short tmp = y0;
606 y0 = y1;
607 y1 = tmp;
608 }
609 if (y1 < 0)
610 return;
611 yres = info->var.yres;
612 if (y0 >= yres)
613 return;
614 if (y0 < 0)
615 y0 = 0;
616 if (y1 >= yres)
617 y1 = yres-1;
618 /*----------*/
619
620 linelen = info->fix.line_length;
621 bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
622 offset = y0 * linelen + x * bytes_per_pixel;
623 ptr = info->screen_base;
624 ptr += offset;
625
626 i = y1-y0+1;
627 pixel = pixel_from_rgb (info, color);
628
629 switch (bytes_per_pixel) {
630 case 4:
631 while (i--) {
632 fb_writel (pixel, ptr);
633 ptr += linelen;
634 }
635 break;
636
637 case 3:
638 while (i--) {
639 register u32 c = pixel;
640 fb_writeb (c, ptr); ptr++; c >>= 8;
641 fb_writeb (c, ptr); ptr++; c >>= 8;
642 fb_writeb (c, ptr);
643 ptr += linelen;
644 ptr -= 2;
645 }
646 break;
647
648 case 2:
649 while (i--) {
650 fb_writew (pixel, ptr);
651 ptr += linelen;
652 }
653 break;
654
655 case 1:
656 while (i--) {
657 fb_writeb (pixel, ptr);
658 ptr += linelen;
659 }
660 break;
661 }
662
663 return;
664 }
665
666
667 void fb_clear (struct fb_info *info, u32 color_)
668 {
669 u32 color = color_;
670 short y, ylim, xlim;
671
672 if (!info)
673 return;
674 if (info->state != FBINFO_STATE_RUNNING)
675 return;
676 /*----------*/
677
678 y = 0;
679 ylim = info->var.yres;
680 xlim = info->var.xres - 1;
681
682 while (y < ylim)
683 fb_hline (info, 0, xlim, y++, color);
684 }
685
686
687 /* Parameter cons is the VC we are switching to;
688 * info->currcon is the VC we are switching from.
689 */
690 int fbui_switch (struct fb_info *info, int cons)
691 {
692 struct fbui_window *win;
693 struct fbui_event ev;
694 int i,lim;
695
696 if (!info)
697 return 0;
698 if (cons < 0 || cons >= FBUI_MAXCONSOLES)
699 return FBUI_ERR_BADVC;
700 if (!vc_cons_allocated (cons))
701 return 0;
702 /*----------*/
703
704 info->pointer_active = 0;
705 intercepting_accel = 0;
706 altdown = 0;
707
708 /* Clean up the new console
709 */
710 fbui_clean (info, cons);
711
712 /* Send Leave event to whichever window had gotten an Enter.
713 */
714 down_read (&info->winptrSem);
715 win = info->pointer_window [info->currcon];
716 up_read (&info->winptrSem);
717 if (win) {
718 memset (&ev, 0, sizeof (struct fbui_event));
719 ev.type = FBUI_EVENT_LEAVE;
720
721 win->pointer_inside = 0;
722 down_write (&info->winptrSem);
723 info->pointer_window [info->currcon] = NULL;
724 up_write (&info->winptrSem);
725
726 fbui_enqueue_event (info, win, &ev, 0);
727 }
728
729 info->currcon = cons;
730
731 /* This routine is called whenever there's a switch,
732 * not just when we're switching to a graphics console.
733 */
734 if (vt_cons[cons]->vc_mode != KD_GRAPHICS)
735 return 1;
736
737 /* Former value no longer valid */
738 down_write (&info->winptrSem);
739 info->pointer_window [cons] = NULL;
740 up_write (&info->winptrSem);
741
742 fb_clear (info, info->bgcolor[cons]);
743
744 /* Firstly perform the clears
745 */
746 i = cons * FBUI_MAXWINDOWSPERVC;
747 lim = i + FBUI_MAXWINDOWSPERVC;
748 down_read (&info->winptrSem);
749 for (; i < lim; i++) {
750 struct fbui_window *ptr =
751 info->windows [i];
752
753 if (ptr && !ptr->is_wm && !ptr->is_hidden)
754 fbui_clear (info, ptr);
755 }
756 up_read (&info->winptrSem);
757
758 /* Secondly sent the expose events
759 */
760 memset (&ev, 0, sizeof (struct fbui_event));
761 i = cons * FBUI_MAXWINDOWSPERVC;
762 lim = i + FBUI_MAXWINDOWSPERVC;
763 down_read (&info->winptrSem);
764 for (; i < lim; i++) {
765 struct fbui_window *ptr =
766 info->windows [i];
767
768 if (ptr) {
769 ev.type = FBUI_EVENT_EXPOSE;
770
771 ptr->pointer_inside = 0;
772
773 /* No need to expose if hidden */
774 if (!ptr->is_hidden)
775 fbui_enqueue_event (info, ptr, &ev, 0);
776 }
777 }
778 up_read (&info->winptrSem);
779
780 info->pointer_active = 0;
781 fbui_enable_pointer (info);
782
783 /* If the pointer is on top of a window,
784 * send that window an Enter event.
785 */
786 down_read (&info->winptrSem);
787 win = get_pointer_window (info);
788 up_read (&info->winptrSem);
789 if (win) {
790 struct fbui_event ev;
791 memset (&ev, 0, sizeof (struct fbui_event));
792 ev.type = FBUI_EVENT_ENTER;
793 fbui_enqueue_event (info, win, &ev, 0);
794 }
795
796 return 1;
797 }
798
799
800 static int pointer_in_window (struct fb_info *info, struct fbui_window *win, char just_tip)
801 {
802 register short mx,my,mx1,my1;
803 short x0,y0,x1,y1;
804
805 if (!info || !win)
806 return 0;
807 if (!info->pointer_active || info->pointer_hidden)
808 return 0;
809 /*----------*/
810 if (win->console != info->currcon)
811 return 0;
812 if (win->is_hidden)
813 return 0;
814 mx = info->curr_mouse_x;
815 my = info->curr_mouse_y;
816 mx1 = mx + PTRWID - 1;
817 my1 = my + PTRHT - 1;
818 x0 = win->x0;
819 y0 = win->y0;
820 x1 = win->x1;
821 y1 = win->y1;
822 if (!just_tip) {
823 if ((mx >= x0 && mx <= x1) || (mx1 >= x0 && mx1 <= x1))
824 if ((my >= y0 && my <= y1) || (my1 >= y0 && my1 <= y1))
825 return 1;
826 } else {
827 if ((mx >= x0 && mx <= x1) && (my >= y0 && my <= y1))
828 return 1;
829 }
830
831 return 0;
832 }
833
834
835 /* XX -- Currently the mouse pointer is a fixed pattern */
836 static unsigned long ptrpixels [] = {
837 #define T___ 0xff000000
838 #define BORD RGB_BLACK
839 #define X___ RGB_WHITE
840 BORD,BORD,T___,T___,T___,T___,T___,T___,T___,T___,
841 BORD,X___,BORD,T___,T___,T___,T___,T___,T___,T___,
842 BORD,X___,X___,BORD,T___,T___,T___,T___,T___,T___,
843 BORD,X___,X___,X___,BORD,T___,T___,T___,T___,T___,
844 BORD,X___,X___,X___,X___,BORD,T___,T___,T___,T___,
845 BORD,X___,X___,X___,X___,X___,BORD,T___,T___,T___,
846 BORD,X___,X___,X___,X___,X___,X___,BORD,T___,T___,
847 BORD,X___,X___,X___,X___,X___,X___,X___,BORD,T___,
848 BORD,X___,X___,X___,X___,X___,X___,X___,X___,BORD,
849 BORD,X___,X___,X___,X___,X___,BORD,BORD,BORD,BORD,
850 BORD,X___,X___,BORD,X___,X___,BORD,T___,T___,T___,
851 BORD,X___,BORD,T___,BORD,X___,X___,BORD,T___,T___,
852 BORD,BORD,T___,T___,BORD,X___,X___,BORD,T___,T___,
853 T___,T___,T___,T___,T___,BORD,X___,X___,BORD,T___,
854 T___,T___,T___,T___,T___,BORD,X___,X___,BORD,T___,
855 T___,T___,T___,T___,T___,T___,BORD,BORD,T___,T___
856 };
857
858
859 static void fbui_pointer_save (struct fb_info *info)
860 {
861 short j,x,y;
862 unsigned long *p = pointer_saveunder;
863
864 if (!info)
865 return;
866 /*----------*/
867
868 x = info->mouse_x0;
869 y = info->mouse_y0;
870 j = PTRHT;
871 while (j--) {
872 if (info->fbops->fb_getpixels_rgb)
873 info->fbops->fb_getpixels_rgb (info, x, y++, PTRWID, p, 1);
874 p += PTRWID;
875 }
876 }
877
878 static void fbui_pointer_restore (struct fb_info *info)
879 {
880 short j,x,y;
881 unsigned long *p = pointer_saveunder;
882
883 if (!info)
884 return;
885 /*----------*/
886
887 x = info->mouse_x0;
888 y = info->mouse_y0;
889 j = PTRHT;
890 while (j--) {
891 if (info->fbops->fb_putpixels_rgb)
892 info->fbops->fb_putpixels_rgb (info, x, y++, PTRWID, p, 1);
893 p += PTRWID;
894 }
895 }
896
897 static void fbui_pointer_draw (struct fb_info *info)
898 {
899 short j, x, y;
900 unsigned long *p = ptrpixels;
901
902 if (!info)
903 return;
904 /*----------*/
905
906 x = info->mouse_x0;
907 y = info->mouse_y0;
908 j = PTRHT;
909 while (j--) {
910 if (info->fbops->fb_putpixels_rgb)
911 info->fbops->fb_putpixels_rgb (info, x, y++, PTRWID, p, 1);
912 p += PTRWID;
913 }
914 }
915
916 static void fbui_enable_pointer (struct fb_info *info)
917 {
918 if (!info)
919 return;
920 if (info->pointer_active)
921 return;
922 /*----------*/
923
924 fbui_pointer_save (info);
925 fbui_pointer_draw (info);
926
927 info->pointer_active = 1;
928 info->pointer_hidden = 0;
929 }
930
931 #if 0
932 static void fbui_disable_pointer (struct fb_info *info)
933 {
934 if (!info)
935 return;
936 if (!info->pointer_active)
937 return;
938 /*----------*/
939
940 // fbui_pointer_restore (info, win);
941 info->pointer_active = 0;
942 info->pointer_hidden = 0;
943 }
944 #endif
945
946 static void fbui_hide_pointer (struct fb_info *info)
947 {
948 if (!info)
949 return;
950 if (!info->pointer_active)
951 return;
952 if (info->pointer_hidden)
953 return;
954 /*----------*/
955
956 if (!info->have_hardware_pointer) {
957 fbui_pointer_restore (info);
958 }
959 info->pointer_hidden = 1;
960 }
961
962 static void fbui_unhide_pointer (struct fb_info *info)
963 {
964 if (!info)
965 return;
966 if (!info->pointer_active)
967 return;
968 if (!info->pointer_hidden)
969 return;
970 /*----------*/
971
972 if (!info->have_hardware_pointer) {
973 fbui_pointer_save (info);
974 fbui_pointer_draw (info);
975 }
976 info->pointer_hidden = 0;
977 }
978
979
980 static struct fbui_window *get_pointer_window (struct fb_info *info)
981 {
982 struct fbui_window *win=NULL;
983 int i,lim;
984 int cons;
985
986 if (!info)
987 return NULL;
988 /*----------*/
989
990 cons = info->currcon;
991 i = cons * FBUI_MAXWINDOWSPERVC;
992 lim = i + FBUI_MAXWINDOWSPERVC;
993 while (i < lim) {
994 win = info->windows [i];
995 if (win && !win->is_wm && pointer_in_window (info,win,1))
996 break;
997
998 i++;
999 }
1000 if (i >= lim)
1001 return NULL;
1002 return win;
1003 }
1004
1005
1006
1007 static struct fbui_window *fbui_lookup_wm (struct fb_info *info, int cons)
1008 {
1009 struct fbui_window *ptr;
1010 struct rw_semaphore *sem;
1011
1012 if (!info)
1013 return NULL;
1014 if (cons < 0 || cons >= FBUI_MAXCONSOLES)
1015 return NULL;
1016 /*----------*/
1017
1018 sem = &info->winptrSem;
1019 down_read (sem);
1020 ptr = info->window_managers [cons];
1021 up_read (sem);
1022
1023 /* Since the wm is a critical window, let's
1024 * just make sure that its process still exists.
1025 */
1026 if (ptr) {
1027 if (!process_exists (ptr->pid)) {
1028 fbui_remove_win (info, ptr->id, 0);
1029 ptr = NULL;
1030 down_write (sem);
1031 ptr = info->window_managers [cons];
1032 up_write (sem);
1033 }
1034 }
1035
1036 return ptr;
1037 }
1038
1039 void input_handler (u32 param, struct input_event *ev)
1040 {
1041 struct fb_info *info;
1042 int type, code, value;
1043 short xlim, ylim;
1044 int cons;
1045 char event_is_altkey=0;
1046
1047 if (!fbui_handler_regd)
1048 return;
1049
1050 info = (struct fb_info*) param;
1051 if (!info || !ev)
1052 return;
1053
1054 cons = info->currcon;
1055 if (cons < 0 || cons >= FBUI_MAXCONSOLES)
1056 return;
1057 if (vt_cons[cons]->vc_mode != KD_GRAPHICS)
1058 return;
1059 /*----------*/
1060
1061 type = ev->type;
1062 code = ev->code;
1063 value = ev->value;
1064
1065 /* Intercept Alt-keys at all times.
1066 */
1067 if (type == EV_KEY && (code == KEY_LEFTALT || code == KEY_RIGHTALT)) {
1068 altdown = value > 0;
1069 event_is_altkey=1;
1070 }
1071
1072 switch (type) {
1073 case EV_SYN:
1074 return;
1075
1076 case EV_KEY:
1077 if (altdown && !event_is_altkey) {
1078 if (value==1) {
1079 unsigned char ia = 0;
1080 struct fbui_window *match;
1081
1082 switch (code) {
1083 case KEY_1: ia = '1'; break;
1084 case KEY_2: ia = '2'; break;
1085 case KEY_3: ia = '3'; break;
1086 case KEY_4:ia = '4'; break;
1087 case KEY_5: ia = '5'; break;
1088 case KEY_6: ia = '6'; break;
1089 case KEY_7: ia = '7'; break;
1090 case KEY_8:ia = '8'; break;
1091 case KEY_9: ia = '9'; break;
1092 case KEY_0: ia = '0'; break;
1093 case KEY_TAB:ia = '\t'; break;
1094 case KEY_ENTER:ia = '\n'; break;
1095 case KEY_SYSRQ:ia = FBUI_ACCEL_PRTSC; break;
1096 case KEY_HOME:ia = FBUI_ACCEL_HOME; break;
1097 case KEY_END:ia = FBUI_ACCEL_END; break;
1098 case KEY_PAGEUP:ia = FBUI_ACCEL_PGUP; break;
1099 case KEY_PAGEDOWN:ia = FBUI_ACCEL_PGDN; break;
1100 case KEY_A: ia = 'a'; break;
1101 case KEY_B: ia = 'b'; break;
1102 case KEY_C: ia = 'c'; break;
1103 case KEY_D: ia = 'd'; break;
1104 case KEY_E: ia = 'e'; break;
1105 case KEY_F: ia = 'f'; break;
1106 case KEY_G: ia = 'g'; break;
1107 case KEY_H: ia = 'h'; break;
1108 case KEY_I: ia = 'i'; break;
1109 case KEY_J: ia = 'j'; break;
1110 case KEY_K: ia = 'k'; break;
1111 case KEY_L: ia = 'l'; break;
1112 case KEY_M: ia = 'm'; break;
1113 case KEY_N: ia = 'n'; break;
1114 case KEY_O: ia = 'o'; break;
1115 case KEY_P: ia = 'p'; break;
1116 case KEY_Q: ia = 'q'; break;
1117 case KEY_R: ia = 'r'; break;
1118 case KEY_S: ia = 's'; break;
1119 case KEY_T: ia = 't'; break;
1120 case KEY_U: ia = 'u'; break;
1121 case KEY_V: ia = 'v'; break;
1122 case KEY_W: ia = 'w'; break;
1123 case KEY_X: ia = 'x'; break;
1124 case KEY_Y: ia = 'y'; break;
1125 case KEY_Z: ia = 'z'; break;
1126 case KEY_BACKSPACE: ia = '\b'; break;
1127 }
1128
1129 match = accelerator_test (info, info->currcon, ia);
1130 if (match) {
1131 struct fbui_event ev;
1132 memset (&ev, 0, sizeof (struct fbui_event));
1133 ev.type = FBUI_EVENT_ACCEL;
1134 ev.key = ia;
1135 fbui_enqueue_event (info, match, &ev, 1);
1136 }
1137
1138 intercepting_accel = 1;
1139 return;
1140 }
1141 }
1142
1143 if (intercepting_accel && code!=KEY_LEFTALT && code!=KEY_RIGHTALT) {
1144 intercepting_accel = 0;
1145 return;
1146 }
1147
1148 if (!intercepting_accel) {
1149 if (down_read_trylock (&info->winptrSem)) {
1150 if ((code & 0xfff0) == BTN_MOUSE) {
1151 struct fbui_window *win;
1152
1153 win = get_pointer_window (info);
1154 up_read (&info->winptrSem);
1155
1156 if (win) {
1157 struct fbui_event ev;
1158 short tmp=0;
1159
1160 memset (&ev, 0, sizeof (struct fbui_event));
1161 ev.type = FBUI_EVENT_BUTTON;
1162 ev.key = value ? 1 : 0;
1163
1164 switch (code) {
1165 case BTN_LEFT:
1166 tmp = FBUI_BUTTON_LEFT;
1167 break;
1168 case BTN_MIDDLE:
1169 tmp = FBUI_BUTTON_MIDDLE;
1170 break;
1171 case BTN_RIGHT:
1172 tmp = FBUI_BUTTON_RIGHT;
1173 break;
1174 }
1175 ev.key |= tmp;
1176 fbui_enqueue_event (info, win, &ev, 1);
1177 }
1178 }
1179 else
1180 {
1181 struct fbui_window *recipient=info->keyfocus_window [cons];
1182 up_read (&info->winptrSem);
1183
1184 if (recipient) {
1185 struct fbui_event ev;
1186 memset (&ev, 0, sizeof (struct fbui_event));
1187
1188 ev.type = FBUI_EVENT_KEY;
1189 ev.key = (code << 2) | (value & 3);
1190 fbui_enqueue_event (info, recipient, &ev, 1);
1191 }
1192 #if 0
1193 else
1194 printk (KERN_INFO "key %d,%d discarded\n",code,value);
1195 #endif
1196 }
1197 }
1198 else /* XX need workaround */
1199 printk (KERN_INFO "key %d,%d INADVERTENTLY discarded\n",code,value);
1200 }
1201 break;
1202
1203 case EV_REL:
1204 /* We don't receive both x and y at once;
1205 * we must wait for both to arrive.
1206 */
1207 xlim = info->var.xres;
1208 ylim = info->var.yres;
1209 if (!got_rel_x && !got_rel_y) {
1210 incoming_x = info->curr_mouse_x;
1211 incoming_y = info->curr_mouse_y;
1212 }
1213 if (code == REL_X) {
1214 short x = incoming_x;
1215 if (got_rel_x && !got_rel_y)
1216 got_rel_y = 1;
1217 xlim--;
1218 x += value;
1219 if (x<0)
1220 x = 0;
1221 if (x>xlim)
1222 x = xlim;
1223 incoming_x = x;
1224 got_rel_x = 1;
1225 } else
1226 if (code == REL_Y) {
1227 short y = incoming_y;
1228 if (got_rel_y && !got_rel_x)
1229 got_rel_x = 1;
1230 ylim--;
1231 y += value;
1232 if (y<0)
1233 y = 0;
1234 if (y>ylim)
1235 y = ylim;
1236 incoming_y = y;
1237 got_rel_y = 1;
1238 }
1239
1240 if (got_rel_x && got_rel_y) {
1241 int cons = info->currcon;
1242
1243 if (!info->pointer_active || info->pointer_hidden)
1244 return;
1245
1246 /* Even if the new coords cannot affect the
1247 * display due to drawing that is happening,
1248 * we at least need to record them.
1249 */
1250 info->curr_mouse_x = incoming_x;
1251 info->curr_mouse_y = incoming_y;
1252
1253 if (down_read_trylock (&info->winptrSem)) {
1254 struct fbui_window *win = NULL;
1255 struct fbui_window *wm = NULL;
1256 struct fbui_window *pf = NULL;
1257 struct fbui_window *oldwin =
1258 info->pointer_window [cons];
1259 char drawing=0;
1260 struct fbui_processentry *pre = NULL;
1261 struct fbui_processentry *oldpre = NULL;
1262
1263 win = get_pointer_window (info);
1264 if (win) {
1265 drawing = win->drawing;
1266 pre = win->processentry;
1267 }
1268
1269 if (oldwin)
1270 oldpre = oldwin->processentry;
1271
1272 /* generate Leave */
1273 if (oldwin && oldpre && win != oldwin &&
1274 (oldpre->wait_event_mask & FBUI_EVENTMASK_LEAVE)) {
1275 struct fbui_event ev;
1276 memset (&ev, 0, sizeof (struct fbui_event));
1277 ev.type = FBUI_EVENT_LEAVE;
1278 fbui_enqueue_event (info, oldwin, &ev, 1);
1279
1280 oldwin->pointer_inside = 0;
1281 info->pointer_window [cons] = NULL;
1282 }
1283
1284 /* generate Enter */
1285 if (win && pre && !win->pointer_inside &&
1286 (pre->wait_event_mask & FBUI_EVENTMASK_ENTER)) {
1287 struct fbui_event ev;
1288 memset (&ev, 0, sizeof (struct fbui_event));
1289 ev.type = FBUI_EVENT_ENTER;
1290 fbui_enqueue_event (info, win, &ev, 1);
1291
1292 win->pointer_inside = 1;
1293 info->pointer_window [cons] = win;
1294 }
1295
1296 /* If possible draw the pointer */
1297 if (!win || !drawing) {
1298 fbui_pointer_restore (info);
1299 info->mouse_x0 = incoming_x;
1300 info->mouse_y0 = incoming_y;
1301 info->mouse_x1 = info->mouse_x0 + PTRWID - 1;
1302 info->mouse_y1 = info->mouse_y0 + PTRHT - 1;
1303 fbui_pointer_save (info);
1304 fbui_pointer_draw (info);
1305 }
1306
1307 /* generate Motion for appropriate window */
1308 if (win && pre &&
1309 (pre->wait_event_mask & FBUI_EVENTMASK_MOTION))
1310 {
1311 struct fbui_event ev;
1312 memset (&ev, 0, sizeof (struct fbui_event));
1313 ev.type = FBUI_EVENT_MOTION;
1314 ev.x = info->mouse_x0 - win->x0;
1315 ev.y = info->mouse_y0 - win->y0;
1316 fbui_enqueue_event (info, win, &ev, 1);
1317 }
1318
1319 /* generate Motion for the window that has pointer focus*/
1320 pf = info->pointerfocus_window[cons];
1321 if (pf && pf->processentry) {
1322 struct fbui_event ev;
1323 memset (&ev, 0, sizeof (struct fbui_event));
1324 ev.type = FBUI_EVENT_MOTION;
1325 ev.x = info->mouse_x0 - pf->x0;
1326 ev.y = info->mouse_y0 - pf->y0;
1327 fbui_enqueue_event (info, pf, &ev, 1);
1328 }
1329
1330 wm = info->window_managers [cons];
1331 if (wm && wm->receive_all_motion) {
1332 struct fbui_event ev;
1333 memset (&ev, 0, sizeof (struct fbui_event));
1334 ev.type = FBUI_EVENT_MOTION;
1335 ev.x = info->mouse_x0;
1336 ev.y = info->mouse_y0;
1337 fbui_enqueue_event (info, wm, &ev, 1);
1338 }
1339 up_read (&info->winptrSem);
1340 }
1341
1342 got_rel_x = 0;
1343 got_rel_y = 0;
1344 }
1345 break;
1346 }
1347 }
1348
1349
1350 int fbui_init (struct fb_info *info)
1351 {
1352 int i;
1353
1354 if (!info)
1355 return 0;
1356 /*----------*/
1357
1358 #ifdef FBUI_DEBUG
1359 init_MUTEX (&logsem);
1360 #endif
1361
1362 for (i=0; i < FBUI_TOTALACCELS * FBUI_MAXCONSOLES; i++)
1363 info->accelerators [i] = NULL;
1364
1365 for (i=0; i < (FBUI_MAXCONSOLES * FBUI_MAXWINDOWSPERVC); i++) {
1366 info->windows [i] = NULL;
1367 init_MUTEX (&info->windowSems [i]);
1368 }
1369
1370 init_MUTEX (&info->preSem);
1371
1372 for (i=0; i<FBUI_MAXCONSOLES; i++) {
1373 info->force_placement [i] = 0;
1374 info->bgcolor[i] = 0;
1375 info->pointer_window [i] = NULL;
1376 info->keyfocus_window [i] = NULL;
1377 info->pointerfocus_window [i] = NULL;
1378 info->window_managers [i] = NULL;
1379 }
1380
1381 init_rwsem (&info->winptrSem);
1382 info->mouse_x0 = info->var.xres >> 1;
1383 info->mouse_y0 = info->var.yres >> 1;
1384 info->curr_mouse_x = info->mouse_x0;
1385 info->curr_mouse_y = info->mouse_y0;
1386 info->mouse_x1 = info->mouse_x0 + PTRWID - 1;
1387 info->mouse_y1 = info->mouse_y0 + PTRHT - 1;
1388 info->pointer_active = 0;
1389
1390 info->have_hardware_pointer = 0;
1391
1392 init_rwsem (&info->cutpaste_sem);
1393 info->cutpaste_buffer = NULL;
1394
1395 info->redsize = info->var.red.length;
1396 info->greensize = info->var.green.length;
1397 info->bluesize = info->var.blue.length;
1398 info->redshift = info->var.red.offset;
1399 info->greenshift = info->var.green.offset;
1400 info->blueshift = info->var.blue.offset;
1401
1402 info->mode24 = (info->redsize == 8 && info->greensize == 8 &&
1403 info->bluesize == 8 && info->redshift == 16 &&
1404 info->greenshift == 8 && !info->blueshift);
1405
1406 intercepting_accel = 0;
1407 altdown = 0;
1408
1409 printk(KERN_INFO "FrameBuffer UI (%s) by Zack T Smith: operational on fb%d\n", FBUI_VERSION,info->node);
1410
1411 /*
1412 printk(KERN_INFO "sizeof (struct fbui_window)=%d\n", sizeof (struct fbui_window));
1413 printk(KERN_INFO "sizeof (struct fbui_processentry)=%d\n",sizeof(struct fbui_processentry));
1414 printk(KERN_INFO "sizeof (struct fbui_font)=%d\n", sizeof (struct fbui_font));
1415 */
1416
1417 return 1;
1418 }
1419
1420
1421 static inline struct fbui_window *fbui_lookup_win (struct fb_info *info, int win_id)
1422 {
1423 struct fbui_window *win;
1424
1425 if (!info)
1426 return NULL;
1427 if (win_id < 0 || win_id >= (FBUI_MAXWINDOWSPERVC * FBUI_MAXCONSOLES))
1428 return NULL;
1429 /*----------*/
1430
1431 down_read (&info->winptrSem);
1432 win = info->windows [win_id];
1433 up_read (&info->winptrSem);
1434
1435 return win;
1436 }
1437
1438
1439
1440
1441 static int fbui_overlap_check (struct fb_info *info,
1442 short x0, short y0, short x1, short y1,
1443 int cons, struct fbui_window *self)
1444 {
1445 struct fbui_window *ptr;
1446 struct rw_semaphore *sem;
1447 int i,lim;
1448
1449 if (!info)
1450 return -1;
1451 if (cons < 0 || cons >= FBUI_MAXCONSOLES)
1452 return -1;
1453 /*----------*/
1454
1455 sem = &info->winptrSem;
1456 down_read (sem);
1457 i = cons * FBUI_MAXWINDOWSPERVC;
1458 lim = i + FBUI_MAXWINDOWSPERVC;
1459 while (i < lim) {
1460 ptr = info->windows [i];
1461
1462 if (ptr && !ptr->is_hidden && ptr->console == cons && !ptr->is_wm
1463 && ptr != self)
1464 {
1465 short x2, y2, x3, y3;
1466
1467 x2 = ptr->x0;
1468 x3 = ptr->x1;
1469 y2 = ptr->y0;
1470 y3 = ptr->y1;
1471
1472 if ((x2 >= x0 && x2 <= x1) ||
1473 (x3 >= x0 && x3 <= x1)) {
1474 if ((y2 >= y0 && y2 <= y1) ||
1475 (y3 >= y0 && y3 <= y1)) {
1476 up_read (sem);
1477 return 1;
1478 }
1479 }
1480 }
1481 i++;
1482 }
1483 up_read (sem);
1484
1485 return 0;
1486 }
1487
1488
1489 static void restore_vc (struct fb_info *info, int cons)
1490 {
1491 if (cons < 0 || cons >= FBUI_MAXCONSOLES)
1492 return;
1493 /*----------*/
1494
1495 if (cons != info->currcon) {
1496 vc_cons[cons].d->vc_tty = info->ttysave[cons];
1497 vt_cons[cons]->vc_mode = KD_TEXT;
1498 } else {
1499 acquire_console_sem();
1500 vc_cons[cons].d->vc_tty = info->ttysave[cons];
1501 vt_cons[cons]->vc_mode = KD_TEXT;
1502 do_unblank_screen(1);
1503 redraw_screen (cons,0);
1504 release_console_sem();
1505 }
1506 }
1507
1508
1509
1510
1511 static void fbui_winptrs_change (struct fb_info *info, int cons)
1512 {
1513 struct fbui_window *ptr;
1514
1515 if (!info)
1516 return;
1517 if (cons < 0 || cons >= FBUI_MAXCONSOLES)
1518 return;
1519 /*----------*/
1520
1521 ptr = fbui_lookup_wm (info, cons);
1522 if (ptr) {
1523 struct fbui_event ev;
1524 memset (&ev, 0, sizeof (struct fbui_event));
1525 ev.type = FBUI_EVENT_WINCHANGE;
1526 fbui_enqueue_event (info, ptr, &ev, 0);
1527 }
1528 }
1529
1530
1531 static int get_total_windows (struct fb_info *info, int cons)
1532 {
1533 int i,lim,total;
1534
1535 if (!info)
1536 return 0;
1537
1538 total=0;
1539 i = FBUI_MAXWINDOWSPERVC * cons;
1540 lim = i + FBUI_MAXWINDOWSPERVC;
1541 down_read (&info->winptrSem);
1542 for ( ; i < lim; i++) {
1543 if (NULL != info->windows [i])
1544 total++;
1545 }
1546 up_read (&info->winptrSem);
1547 return total;
1548 }
1549
1550 static int fbui_remove_win (struct fb_info *info, short win_id, int force)
1551 {
1552 struct fbui_window *win;
1553 struct fbui_processentry *pre;
1554 struct rw_semaphore *sem;
1555 int cons = 0;
1556 int i, lim;
1557
1558 if (!info)
1559 return FBUI_ERR_NULLPTR;
1560 if (win_id < 0 || win_id >= (FBUI_MAXWINDOWSPERVC * FBUI_MAXCONSOLES))
1561 return FBUI_ERR_BADWIN;
1562 /*----------*/
1563
1564 sem = &info->winptrSem;
1565 down_read (sem);
1566 win = info->windows [win_id];
1567 up_read (sem);
1568
1569 if (!win)
1570 return FBUI_ERR_BADWIN;
1571
1572 /* Verify that we're allowed to remove this window */
1573 if (!force && current->pid != win->pid) {
1574 struct fbui_window *wm = fbui_lookup_wm (info, win->console);
1575 if (!wm)
1576 return FBUI_ERR_BADWIN;
1577
1578 if (current->pid != wm->pid)
1579 return FBUI_ERR_BADWIN;
1580 }
1581
1582 /* XX */
1583 if (win->drawing)
1584 printk(KERN_INFO "DRAWING DURING REMOVEWIN\n");
1585
1586 down_write (sem);
1587 cons = win->console;
1588 if (win == info->windows[win_id])
1589 info->windows [win_id] = NULL;
1590 else {
1591 printk (KERN_INFO "fbui_remove_win: window[win->id] != win\n");
1592 }
1593 if (win->is_wm)
1594 info->window_managers [cons] = NULL;
1595
1596 if (info->pointerfocus_window[cons] == win)
1597 info->pointerfocus_window[cons] = NULL;
1598
1599 /* XX need to search window list for another window that wants
1600 * focus
1601 */
1602 if (info->keyfocus_window[cons] == win)
1603 info->keyfocus_window[cons] = NULL;
1604
1605 if (info->pointer_window [cons] == win)
1606 info->pointer_window[cons] = NULL;
1607
1608 /* Clear any accelerators tied to this window */
1609 i = FBUI_TOTALACCELS * cons;
1610 lim = i + FBUI_TOTALACCELS;
1611 for ( ; i < lim; i++) {
1612 if (info->accelerators[i] == win)
1613 info->accelerators[i] = NULL;
1614 }
1615 up_write (sem);
1616
1617 /* Reduce the window count for this pid */
1618 pre = win->processentry;
1619 if (!pre)
1620 printk (KERN_INFO "fbui_remove_win: window is missing processentry\n");
1621 else {
1622 if (pre->nwindows <= 0)
1623 printk (KERN_INFO "fbui_remove_win: processentry has invalid #windows=%d\n",
1624 pre->nwindows);
1625 else
1626 pre->nwindows--;
1627
1628 if (pre->nwindows <= 0)
1629 free_processentry (info,pre);
1630 else
1631 printk(KERN_INFO "fbui_remove_win: processentry %d has #wins=%d\n",pre->index,
1632 pre->nwindows);
1633 }
1634
1635 /* Clear window to display's bgcolor */
1636 win->bgcolor = info->bgcolor[cons];
1637 if (!win->is_wm)
1638 fbui_clear (info, win);
1639 kfree(win);
1640
1641 /* console empty? if so, restore textmode
1642 */
1643 if (!get_total_windows (info, cons)) {
1644 printk (KERN_INFO "fbui: restoring to text mode on VC %d\n", cons);
1645 restore_vc (info,cons);
1646 } else
1647 if (!force) {
1648 fbui_winptrs_change (info,cons);
1649 }
1650
1651 return FBUI_SUCCESS;
1652 }
1653
1654 static inline struct fbui_window *
1655 fbui_add_win (struct fb_info *info,
1656 int cons,
1657 char autoplacement,
1658 char hidden)
1659 {
1660 struct fbui_window *nu = NULL;
1661 struct fbui_processentry *pre = NULL;
1662 struct semaphore *sem = NULL;
1663 int pid = current->pid;
1664 short win_id;
1665 short i, lim;
1666
1667 if (!info)
1668 return NULL;
1669 if (cons < 0 || cons >= FBUI_MAXCONSOLES)
1670 return NULL;
1671 /*----------*/
1672
1673 /* Find an empty window array entry
1674 */
1675 down_write (&info->winptrSem);
1676 i = cons * FBUI_MAXWINDOWSPERVC;
1677 lim = i + FBUI_MAXWINDOWSPERVC;
1678 win_id = -1;
1679 while (i < lim) {
1680 if (!info->windows [i]) {
1681 nu = kmalloc (sizeof(struct fbui_window), GFP_KERNEL);
1682 if (!nu) {
1683 /* XX kprint ... */
1684 up_write (&info->winptrSem);
1685 return NULL;
1686 }
1687 win_id = i;
1688 info->windows [i] = nu;
1689 break;
1690 }
1691 i++;
1692 }
1693 up_write (&info->winptrSem);
1694
1695 if (i >= lim)
1696 return NULL;
1697
1698 memset ((void*) nu, 0, sizeof(struct fbui_window));
1699
1700 nu->id = win_id;
1701
1702 nu->pid = pid;
1703 nu->console = cons;
1704
1705 nu->mouse_x = -1;
1706 nu->mouse_y = -1;
1707
1708 nu->font_valid = 0;
1709
1710 /* Lookup the appropriate processentry, or allocate one
1711 * if necessary.
1712 */
1713 sem = &info->preSem;
1714 down (sem);
1715 pre = NULL;
1716 i=0;
1717 while (i < FBUI_MAXCONSOLES * FBUI_MAXWINDOWSPERVC) {
1718 pre = &info->processentries[i];
1719 if (pre->in_use && pre->pid == pid) {
1720 nu->processentry = pre;
1721
1722 /* Rule: each process' windows are limited to one VC
1723 */
1724 if (pre->console != cons)
1725 nu->console = cons = pre->console;
1726 break;
1727 }
1728 pre = NULL;
1729 i++;
1730 }
1731 up (sem);
1732
1733 if (!pre) {
1734 pre = alloc_processentry (info, pid, cons);
1735 if (pre)
1736 nu->processentry = pre;
1737 }
1738
1739 if (!pre) {
1740 printk (KERN_INFO "fbui_add_win: cannot even allocate a processentry\n");
1741 info->windows [nu->id] = NULL;
1742 kfree (nu);
1743 return NULL;
1744 }
1745 else
1746 ++pre->nwindows;
1747
1748 nu->is_hidden = hidden;
1749 nu->need_placement = autoplacement;
1750
1751 if (!autoplacement && !hidden) {
1752 struct fbui_event ev;
1753 memset (&ev, 0, sizeof (struct fbui_event));
1754 ev.type = FBUI_EVENT_EXPOSE;
1755 fbui_enqueue_event (info, nu, &ev, 0);
1756 }
1757
1758 fbui_winptrs_change (info,cons);
1759
1760 return nu;
1761 }
1762
1763
1764 static inline void
1765 backup_vc (struct fb_info *info, int cons)
1766 {
1767 struct tty_struct *tty;
1768
1769 if (!info || cons < 0 || cons >= FBUI_MAXCONSOLES)
1770 return;
1771 /*----------*/
1772
1773 acquire_console_sem();
1774 vt_cons[cons]->vc_mode = KD_GRAPHICS;
1775 tty = vc_cons[cons].d->vc_tty;
1776 info->ttysave[cons] = tty;
1777 vc_cons[cons].d->vc_tty = NULL;
1778 info->cursor.enable = 0;
1779 do_blank_screen(1);
1780 release_console_sem();
1781
1782 if (cons == info->currcon) {
1783 fb_clear (info, info->bgcolor[cons]);
1784 info->pointer_active = 0;
1785 fbui_enable_pointer(info);
1786 }
1787 }
1788
1789
1790 static int fbui_set_geometry (struct fb_info *info, struct fbui_window *win,
1791 short x0, short y0, short x1, short y1);
1792
1793 int fbui_open (struct fb_info *info, struct fbui_openparams *p)
1794 {
1795 struct fbui_window *win;
1796 struct fbui_window *wm;
1797 short cons;
1798 char auto_placed=0;
1799 char initially_hidden;
1800 short tmp1, tmp2, max;
1801
1802 /* Extra bulletproofing! */
1803 if (!info || !p)
1804 return FBUI_ERR_NULLPTR;
1805 if (p->need_keys & 0xfe)
1806 return FBUI_ERR_BADPARAM;
1807 if (p->need_motion & 0xfe)
1808 return FBUI_ERR_BADPARAM;
1809 if (p->desired_vc < -1 || p->desired_vc >= FBUI_MAXCONSOLES)
1810 return FBUI_ERR_BADPARAM;
1811 if (p->req_control & 0xfe)
1812 return FBUI_ERR_BADPARAM;
1813 if (p->receive_all_motion & 0xfe)
1814 return FBUI_ERR_BADPARAM;
1815 if (p->doing_autoposition & 0xfe)
1816 return FBUI_ERR_BADPARAM;
1817 if (p->initially_hidden & 0xfe)
1818 return FBUI_ERR_BADPARAM;
1819 if (p->program_type < 0 || p->program_type >= FBUI_PROGTYPE_LAST)
1820 return FBUI_ERR_BADPARAM;
1821 tmp1 = p->x0;
1822 tmp2 = p->x1;
1823 max = info->var.xres;
1824 if (tmp1 < 0)
1825 tmp1 = 0;
1826 if (tmp1 >= max)
1827 tmp1 = max-1;
1828 if (tmp2 < 0)
1829 tmp2 = 0;
1830 if (tmp2 >= max)
1831 tmp2 = max-1;
1832 if (tmp1 > tmp2) {
1833 p->x0 = tmp2;
1834 p->x1 = tmp1;
1835 }
1836 tmp1 = p->y0;
1837 tmp2 = p->y1;
1838 max = info->var.yres;
1839 if (tmp1 < 0)
1840 tmp1 = 0;
1841 if (tmp1 >= max)
1842 tmp1 = max-1;
1843 if (tmp2 < 0)
1844 tmp2 = 0;
1845 if (tmp2 >= max)
1846 tmp2 = max-1;
1847 if (tmp1 > tmp2) {
1848 p->y0 = tmp2;
1849 p->y1 = tmp1;
1850 }
1851 /*----------*/
1852
1853 if (!fbui_handler_regd) {
1854 fbui_input_register_handler (&input_handler, (u32) info);
1855 fbui_handler_regd = 1;
1856 }
1857
1858 initially_hidden = p->initially_hidden;
1859
1860 cons = p->desired_vc;
1861 if (cons >= FBUI_MAXCONSOLES)
1862 return FBUI_ERR_BADVC;
1863 if (!vc_cons_allocated (cons)) {
1864 if (!vc_allocate (cons))
1865 return FBUI_ERR_BADVC;
1866 }
1867 if (cons < 0)
1868 cons = info->currcon;
1869
1870 wm = fbui_lookup_wm (info, cons);
1871
1872 if (p->req_control) {
1873 if (wm)
1874 return FBUI_ERR_HAVEWM;
1875
1876 /* the window-manager process gets the full screen area */
1877 p->x0 = 0;
1878 p->y0 = 0;
1879 p->x1 = info->var.xres - 1;
1880 p->y1 = info->var.yres - 1;
1881 info->bgcolor[cons] = p->bgcolor;
1882 } else {
1883 if (p->program_type)
1884 auto_placed = 1;
1885 if (info->force_placement[cons])
1886 auto_placed = 1;
1887 if (!wm)
1888 auto_placed = 0;
1889 if (wm && !wm->doing_autopos)
1890 auto_placed = 0;
1891
1892 if (!auto_placed && !initially_hidden) {
1893 if (fbui_overlap_check (info, p->x0, p->y0, p->x1, p->y1,
1894 cons, NULL))
1895 return FBUI_ERR_OVERLAP;
1896 }
1897 }
1898
1899 win = fbui_add_win (info, cons, auto_placed,
1900 initially_hidden | auto_placed);
1901 if (!win)
1902 return FBUI_ERR_NOMEM;
1903
1904 /* printk(KERN_INFO "fbui_open: window %s/%d successfully added, location %d %d, %dx%d\n", win->name,win->id,win->x0,win->y0,win->width,win->height); */
1905 win->program_type = p->program_type;
1906 win->need_keys = p->need_keys;
1907 win->need_motion = p->need_motion;
1908 win->receive_all_motion = p->receive_all_motion;
1909 win->need_placement = auto_placed;
1910
1911 strncpy (win->name, p->name, FBUI_NAMELEN);
1912 strncpy (win->subtitle, p->subtitle, FBUI_NAMELEN);
1913
1914 win->max_width = p->max_width;
1915 win->max_height = p->max_height;
1916
1917 if (p->req_control) {
1918 win->is_wm = 1;
1919 if (p->doing_autoposition)
1920 win->doing_autopos = 1;
1921
1922 down_write (&info->winptrSem);
1923 info->window_managers [cons] = win;
1924 up_write (&info->winptrSem);
1925 }
1926
1927 if (vt_cons[cons]->vc_mode != KD_GRAPHICS) {
1928 backup_vc (info, cons);
1929 intercepting_accel = 0;
1930 }
1931
1932 if (!auto_placed && !initially_hidden && !p->req_control)
1933 fbui_set_geometry (info, win, p->x0,p->y0,p->x1,p->y1);
1934 else {
1935 /* Copy the numbers over verbatim since the wm may find them useful*/
1936 win->x0 = p->x0;
1937 win->y0 = p->y0;
1938 win->x1 = p->x1;
1939 win->y1 = p->y1;
1940 win->width = p->x1 - p->x0 + 1;
1941 win->height = p->y1 - p->y0 + 1;
1942 }
1943
1944 win->bgcolor = p->bgcolor;
1945
1946 if (!win->is_wm && !auto_placed && !initially_hidden)
1947 fbui_clear (info, win);
1948
1949 down_write (&info->winptrSem);
1950 {struct fbui_window *p = info->keyfocus_window[cons];
1951 printk(KERN_INFO "fbui_open: cons=%d needkeys=%d keyfocus=%08lx %s %d\n", cons, win->need_keys, (unsigned long)p, p?p->name:"(none)", p?p->id:-1);
1952 }
1953 if (!info->keyfocus_window[cons] && win->need_keys)
1954 info->keyfocus_window[cons] = win;
1955 if (!info->pointerfocus_window[cons] && win->need_motion)
1956 info->pointerfocus_window[cons] = win;
1957 up_write (&info->winptrSem);
1958
1959 return win->id;
1960 }
1961
1962
1963 int fbui_close (struct fb_info *info, short id)
1964 {
1965 struct fbui_window *win;
1966
1967 if (!info)
1968 return FBUI_ERR_NULLPTR;
1969 if (id < 0 || id >= (FBUI_MAXWINDOWSPERVC * FBUI_MAXCONSOLES))
1970 return FBUI_ERR_BADWIN;
1971 /*----------*/
1972
1973 win = fbui_lookup_win (info, id);
1974 if (!win)
1975 return FBUI_ERR_NOTOPEN;
1976
1977 return fbui_remove_win (info, id, 0);
1978 }
1979
1980
1981 /* "redraw" forced by window-manager process
1982 */
1983 int fbui_redraw (struct fb_info *info, struct fbui_window *self,
1984 struct fbui_window *win)
1985 {
1986 struct fbui_event ev;
1987
1988 if (!info || !self || !win)
1989 return 0;
1990 if (!self->is_wm)
1991 return FBUI_ERR_NOTWM;
1992 /*----------*/
1993
1994 fbui_clear (info, win);
1995
1996 memset (&ev, 0, sizeof (struct fbui_event));
1997 ev.type = FBUI_EVENT_EXPOSE;
1998 fbui_enqueue_event (info, win, &ev, 0);
1999
2000 return FBUI_SUCCESS;
2001 }
2002
2003
2004 /* Verify that the process entry array doesn't contain killed processes,
2005 * remove any such entries.
2006 * Verify that the windows on the system are for processes that exist.
2007 * remove any such windows.
2008 */
2009 static int fbui_clean (struct fb_info *info, int cons)
2010 {
2011 struct semaphore *sem;
2012 struct rw_semaphore *rwsem;
2013 int i, lim;
2014
2015 if (!fbui_handler_regd)
2016 return FBUI_SUCCESS;
2017 if (!info)
2018 return FBUI_ERR_NULLPTR;
2019 if (cons < 0 || cons >= FBUI_MAXCONSOLES)
2020 return FBUI_ERR_BADPARAM;
2021 /*----------*/
2022
2023 /* Process entry check */
2024 sem = &info->preSem;
2025 down(sem);
2026 i=0;
2027 while (i < FBUI_MAXCONSOLES * FBUI_MAXWINDOWSPERVC) {
2028 struct fbui_processentry *pre = &info->processentries[i];
2029
2030 if (pre->in_use) {
2031 if (!process_exists (pre->pid)) {
2032 printk (KERN_INFO "fbui_clean: removing zombie process entry %d\n", i);
2033 pre->in_use = 0;
2034 pre->waiting = 0;
2035 pre->pid = 0;
2036 pre->nwindows = 0;
2037 }
2038 }
2039 i++;
2040 }
2041 up(sem);
2042
2043 /* Window struct check */
2044 rwsem = &info->winptrSem;
2045 i = cons * FBUI_MAXWINDOWSPERVC;
2046 lim = i + FBUI_MAXWINDOWSPERVC;
2047 while (i < lim) {
2048 struct fbui_window *win;
2049
2050 down_read (rwsem);
2051 win = info->windows [i];
2052 up_read (rwsem);
2053
2054 if (win) {
2055 if (!process_exists (win->pid)) {
2056 short id = win->id;
2057
2058 if (id == i) {
2059 printk (KERN_INFO "fbui_clean: removing zombie window %d\n", i);
2060 fbui_remove_win (info, i, 1);
2061 } else
2062 printk (KERN_INFO "fbui_clean: invalid window entry for window %d\n", id);
2063 }
2064 }
2065 i++;
2066 }
2067
2068 return FBUI_SUCCESS;
2069 }
2070
2071
2072 /* Return the process ids of all windows for this console
2073 * npids initially tells the maximum we can return.
2074 */
2075 int fbui_window_info (struct fb_info *info, int cons,
2076 /*user*/ struct fbui_wininfo *ary, int ninfo)
2077 {
2078 struct fbui_window *win;
2079 int i, j, lim;
2080
2081 if (!info || !ary || ninfo <= 0)
2082 return FBUI_ERR_NULLPTR;
2083 if (!access_ok (VERIFY_WRITE, (void*)ary,
2084 ninfo * sizeof(struct fbui_wininfo)))
2085 return FBUI_ERR_BADADDR;
2086 if (cons < 0 || cons >= FBUI_MAXCONSOLES)
2087 return FBUI_ERR_BADPARAM;
2088 /*----------*/
2089
2090 /* Clean up the console */
2091 fbui_clean (info, cons);
2092
2093 /*printk(KERN_INFO "fbui_window_info: cons=%d\n", cons);*/
2094 i = 0;
2095 j = cons * FBUI_MAXWINDOWSPERVC;
2096 lim = j + FBUI_MAXWINDOWSPERVC;
2097 down_read (&info->winptrSem);
2098 while (i < ninfo && j < lim) {
2099 win = info->windows [j];
2100 if (win && !win->is_wm) {
2101 struct fbui_wininfo wi;
2102 char *ptr;
2103 #if 0
2104 printk(KERN_INFO " : window %d/%s ", win->id,win->name);
2105 printk(KERN_INFO " : %s %s type=%d\n", win->is_hidden?"hidden":"",win->need_keys?"need_keys","",win->program_type);
2106 #endif
2107 wi.id = win->id;
2108 wi.pid = win->pid;
2109 wi.program_type = win->program_type;
2110 wi.hidden = win->is_hidden;
2111 wi.need_placement = win->need_placement;
2112 wi.need_keys = win->need_keys;
2113 wi.need_motion = win->need_motion;
2114 wi.x = win->x0;
2115 wi.y = win->y0;
2116 wi.width = win->width;
2117 wi.height = win->height;
2118 wi.max_width = win->max_width;
2119 wi.max_height = win->max_height;
2120 /* printk(KERN_INFO "inside wininfo: x %d y %d w %d h %d\n",(int)wi.x,(int)wi.y,(int)wi.width, (int)wi.height); */
2121 strcpy (wi.name, win->name);
2122 strcpy (wi.subtitle, win->subtitle);
2123
2124 ptr = (char*) &ary[i];
2125
2126 if (copy_to_user (ptr, &wi, sizeof(struct fbui_wininfo))) {
2127 up_read (&info->winptrSem);
2128 return FBUI_ERR_BADADDR;
2129 }
2130
2131 i++;
2132 }
2133 j++;
2134 }
2135 up_read (&info->winptrSem);
2136
2137 return i;
2138 }
2139
2140
2141 /* Delete the window belonging to a given process,
2142 * as identified by its process id.
2143 */
2144 int fbui_delete (struct fb_info *info, struct fbui_window *self,
2145 struct fbui_window *win)
2146 {
2147 int rv;
2148 short id;
2149 struct semaphore *sem;
2150
2151 if (!info || !self || !win)
2152 return 0;
2153 if (!self->is_wm)
2154 return FBUI_ERR_NOTWM;
2155 /*----------*/
2156
2157 id = win->id;
2158 sem = &info->windowSems [id];
2159 down (sem);
2160 rv = fbui_remove_win (info, win->id, 0);
2161 up (sem);
2162 return FBUI_SUCCESS;
2163 }
2164
2165
2166
2167 static struct fbui_window *
2168 accelerator_test (struct fb_info *info, int cons, unsigned char ch)
2169 {
2170 if (!info)
2171 return NULL;
2172 if (ch >= FBUI_TOTALACCELS)
2173 return NULL;
2174 if (cons < 0 || cons >= FBUI_MAXCONSOLES)
2175 return NULL;
2176 /*----------*/
2177
2178 return info->accelerators [ch + FBUI_TOTALACCELS*cons];
2179 }
2180
2181
2182 /* op==1 to register an accelerator (Alt-key sequence), 0 to unregister
2183 */
2184 static int fbui_accel (struct fb_info *info, struct fbui_window *win,
2185 short which, short op)
2186 {
2187 int ix;
2188
2189 if (!info || !win)
2190 return FBUI_ERR_NULLPTR;
2191 if (which < 0 || which > 127 || op < 0 || op > 1)
2192 return FBUI_ERR_BADPARAM;
2193 /*----------*/
2194
2195 ix = which + FBUI_TOTALACCELS * win->console;
2196
2197 if (op==1) {
2198 if (accelerator_test (info, win->console, which))
2199 return FBUI_ERR_ACCELBUSY;
2200
2201 info->accelerators[ix] = win;
2202 } else
2203 info->accelerators[ix] = NULL;
2204
2205 return FBUI_SUCCESS;
2206 }
2207
2208
2209 /* Does not generate WinChange event */
2210 int fbui_move_resize (struct fb_info *info, struct fbui_window *self,
2211 struct fbui_window *win,
2212 short x, short y, short width, short height)
2213 {
2214 char result=FBUI_SUCCESS;
2215 short x1, y1;
2216 struct semaphore *sem;
2217
2218 if (!info || !self || !win)
2219 return 0;
2220 if (!self->is_wm)
2221 return FBUI_ERR_NOTWM;
2222 /*----------*/
2223
2224 x1 = x+width-1;
2225 y1 = y+height-1;
2226
2227 sem = &info->windowSems [win->id];
2228 down (sem);
2229
2230 /* If the window is not hidden, verify no overlap.
2231 * If hidden, we don't care.
2232 */
2233 if (!win->is_hidden)
2234 result = fbui_overlap_check (info, x, y, x1, y1, self->console, win);
2235
2236 if (!result) {
2237 result = fbui_set_geometry (info, win, x, y, x1, y1);
2238
2239 if (!result) {
2240 struct fbui_event ev;
2241
2242 fbui_clear (info, win);
2243
2244 memset (&ev, 0, sizeof (struct fbui_event));
2245 ev.type = FBUI_EVENT_MOVE_RESIZE;
2246 ev.x = x;
2247 ev.y = y;
2248 ev.width = x1-x+1;
2249 ev.height = y1-y+1;
2250 fbui_enqueue_event (info, win, &ev, 0);
2251
2252 /*ev.type = FBUI_EVENT_EXPOSE;
2253 fbui_enqueue_event (info, win, &ev, 0);
2254 */
2255
2256 win->need_placement = 0;
2257 }
2258 else
2259 printk (KERN_INFO "set geometry failed -- %s\n",win->name);
2260 } else
2261 printk (KERN_INFO "overlap check failed -- %s\n",win->name);
2262 up (sem);
2263 return result;
2264 }
2265
2266
2267
2268 /* Does not generate WinChange event */
2269 int fbui_hide (struct fb_info *info, struct fbui_window *self,
2270 struct fbui_window *win)
2271 {
2272 struct semaphore *sem;
2273 int cons;
2274
2275 if (!info || !self || !win)
2276 return FBUI_ERR_NULLPTR;
2277 if (!self->is_wm)
2278 return FBUI_ERR_NOTWM;
2279 if (self == win)
2280 return FBUI_ERR_BADPARAM;
2281 cons = self->console;
2282 if (cons != win->console)
2283 return FBUI_ERR_BADPARAM;
2284 /*----------*/
2285
2286 if (!win->is_hidden) {
2287 struct fbui_event ev;
2288 struct fbui_window *win2, *wm;
2289
2290 wm = fbui_lookup_wm (info, cons);
2291
2292 /* printk(KERN_INFO "Entered fbui_hide: hiding unhidden window %s/%d\n", win->name,win->id); */
2293 sem = &info->windowSems [win->id];
2294 down (sem);
2295 if (!wm) {
2296 /* Rule: if there is a window manager running,
2297 * let it decide whether to perform a window clear.
2298 */
2299 u32 c = win->bgcolor;
2300 win->bgcolor = info->bgcolor [cons];
2301 fbui_clear (info, win); /* clear to display bgcolor */
2302 win->bgcolor = c;
2303 }
2304 win->is_hidden = 1;
2305 up (sem);
2306
2307 memset (&ev, 0, sizeof (struct fbui_event));
2308 ev.type = FBUI_EVENT_HIDE;
2309 fbui_enqueue_event (info, win, &ev, 0);
2310
2311 down_read (&info->winptrSem);
2312 win2 = info->pointer_window [info->currcon];
2313 up_read (&info->winptrSem);
2314
2315 if (win2 == win) {
2316 memset (&ev, 0, sizeof (struct fbui_event));
2317 ev.type = FBUI_EVENT_LEAVE;
2318 fbui_enqueue_event (info, win, &ev, 0);
2319 }
2320 }
2321
2322 return FBUI_SUCCESS;
2323 }
2324
2325
2326 /* Does not generate WinChange event */
2327 int fbui_unhide (struct fb_info *info, struct fbui_window *self,
2328 struct fbui_window *win)
2329 {
2330 struct semaphore *sem;
2331 struct fbui_event ev;
2332 struct fbui_window *win2;
2333 int cons;
2334
2335 if (!info || !self || !win)
2336 return 0;
2337 if (!self->is_wm)
2338 return 0;
2339 if (self == win)
2340 return FBUI_ERR_BADPARAM;
2341 cons = self->console;
2342 if (cons != win->console)
2343 return FBUI_ERR_BADPARAM;
2344 if (!win->is_hidden)
2345 return FBUI_SUCCESS;
2346 /*----------*/
2347
2348 /* Rule: Don't allow unhide if the window will overlap.
2349 */
2350 if (fbui_overlap_check (info, win->x0, win->y0, win->x1, win->y1,
2351 cons, win))
2352 return FBUI_ERR_OVERLAP;
2353
2354 sem = &info->windowSems [win->id];
2355 down (sem);
2356 win->is_hidden = 0;
2357 fbui_clear (info, win);
2358 up (sem);
2359
2360 memset (&ev, 0, sizeof (struct fbui_event));
2361 ev.type = FBUI_EVENT_UNHIDE;
2362 fbui_enqueue_event (info, win, &ev, 0);
2363 ev.type = FBUI_EVENT_EXPOSE;
2364 fbui_enqueue_event (info, win, &ev, 0);
2365
2366 down_read (&info->winptrSem);
2367 win2 = get_pointer_window (info);
2368 up_read (&info->winptrSem);
2369 if (win2 == win) {
2370 memset (&ev, 0, sizeof (struct fbui_event));
2371 ev.type = FBUI_EVENT_ENTER;
2372 fbui_enqueue_event (info, win, &ev, 0);
2373 }
2374
2375 return FBUI_SUCCESS;
2376 }
2377
2378
2379 static struct fbui_processentry *alloc_processentry (struct fb_info *info,
2380 int pid, int cons)
2381 {
2382 int i;
2383 struct fbui_processentry *pre;
2384 struct semaphore *sem;
2385
2386 if (!info)
2387 return NULL;
2388 /*----------*/
2389
2390 sem = &info->preSem;
2391 down(sem);
2392 i=0;
2393 while (i < FBUI_MAXCONSOLES * FBUI_MAXWINDOWSPERVC) {
2394 pre = &info->processentries[i];
2395 if (!pre->in_use) {
2396 pre->index = i;
2397 pre->waiting = 0;
2398 pre->pid = pid;
2399 pre->console = cons;
2400 pre->nwindows = 0;
2401 pre->events_head = 0;
2402 pre->events_tail = 0;
2403 pre->events_pending = 0;
2404 init_waitqueue_head(&pre->waitqueue);
2405 pre->window_num = -1;
2406 pre->queuelock = SPIN_LOCK_UNLOCKED;
2407 init_MUTEX (&pre->queuesem);
2408 pre->in_use = 1;
2409 up (sem);
2410 return pre;
2411 }
2412 i++;
2413 }
2414 up (sem);
2415 return NULL;
2416 }
2417
2418 static void free_processentry (struct fb_info *info, struct fbui_processentry *pre)
2419 {
2420 struct semaphore *sem;
2421 if (!pre)
2422 return;
2423 /*----------*/
2424
2425 sem = &info->preSem;
2426 down (sem);
2427 pre->in_use = 0;
2428 pre->waiting = 0;
2429 pre->pid = 0;
2430 pre->nwindows = 0;
2431 pre->events_head = 0;
2432 pre->events_tail = 0;
2433 pre->events_pending = 0;
2434 up (sem);
2435 }
2436
2437
2438
2439
2440 int fbui_control (struct fb_info *info, struct fbui_ctrlparams *ctl)
2441 {
2442 struct fbui_window *self=NULL;
2443 struct fbui_window *win=NULL;
2444 struct fbui_processentry *pre=NULL;
2445 int cons = -1;
2446 char cmd;
2447 short id;
2448 short x, y;
2449 short width, height;
2450 struct fbui_event *event;
2451 unsigned char *pointer;
2452 u32 cutlen;
2453
2454 if (!info || !ctl)
2455 return FBUI_ERR_NULLPTR;
2456 /*----------*/
2457
2458 cmd = ctl->op;
2459 x = ctl->x;
2460 y = ctl->y;
2461 width = ctl->width;
2462 height = ctl->height;
2463 id = ctl->id;
2464 event = ctl->event;
2465 pointer = ctl->pointer;
2466 cutlen = ctl->cutpaste_length;
2467
2468 if (id < 0)
2469 return FBUI_ERR_BADPARAM;
2470
2471 if (!(self = fbui_lookup_win (info, id)))
2472 return FBUI_ERR_MISSINGWIN;
2473
2474 pre = self->processentry;
2475 if (pre->pid != current->pid)
2476 return FBUI_ERR_BADPID;
2477
2478 if (!pre)
2479 return FBUI_ERR_MISSINGPROCENT;
2480
2481 cons = pre->console;
2482 if (cons < 0 || cons >= FBUI_MAXCONSOLES)
2483 return FBUI_ERR_BADVC;
2484 if (cons != id / FBUI_MAXWINDOWSPERVC)
2485 return FBUI_ERR_BADVC;
2486
2487 /* Only poll and wait do not take a window param
2488 */
2489 if (!self && (cmd != FBUI_POLLEVENT && cmd != FBUI_WAITEVENT))
2490 return FBUI_ERR_INVALIDCMD;
2491
2492 if (cmd >= FBUI_CTL_TAKESWIN) {
2493 if (!self->is_wm)
2494 return FBUI_ERR_NOTWM;
2495 if (!(win = fbui_lookup_win (info, ctl->id2)))
2496 return FBUI_ERR_BADPID;
2497 if (win->console != cons)
2498 return FBUI_ERR_WRONGWM;
2499 }
2500
2501 switch (cmd) {
2502 case FBUI_REDRAW:
2503 return fbui_redraw (info, self, win);
2504
2505 case FBUI_DELETE:
2506 return fbui_delete (info, self, win);
2507
2508 case FBUI_MOVE_RESIZE:
2509 return fbui_move_resize (info, self, win, x, y, width, height);
2510
2511 case FBUI_HIDE:
2512 return fbui_hide (info, self, win);
2513
2514 case FBUI_UNHIDE:
2515 return fbui_unhide (info, self, win);
2516
2517 case FBUI_WININFO:
2518 return fbui_window_info (info, cons, ctl->info, ctl->ninfo);
2519
2520 case FBUI_ACCEL:
2521 return fbui_accel (info, self, ctl->x, ctl->y);
2522
2523 case FBUI_GETDIMS: {
2524 long value;
2525 if (self->need_placement)
2526 value = FBUI_ERR_NOTPLACED;
2527 else {
2528 value = self->width;
2529 value <<= 16;
2530 value |= self->height;
2531 }
2532 return value;
2533 }
2534
2535 case FBUI_READMOUSE: {
2536 long value;
2537 value = self->mouse_x;
2538 value <<= 16;
2539 value |= self->mouse_y;
2540 return value;
2541 }
2542
2543 case FBUI_GETPOSN: {
2544 u32 value;
2545 if (self->need_placement) {
2546 value = FBUI_ERR_NOTPLACED;
2547 } else {
2548 value = self->x0;
2549 value <<= 16;
2550 value |= self->y0;
2551 }
2552 return value;
2553 }
2554
2555 case FBUI_ASSIGN_KEYFOCUS:
2556 if (!win->is_hidden && win->need_keys && !win->is_wm) {
2557 down_write (&info->winptrSem);
2558 info->keyfocus_window [cons] = win;
2559 up_write (&info->winptrSem);
2560 }
2561 return FBUI_SUCCESS;
2562
2563 case FBUI_ASSIGN_PTRFOCUS:
2564 if (!win->is_hidden && win->need_motion && !win->is_wm) {
2565 down_write (&info->winptrSem);
2566 info->pointerfocus_window [cons] = win;
2567 up_write (&info->winptrSem);
2568 }
2569 return FBUI_SUCCESS;
2570
2571 case FBUI_SUBTITLE:
2572 strncpy (self->subtitle, ctl->string, FBUI_NAMELEN);
2573 fbui_winptrs_change (info, self->console);
2574 return FBUI_SUCCESS;
2575
2576 case FBUI_SETFONT:
2577 if (!access_ok (VERIFY_READ, pointer, FBUI_FONTSIZE))
2578 return FBUI_ERR_BADADDR;
2579
2580 if (copy_from_user ((char*) &self->font, pointer, FBUI_FONTSIZE))
2581 return FBUI_ERR_BADADDR;
2582
2583 self->font_valid = 1;
2584 return FBUI_SUCCESS;
2585
2586 case FBUI_POLLEVENT:
2587 case FBUI_WAITEVENT: {
2588 struct fbui_event ev;
2589
2590 if (!event)
2591 return FBUI_ERR_NULLPTR;
2592
2593 if (!access_ok (VERIFY_WRITE, (void*)event, sizeof(struct fbui_event)))
2594 return -EFAULT;
2595
2596 /* Rule: all windows for a process use the same event mask */
2597 pre->wait_event_mask = x;
2598
2599 memset (&ev, 0, sizeof (struct fbui_event));
2600 ev.type = FBUI_EVENT_NONE;
2601
2602 if (fbui_dequeue_event (info, pre, &ev)) {
2603 if (copy_to_user (event, &ev, sizeof(struct fbui_event)))
2604 return -EFAULT;
2605 else
2606 return FBUI_SUCCESS;
2607 }
2608
2609 /* No event & polling means exit here */
2610 if (cmd == FBUI_POLLEVENT) {
2611 pre->waiting = 0;
2612 return FBUI_ERR_NOEVENT;
2613 }
2614
2615 pre->waiting = 1;
2616 wait_event_interruptible (pre->waitqueue,
2617 pre->events_pending > 0);
2618
2619 if (fbui_dequeue_event (info, pre, &ev)) {
2620 if (copy_to_user (event, &ev, sizeof(struct fbui_event)))
2621 return -EFAULT;
2622 else
2623 return FBUI_SUCCESS;
2624 } else {
2625 printk (KERN_INFO "XXXXXXXXXX process (pid %d) woken up but no event pending! (pre->nwindows=%d)\n",pre->pid,pre->nwindows);
2626 return FBUI_ERR_NOEVENT;
2627 }
2628 }
2629
2630 case FBUI_READPOINT:
2631 if (!self->is_wm)
2632 return RGB_NOCOLOR;
2633 else
2634 return info->fbops->fb_read_point ?
2635 info->fbops->fb_read_point (info, x, y) :
2636 RGB_NOCOLOR;
2637
2638 case FBUI_PLACEMENT:
2639 if (self->is_wm) {
2640 info->force_placement[cons] = x?1:0;
2641 return FBUI_SUCCESS;
2642 }
2643 else
2644 return FBUI_ERR_NOTWM;
2645
2646 case FBUI_CUT: { /* write to kernel buf */
2647 unsigned char *ptr;
2648 char err=0;
2649 if (!pointer)
2650 return FBUI_ERR_NULLPTR;
2651
2652 if (cutlen <= 0)
2653 return FBUI_ERR_BADPARAM;
2654
2655 if (!access_ok (VERIFY_READ, pointer, cutlen))
2656 return FBUI_ERR_BADADDR;
2657
2658 down_write (&info->cutpaste_sem);
2659 ptr = kmalloc (cutlen, GFP_KERNEL);
2660 if (!ptr)
2661 err = 1;
2662 else {
2663 if (copy_from_user (ptr, pointer, cutlen)) {
2664 err = 1;
2665 kfree (ptr);
2666 } else {
2667 /* success */
2668 if (info->cutpaste_buffer)
2669 kfree (info->cutpaste_buffer);
2670 info->cutpaste_buffer = ptr;
2671 info->cutpaste_length = cutlen;
2672 }
2673 }
2674 up_write (&info->cutpaste_sem);
2675 if (err)
2676 return FBUI_ERR_CUTFAIL;
2677 else
2678 return FBUI_SUCCESS;
2679 }
2680
2681 case FBUI_CUTLENGTH:
2682 return info->cutpaste_length;
2683
2684 case FBUI_PASTE: { /* read from kernel buf */
2685 unsigned char *ptr;
2686 char err = 0;
2687
2688 if (!pointer)
2689 return FBUI_ERR_NULLPTR;
2690
2691 if (cutlen <= 0)
2692 return FBUI_ERR_BADPARAM;
2693
2694 if (!access_ok (VERIFY_WRITE, pointer, cutlen))
2695 return FBUI_ERR_BADADDR;
2696
2697 if (info->cutpaste_buffer)
2698 kfree (info->cutpaste_buffer);
2699 down_read (&info->cutpaste_sem);
2700 ptr = info->cutpaste_buffer;
2701 if (ptr) {
2702 u32 len = sizeof(struct fbui_wininfo);
2703 if (cutlen < len)
2704 len = cutlen;
2705 if (copy_to_user (pointer, ptr, len))
2706 err = 1;
2707 } else
2708 err = 1;
2709 up_read (&info->cutpaste_sem);
2710 if (err)
2711 return FBUI_ERR_PASTEFAIL;
2712
2713 /* return byte count */
2714 if (!ptr)
2715 return 0;
2716 else
2717 return cutlen;
2718 } /* paste */
2719
2720 default:
2721 return FBUI_ERR_INVALIDCMD;
2722 }
2723 }
2724
2725
2726 static char cmdinfo[] =
2727 {
2728 0, /* none */
2729 192+ 6, /* copy area x0,y0,x1,y1,w,h*/
2730 32+128+ 4, /* point x,y,color lo,hi*/
2731 32+192+ 6, /* line x0,y0,x1,y1,color lo,hi*/
2732 32+128+ 5, /* hline x0,x1,color lo,hi,y*/
2733 32+128+ 5, /* vline y0,y1,color lo,hi,x*/
2734 32+192+ 6, /* rect x0,y0,x1,y1,color lo,hi*/
2735 32+192+ 6, /* fill_area x0,y0,x1,y1,color lo,hi*/
2736 0, /* clear */
2737 192+ 4, /* invertline x0,y0,x1,y1*/
2738 32+128+ 9, /* string x,y,font lo,hi,len, string lo,hi, fgcolor lo,hi*/
2739 32+128+ 5, /* put pixels x,y,ptr lo,hi,len*/
2740 32+128+ 5, /* put pixels RGB x,y,ptr lo,hi,len */
2741 32+128+ 5, /* put pixels RGB 3-byte x,y,ptr lo,hi,len */
2742 192+ 4, /* clear area x0,y0,x1,y1*/
2743 32+128+ 9, /* tinyblit x,y,color lo,hi,bgcolor lo,hi,width, bitmap lo,hi */
2744 };
2745
2746
2747 /* This routine executes commands which can be
2748 * safely ignored when a window is hidden, suspended, or
2749 * not in the foreground console.
2750 */
2751 int fbui_exec (struct fb_info *info, short win_id, short n, unsigned char *arg)
2752 {
2753 struct fbui_window *win=NULL;
2754 unsigned char *argmax = arg + n * 2;
2755 int result = FBUI_SUCCESS;
2756 char initial_hide=0;
2757
2758 if (!info || !arg)
2759 return FBUI_ERR_NULLPTR;
2760 if (win_id < 0 || win_id >= (FBUI_MAXWINDOWSPERVC * FBUI_MAXCONSOLES))
2761 return FBUI_ERR_BADWIN;
2762 if (info->fix.visual != FB_VISUAL_TRUECOLOR &&
2763 info->fix.visual != FB_VISUAL_DIRECTCOLOR)
2764 return FBUI_ERR_WRONGVISUAL;
2765 if (n < 0)
2766 return FBUI_ERR_INVALIDCMD; /* XX */
2767 /*----------*/
2768
2769 if (!(win = fbui_lookup_win (info, win_id)))
2770 return FBUI_ERR_BADWIN;
2771 if (win->pid != current->pid)
2772 return FBUI_ERR_BADWIN;
2773 if (win->is_hidden)
2774 return FBUI_SUCCESS;
2775
2776 down (&info->windowSems [win->id]);
2777 win->drawing = 1;
2778
2779 initial_hide = info->pointer_hidden;
2780
2781 while (!result && arg < argmax && !win->is_hidden)
2782 {
2783 unsigned short ary [20];
2784 short len;
2785 short a=0, b=0, c=0, d=0, wid=0, ht=0;
2786 u32 ptr=0;
2787 unsigned short cmd;
2788 unsigned char flags;
2789 unsigned short ix;
2790 u32 param32=0;
2791
2792 if (get_user (cmd, arg)) {
2793 result = FBUI_ERR_BADADDR;
2794 break;
2795 }
2796 arg += 2;
2797
2798 if (cmd > sizeof (cmdinfo)) {
2799 result = FBUI_ERR_INVALIDCMD;
2800 break;
2801 }
2802
2803 flags = cmdinfo[cmd];
2804 if ((len = 2 * (flags & 31))) {
2805 if (copy_from_user (ary, arg, len)) {
2806 result = FBUI_ERR_BADADDR;
2807 break;
2808 }
2809 }
2810 arg += len;
2811
2812 ix = 0;
2813 if (flags & 128) {
2814 a = ary[ix++];
2815 b = ary[ix++];
2816 }
2817 if (flags & 64) {
2818 c = ary[ix++];
2819 d = ary[ix++];
2820 }
2821 if (flags & 32) {
2822 param32 = ary[ix+1];
2823 param32 <<= 16;
2824 param32 |= ary[ix];
2825 ix+=2;
2826 }
2827
2828 switch(cmd) {
2829 case FBUI_CLEAR:
2830 result = fbui_clear (info,win);
2831 if (result)
2832 goto finished;
2833 break;
2834
2835 case FBUI_POINT:
2836 result = fbui_draw_point (info,win, a,b,param32);
2837 if (result)
2838 goto finished;
2839 break;
2840
2841 case FBUI_INVERTLINE:
2842 win->do_invert = 1;
2843 result = fbui_draw_line (info,win, a,b,c,d,0);
2844 win->do_invert = 0;
2845 if (result)
2846 goto finished;
2847 break;
2848
2849 case FBUI_LINE:
2850 result = fbui_draw_line (info,win, a,b,c,d,param32);
2851 if (result)
2852 goto finished;
2853 break;
2854
2855 case FBUI_HLINE:
2856 c = ary[ix++];
2857 result = fbui_draw_hline (info,win,a,b,c,param32);
2858 if (result)
2859 goto finished;
2860 break;
2861
2862 case FBUI_TINYBLIT: {
2863 u32 bits;
2864 u32 bgcolor;
2865 short width;
2866
2867 /* a = x
2868 * b = y
2869 * param32 = fgcolor
2870 */
2871 bgcolor = ary[ix+1];
2872 bgcolor <<= 16;
2873 bgcolor |= ary[ix];
2874 ix += 2;
2875
2876 width = ary[ix++];
2877
2878 bits = ary[ix+1];
2879 bits <<= 16;
2880 bits |= ary[ix];
2881 ix += 2;
2882
2883 /* printk(KERN_INFO "FBUI_TINYBLIT: x=%d y=%d width=%d fgcolor=%08lx bgcolor=%08lx bits=%08lx\n", a,b,width,param32,bgcolor,bits); */
2884
2885 result = fbui_tinyblit (info,win,a,b,width,param32,bgcolor,bits);
2886 if (result)
2887 goto finished;
2888 break;
2889 }
2890
2891 case FBUI_VLINE:
2892 c = ary[ix++];
2893 result = fbui_draw_vline (info,win,c,a,b,param32);
2894 if (result)
2895 goto finished;
2896 break;
2897
2898 case FBUI_RECT:
2899 result = fbui_draw_rect (info,win,a,b,c,d,param32);
2900 if (result)
2901 goto finished;
2902 break;
2903
2904 case FBUI_FILLAREA:
2905 result = fbui_fill_area (info,win,a,b,c,d,param32);
2906 if (result)
2907 goto finished;
2908 break;
2909
2910 case FBUI_CLEARAREA:
2911 result = fbui_clear_area (info,win,a,b,c,d);
2912 if (result)
2913 goto finished;
2914 break;
2915
2916 case FBUI_PUT:
2917 wid = ary[ix++];
2918 result= fbui_put (info,win, a,b,wid, (unsigned char*)param32);
2919 if (result)
2920 goto finished;
2921 break;
2922
2923 case FBUI_PUTRGB:
2924 wid = ary[ix++];
2925 result= fbui_put_rgb (info,win,a,b,wid, (unsigned long*)param32);
2926 if (result)
2927 goto finished;
2928 break;
2929
2930 case FBUI_PUTRGB3:
2931 wid = ary[ix++];
2932 result= fbui_put_rgb3 (info,win, a,b,wid, (unsigned char*)param32);
2933 if (result)
2934 goto finished;
2935 break;
2936
2937 case FBUI_COPYAREA:
2938 wid = ary[ix++];
2939 ht = ary[ix++];
2940 result = fbui_copy_area (info,win,a,b, wid,ht,c,d);
2941 if (result)
2942 goto finished;
2943 break;
2944
2945 case FBUI_STRING: {
2946 struct fbui_font *font = &win->font;
2947 u32 color;
2948 wid = ary[ix++];
2949
2950 ptr = ary[ix+1];
2951 ptr <<= 16;
2952 ptr |= ary[ix];
2953 ix += 2;
2954
2955 if (!ptr) {
2956 result = FBUI_ERR_NULLPTR;
2957 goto finished;
2958 }
2959
2960 color = ary[ix+1];
2961 color <<= 16;
2962 color |= ary[ix];
2963 ix += 2;
2964
2965 if (!param32) {
2966 if (!win->font_valid) {
2967 result = FBUI_ERR_NOFONT;
2968 goto finished;
2969 }
2970 } else {
2971 if (!access_ok (VERIFY_READ, (void*)param32, FBUI_FONTSIZE)) {
2972 result = FBUI_ERR_BADADDR;
2973 goto finished;
2974 }
2975 if (copy_from_user ((char*)font,(char*)param32,FBUI_FONTSIZE)) {
2976 result = FBUI_ERR_BADADDR;
2977 goto finished;
2978 }
2979
2980 win->font_valid = 1;
2981 }
2982
2983 if (!access_ok (VERIFY_READ, (void*)ptr, wid)) {
2984 result = FBUI_ERR_BADADDR;
2985 goto finished;
2986 }
2987 result = fbui_draw_string (info,win,font,a,b,
2988 (unsigned char*) ptr, color);
2989 if (result)
2990 goto finished;
2991 break;
2992 }
2993
2994 } /* switch */
2995 }
2996 finished:
2997 if (!initial_hide && info->pointer_hidden)
2998 fbui_unhide_pointer (info);
2999
3000 win->drawing = 0;
3001 up (&info->windowSems [win->id]);
3002 return result;
3003 }
3004
3005
3006 /* This is provided for completeness sake.
3007 * The current fbdump actually uses mmap().
3008 */
3009 u32 fb_read_point (struct fb_info *info, short x, short y)
3010 {
3011 u32 bytes_per_pixel, offset, value;
3012 unsigned char *ptr;
3013
3014 if (!info || info->state != FBINFO_STATE_RUNNING)
3015 return RGB_NOCOLOR;
3016 if (x < 0 || y < 0 || x >= info->var.xres || y >= info->var.yres)
3017 return RGB_NOCOLOR;
3018 /*----------*/
3019
3020 bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
3021 offset = y * info->fix.line_length + x * bytes_per_pixel;
3022 ptr = offset + ((unsigned char*)info->screen_base);
3023
3024 value = 0;
3025 switch (bytes_per_pixel) {
3026 case 4:
3027 value = fb_readl (ptr);
3028 break;
3029 case 3: {
3030 u32 tmp;
3031 value = 0xff & fb_readb (ptr);
3032 ptr++;
3033 tmp = 0xff & fb_readb (ptr);
3034 ptr++;
3035 tmp <<= 8;
3036 value |= tmp;
3037 tmp = 0xff & fb_readb (ptr);
3038 tmp <<= 16;
3039 value |= tmp;
3040 break;
3041 }
3042 case 2:
3043 value = fb_readw (ptr);
3044 break;
3045 case 1:
3046 value = fb_readb (ptr);
3047 break;
3048 }
3049
3050 return pixel_to_rgb (info, value);
3051 }
3052
3053
3054 short fb_getpixels_rgb (struct fb_info *info, short x, short y, short n,
3055 unsigned long *dest, char in_kernel)
3056 {
3057 short xres, yres;
3058 short i;
3059
3060 if (!info || !dest)
3061 return FBUI_ERR_NULLPTR;
3062 if (n <= 0 || x < 0 || y < 0)
3063 return 0;
3064 xres = info->var.xres;
3065 yres = info->var.yres;
3066 if (x >= xres)
3067 return 0;
3068 if (y >= yres)
3069 return 0;
3070 if (x+n >= xres)
3071 n = xres-x;
3072 /*----------*/
3073
3074 i=n;
3075 while (i > 0) {
3076 u32 rgb = fb_read_point (info, x, y);
3077 if (in_kernel) {
3078 *dest++ = rgb;
3079 } else {
3080 /* not needed? */
3081 }
3082 x++;
3083 i--;
3084 }
3085 return n;
3086 }
3087
3088
3089 static int fbui_draw_point (struct fb_info *info, struct fbui_window *win,
3090 short x, short y, u32 color)
3091 {
3092 short mx,my;
3093 if (!info || !win)
3094 return FBUI_ERR_NULLPTR;
3095 if (info->state != FBINFO_STATE_RUNNING)
3096 return FBUI_ERR_NOTRUNNING;
3097 if (win->console != info->currcon)
3098 return FBUI_SUCCESS;
3099 if (win->is_hidden)
3100 return FBUI_SUCCESS;
3101 if (x < 0 || y < 0 || x >= win->width || y >= win->height)
3102 return 0;
3103 /*----------*/
3104 x += win->x0;
3105 y += win->y0;
3106
3107 if (!info->have_hardware_pointer && info->pointer_active && !info->pointer_hidden) {
3108 short mx1;
3109 short my1;
3110 mx = info->mouse_x0;
3111 my = info->mouse_y0;
3112 mx1 = info->mouse_x1;
3113 my1 = info->mouse_y1;
3114
3115 if (x >= mx && y >= my && x <= mx1 && y <= my1)
3116 fbui_hide_pointer (info);
3117 }
3118
3119 if (info->fbops->fb_point)
3120 info->fbops->fb_point (info, x, y, color, win->do_invert);
3121
3122 return FBUI_SUCCESS;
3123 }
3124
3125
3126 static int fbui_draw_line (struct fb_info *info, struct fbui_window *win,
3127 short x0, short y0, short x1, short y1, u32 color)
3128 {
3129 int dx, dy, e, j, xchange;
3130 char s1, s2;
3131 short x, y;
3132
3133 if (!info || !win)
3134 return FBUI_ERR_NULLPTR;
3135 if (info->state != FBINFO_STATE_RUNNING)
3136 return FBUI_ERR_NOTRUNNING;
3137 if (win->console != info->currcon)
3138 return FBUI_SUCCESS;
3139 if (win->is_hidden)
3140 return FBUI_SUCCESS;
3141 if (x0 < 0 && x1 < 0)
3142 return 0;
3143 if (y0 < 0 && y1 < 0)
3144 return 0;
3145 j = win->width;
3146 if (x0 >= j && x1 >= j)
3147 return 0;
3148 j = win->height;
3149 if (y0 >= j && y1 >= j)
3150 return 0;
3151 /*----------*/
3152
3153 if (!win->do_invert) {
3154 if (x0==x1) {
3155 if (y0==y1)
3156 return fbui_draw_point (info,win,x0,y0,color);
3157 else
3158 return fbui_draw_vline (info,win,x0,y0,y1,color);
3159 }
3160 else
3161 if (y0==y1) {
3162 return fbui_draw_hline (info,win,x0,x1,y0,color);
3163 }
3164 }
3165
3166 /* Bresenham */
3167 s1 = 1;
3168 s2 = 1;
3169 x = x0;
3170 y = y0;
3171
3172 dx = x1-x0;
3173 if (dx < 0) {
3174 dx = -dx;
3175 s1 = -1;
3176 }
3177
3178 dy = y1-y0;
3179 if (dy < 0) {
3180 dy = -dy;
3181 s2 = -1;
3182 }
3183
3184 xchange = 0;
3185
3186 if (dy>dx) {
3187 int tmp = dx;
3188 dx = dy;
3189 dy = tmp;
3190 xchange = 1;
3191 }
3192
3193 e = (dy<<1) - dx;
3194 for (j=0; j <= dx; j++)
3195 {
3196 fbui_draw_point (info,win,x,y,color);
3197
3198 if (e >= 0) {
3199 if (xchange)
3200 x += s1;
3201 else
3202 y += s2;
3203 e -= (dx << 1);
3204 }
3205 if (xchange)
3206 y += s2;
3207 else
3208 x += s1;
3209 e += (dy << 1);
3210 }
3211
3212 return FBUI_SUCCESS;
3213 }
3214
3215
3216 static int fbui_tinyblit (struct fb_info *info, struct fbui_window *win,
3217 short x_, short y, short width_, u32 fg, u32 bg, u32 bitmap_)
3218 {
3219 u32 native_fg=0;
3220 u32 native_bg=0;
3221 u32 bytes_per_pixel;
3222 u32 offset;
3223 u32 bitmap = bitmap_;
3224 unsigned char *ptr;
3225 unsigned char do_bg, width=width_;
3226 short x1;
3227 short x, x0;
3228
3229 if (!info || !win)
3230 return FBUI_ERR_NULLPTR;
3231 if (x_ >= win->width)
3232 return 0;
3233 if (y < 0 || y >= win->height)
3234 return 0;
3235 if (width > 32)
3236 width = 32;
3237 x0 = win->x0;
3238 x1 = x0 + win->width;
3239 x = x0 + x_;
3240 if (x0 + width <= 0)
3241 return 0;
3242 /*----------*/
3243
3244 y += win->y0;
3245
3246 if (!info->have_hardware_pointer && info->pointer_active && !info->pointer_hidden) {
3247 short x2 = x + width - 1;
3248 short mx = info->mouse_x0;
3249 short my = info->mouse_y0;
3250 short mx1 = info->mouse_x1;
3251 short my1 = info->mouse_y1;
3252 if (y >= my && y <= my1) {
3253 if ((mx >= x && mx <= x2) || (mx1 >= x && mx1 <= x2) ||
3254 (x >= mx && x <= mx1))
3255 fbui_hide_pointer (info);
3256 }
3257 }
3258
3259 bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
3260 offset = y * info->fix.line_length + x * bytes_per_pixel;
3261 ptr = ((unsigned char*)info->screen_base);
3262 ptr += offset;
3263
3264 bitmap <<= (32 - width);
3265
3266 native_fg = pixel_from_rgb (info, fg);
3267 do_bg = !(bg & 0xff000000);
3268 if (do_bg)
3269 native_bg = pixel_from_rgb (info, bg);
3270
3271 while (width--) {
3272 if (x >= x1)
3273 break;
3274 if (x >= x0) {
3275 u32 c = native_fg;
3276 u32 bit = bitmap >> 31;
3277 if (!bit)
3278 c = native_bg;
3279
3280 if (bit || (!bit && do_bg))
3281 {
3282 switch (bytes_per_pixel)
3283 {
3284 case 1: fb_writeb (c, ptr); break;
3285 case 2: fb_writew (c, ptr); break;
3286 case 4: fb_writel (c, ptr); break;
3287 case 3:
3288 fb_writeb (c, ptr); ptr++; c >>= 8;
3289 fb_writeb (c, ptr); ptr++; c >>= 8;
3290 fb_writeb (c, ptr);
3291 ptr -= 2;
3292 break;
3293 }
3294 }
3295 }
3296
3297 bitmap <<= 1;
3298 ptr += bytes_per_pixel;
3299 x++;
3300
3301 if (!do_bg && !bitmap)
3302 break;
3303 }
3304
3305 return FBUI_SUCCESS;
3306 }
3307
3308
3309 static int fbui_draw_hline (struct fb_info *info, struct fbui_window *win,
3310 short x0, short x1, short y, u32 color)
3311 {
3312 int i;
3313 short mx,my;
3314 short mx1,my1;
3315
3316 if (!info || !win)
3317 return FBUI_ERR_NULLPTR;
3318 if (info->state != FBINFO_STATE_RUNNING)
3319 return FBUI_ERR_NOTRUNNING;
3320 if (win->console != info->currcon)
3321 return FBUI_SUCCESS;
3322 if (win->is_hidden)
3323 return FBUI_SUCCESS;
3324 if (x0>x1) {
3325 short tmp=x0; x0=x1; x1=tmp;
3326 }
3327 if (y < 0 || y >= win->height)
3328 return 0;
3329 i = win->width;
3330 if (x0 >= i || x1 < 0)
3331 return 0;
3332 if (x0 < 0)
3333 x0 = 0;
3334 if (x1 >= i)
3335 x1 = i-1;
3336 /*----------*/
3337
3338 x0 += win->x0;
3339 x1 += win->x0;
3340 y += win->y0;
3341
3342 if (!info->have_hardware_pointer && info->pointer_active && !info->pointer_hidden) {
3343 mx = info->mouse_x0;
3344 my = info->mouse_y0;
3345 mx1 = info->mouse_x1;
3346 my1 = info->mouse_y1;
3347 if (y >= my && y <= my1) {
3348 if ((mx >= x0 && mx <= x1) || (mx1 >= x0 && mx1 <= x1) ||
3349 (x0 >= mx && x0 <= mx1))
3350 fbui_hide_pointer (info);
3351 }
3352 }
3353
3354 if (info->fbops->fb_hline)
3355 info->fbops->fb_hline (info, x0, x1, y, color);
3356
3357 return FBUI_SUCCESS;
3358 }
3359
3360
3361 static int fbui_draw_vline (struct fb_info *info, struct fbui_window *win,
3362 short x, short y0, short y1, u32 color)
3363 {
3364 short i;
3365 short mx,my;
3366 short mx1,my1;
3367
3368 if (!info || !win)
3369 return FBUI_ERR_NULLPTR;
3370 if (info->state != FBINFO_STATE_RUNNING)
3371 return FBUI_ERR_NOTRUNNING;
3372 if (win->console != info->currcon)
3373 return FBUI_SUCCESS;
3374 if (win->is_hidden)
3375 return FBUI_SUCCESS;
3376 if (y0>y1) {
3377 short tmp=y0; y0=y1; y1=tmp;
3378 }
3379 if (x < 0 || x >= win->width)
3380 return 0;
3381 i = win->height;
3382 if (y1 < 0 || y0 >= i)
3383 return 0;
3384 if (y0 < 0)
3385 y0 = 0;
3386 if (y1 >= i)
3387 y1 = i-1;
3388 /*----------*/
3389
3390 x += win->x0;
3391 y0 += win->y0;
3392 y1 += win->y0;
3393
3394 if (!info->have_hardware_pointer && info->pointer_active && !info->pointer_hidden) {
3395 mx = info->mouse_x0;
3396 my = info->mouse_y0;
3397 mx1 = info->mouse_x1;
3398 my1 = info->mouse_y1;
3399 if (x >= mx && x < mx1) {
3400 if ((my >= y0 && my <= y1) || (my1 >= y0 && my1 <= y1) ||
3401 (y0 >= my && y0 <= my1))
3402 fbui_hide_pointer (info);
3403 }
3404 }
3405
3406 if (info->fbops->fb_vline)
3407 info->fbops->fb_vline (info, x, y0, y1, color);
3408
3409 return FBUI_SUCCESS;
3410 }
3411
3412
3413 static int fbui_draw_rect (struct fb_info *info, struct fbui_window *win,
3414 short x0, short y0, short x1, short y1, u32 color)
3415 {
3416 int retval;
3417
3418 if (!info || !win)
3419 return FBUI_ERR_NULLPTR;
3420 if (info->state != FBINFO_STATE_RUNNING)
3421 return FBUI_ERR_NOTRUNNING;
3422 if (win->console != info->currcon)
3423 return FBUI_SUCCESS;
3424 if (win->is_hidden)
3425 return FBUI_SUCCESS;
3426 /*----------*/
3427
3428 if ((retval = fbui_draw_hline (info, win, x0, x1, y0, color)))
3429 return retval;
3430 if ((retval = fbui_draw_hline (info, win, x0, x1, y1, color)))
3431 return retval;
3432 if ((retval = fbui_draw_vline (info, win, x0, y0, y1, color)))
3433 return retval;
3434 if ((retval = fbui_draw_vline (info, win, x1, y0, y1, color)))
3435 return retval;
3436
3437 return FBUI_SUCCESS;
3438 }
3439
3440
3441 static int fbui_clear_area (struct fb_info *info, struct fbui_window *win,
3442 short x0, short y0, short x1, short y1)
3443 {
3444 if (!info || !win)
3445 return FBUI_ERR_NULLPTR;
3446 /*----------*/
3447
3448 return fbui_fill_area (info,win,x0,y0,x1,y1, win->bgcolor);
3449 }
3450
3451
3452 static int fbui_fill_area (struct fb_info *info, struct fbui_window *win,
3453 short x0, short y0, short x1, short y1, u32 color)
3454 {
3455 int i;
3456
3457 if (!info || !win)
3458 return FBUI_ERR_NULLPTR;
3459 if (info->state != FBINFO_STATE_RUNNING)
3460 return FBUI_ERR_NOTRUNNING;
3461 if (win->console != info->currcon)
3462 return FBUI_SUCCESS;
3463 if (win->is_hidden)
3464 return FBUI_SUCCESS;
3465 if (x0>x1) {
3466 short tmp=x0; x0=x1; x1=tmp;
3467 }
3468 if (y0>y1) {
3469 short tmp=y0; y0=y1; y1=tmp;
3470 }
3471 /*----------*/
3472
3473 i = y0;
3474 while (i <= y1)
3475 fbui_draw_hline (info, win, x0, x1, i++, color);
3476
3477 return FBUI_SUCCESS;
3478 }
3479
3480
3481 int fbui_clear (struct fb_info *info, struct fbui_window *win)
3482 {
3483 if (!info || !win)
3484 return FBUI_ERR_NULLPTR;
3485 if (info->state != FBINFO_STATE_RUNNING)
3486 return FBUI_ERR_NOTRUNNING;
3487 if (win->console != info->currcon)
3488 return FBUI_SUCCESS;
3489 if (win->is_hidden)
3490 return FBUI_SUCCESS;
3491 if (win->is_wm)
3492 return FBUI_SUCCESS;
3493 /*----------*/
3494
3495 /* printk(KERN_INFO "Entered fbui_clear, window %s %d\n", win->name,win->id); */
3496
3497 fbui_clear_area (info, win, 0,0, win->width-1,win->height-1);
3498
3499 /* Following is needed since fbui_clear called from many places,
3500 * not just fbui_exec which does its own unhide
3501 */
3502 fbui_unhide_pointer (info);
3503
3504 return FBUI_SUCCESS;
3505 }
3506
3507
3508 static unsigned char leftshift[4] = {
3509 24, 16, 8, 0
3510 };
3511
3512
3513
3514 /* Returns width of string if > 0, else an error code
3515 */
3516 static int fbui_draw_string (struct fb_info *info, struct fbui_window *win,
3517 struct fbui_font *font,
3518 short x, short y, unsigned char *str, u32 color)
3519 {
3520 unsigned char *bitmap, bitwidth, bitheight;
3521 short ytop, total_width = 0;
3522 short j;
3523
3524 if (!info || !win || !font || !str)
3525 return FBUI_ERR_NULLPTR;
3526 if (win->console != info->currcon)
3527 return FBUI_SUCCESS;
3528 if (win->is_hidden)
3529 return FBUI_SUCCESS;
3530 if (info->state != FBINFO_STATE_RUNNING)
3531 return FBUI_ERR_NOTRUNNING;
3532 if (x >= win->width)
3533 return 0;
3534 if (y + (font->ascent + font->descent) <= 0)
3535 return 0;
3536 if (y >= win->height)
3537 return 0;
3538 /*----------*/
3539
3540 while (x < win->width)
3541 {
3542 char left, descent;
3543 unsigned char ch;
3544 unsigned char width;
3545
3546 if (get_user (ch, str))
3547 return FBUI_ERR_BADADDR;
3548 if (!ch)
3549 break;
3550 str++;
3551
3552 if (ch < font->first_char || ch > font->last_char)
3553 continue;
3554
3555 ch -= font->first_char;
3556 if (ch >= 128 && ch < 160) {
3557 /* our PCF Fonts move [128,159] to end */
3558 ch &= 31;
3559 ch |= 240;
3560 }
3561 else if (ch >= 160)
3562 ch -= 32;
3563
3564 if (get_user (bitmap, &font->bitmaps[ch])
3565 || get_user (bitwidth, &font->bitwidths[ch])
3566 || get_user (bitheight, &font->heights[ch])
3567 || get_user (width, &font->widths[ch])
3568 || get_user (left, &font->lefts[ch])
3569 || get_user (descent, &font->descents[ch]))
3570 return FBUI_ERR_BADADDR;
3571
3572 if (!bitmap || !bitwidth || !bitheight || !width)
3573 continue;
3574
3575 ytop = font->ascent + descent;
3576 ytop -= bitheight;
3577
3578 /* Draw loop */
3579 j = 0;
3580 while (j < bitheight)
3581 {
3582 unsigned long bits;
3583 short current_x;
3584 short current_y = y + j + ytop;
3585 unsigned char datum;
3586 unsigned char bytes_per_row;
3587
3588 bytes_per_row = (bitwidth+7)/8;
3589 if (current_y < 0) {
3590 bitmap += bytes_per_row;
3591 goto ds_inner_skip;
3592 }
3593 if (current_y >= win->height)
3594 break;
3595
3596 current_x = x + left;
3597 bits = 0;
3598
3599 switch (bytes_per_row) {
3600 case 4:
3601 if (get_user (datum, bitmap))
3602 return FBUI_ERR_BADADDR;
3603 bitmap++;
3604 bits |= datum;
3605 case 3:
3606 bits <<= 8;
3607 if (get_user (datum, bitmap))
3608 return FBUI_ERR_BADADDR;
3609 bitmap++;
3610 bits |= datum;
3611 case 2:
3612 bits <<= 8;
3613 if (get_user (datum, bitmap))
3614 return FBUI_ERR_BADADDR;
3615 bitmap++;
3616 bits |= datum;
3617 case 1:
3618 bits <<= 8;
3619 if (get_user (datum, bitmap))
3620 return FBUI_ERR_BADADDR;
3621 bitmap++;
3622 bits |= datum;
3623 }
3624
3625 bits <<= leftshift [bytes_per_row-1];
3626
3627 fbui_tinyblit (info, win, current_x, current_y, bitwidth,
3628 color, RGB_NOCOLOR,
3629 bits);
3630
3631 ds_inner_skip:
3632 j++;
3633 }
3634
3635 x += width;
3636 total_width += width;
3637
3638 } /* char loop */
3639
3640 return total_width;
3641 }
3642
3643
3644
3645 static int fbui_set_geometry (struct fb_info *info, struct fbui_window *win,
3646 short x0, short y0, short x1, short y1)
3647 {
3648 short xres, yres;
3649 short w,h;
3650
3651 if (!info || !win)
3652 return FBUI_ERR_NULLPTR;
3653 xres=info->var.xres;
3654 yres=info->var.yres;
3655 if (x0>x1) {
3656 int tmp=x0; x0=x1; x1=tmp;
3657 }
3658 if (y0>y1) {
3659 int tmp=y0; y0=y1; y1=tmp;
3660 }
3661 if (x1<0 || x0>=xres)
3662 return FBUI_ERR_OFFSCREEN;
3663 if (y1<0 || y0>=yres)
3664 return FBUI_ERR_OFFSCREEN;
3665 if (x0<0)
3666 x0=0;
3667 if (y0<0)
3668 y0=0;
3669 if (x1>=xres)
3670 x1=xres-1;
3671 if (y1>=yres)
3672 y1=yres-1;
3673 /*----------*/
3674
3675 w = x1-x0+1;
3676 h = y1-y0+1;
3677 if (win->max_width && w > win->max_width)
3678 w = win->max_width;
3679 if (win->max_height && h > win->max_height)
3680 h = win->max_height;
3681
3682 win->x0 = x0;
3683 win->y0 = y0;
3684 win->x1 = x0 + w - 1;
3685 win->y1 = y0 + h - 1;
3686 win->width = w;
3687 win->height = h;
3688 /* printk (KERN_INFO "fbui_set_geometry: %s (id=%d) is now at %d %d %d %d , wh = %d %d\n",win->name,win->id,x0,y0,x0+w-1,y0+h-1,w,h); */
3689
3690 return FBUI_SUCCESS;
3691 }
3692
3693
3694 /* Each pixel is 4 bytes, with 4th being transparency (!=0 => 100% transparent)
3695 */
3696 void fb_putpixels_rgb (struct fb_info *info, short x, short y,
3697 short n, unsigned long *src, char in_kernel)
3698 {
3699 int offset;
3700 u32 bytes_per_pixel;
3701 unsigned char *ptr;
3702 int i;
3703 u32 *src2;
3704 short xres, yres;
3705
3706 if (!info || !src || n<=0)
3707 return;
3708 if (n <= 0 || y < 0)
3709 return;
3710 yres = info->var.yres;
3711 if (y >= yres)
3712 return;
3713 xres = info->var.xres;
3714 if (x < 0) {
3715 n += x;
3716 x = 0;
3717 }
3718 if (x+n < 0)
3719 return;
3720 if (x >= xres)
3721 return;
3722 if ((x+n) >= xres)
3723 n = xres - x;
3724 /*----------*/
3725
3726 bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
3727 offset = y * info->fix.line_length + x * bytes_per_pixel;
3728 ptr = info->screen_base;
3729 if (!ptr) {
3730 return;
3731 }
3732 ptr += offset;
3733
3734 src2 = (u32*) src;
3735 i=n;
3736 while (i > 0) {
3737 u32 value;
3738 if (in_kernel) {
3739 value = *src2++;
3740 } else {
3741 if (get_user(value, src2))
3742 return;
3743 src2++;
3744 }
3745
3746 /* XX real transparency is for later */
3747 if (!(0xff000000 & value)) {
3748 value = pixel_from_rgb (info, value);
3749
3750 switch (bytes_per_pixel)
3751 {
3752 case 4:
3753 fb_writel (value, ptr);
3754 ptr += 4;
3755 break;
3756
3757 case 3:
3758 fb_writeb (value, ptr); ptr++; value >>= 8;
3759 fb_writeb (value, ptr); ptr++; value >>= 8;
3760 fb_writeb (value, ptr); ptr++;
3761 break;
3762
3763 case 2:
3764 fb_writew (value, ptr);
3765 ptr += 2;
3766 break;
3767
3768 case 1:
3769 fb_writeb (value, ptr);
3770 *ptr++ = value;
3771 break;
3772
3773 default:
3774 break;
3775 }
3776 } else {
3777 ptr += bytes_per_pixel;
3778 }
3779 i--;
3780 }
3781 }
3782
3783 void fb_putpixels_native (struct fb_info *info, short x,short y,
3784 short n, unsigned char *src, char in_kernel)
3785 {
3786 short bytes_per_pixel;
3787 u32 offset;
3788 unsigned char *ptr;
3789 int i;
3790
3791 if (!info || !src || n<=0)
3792 return;
3793 /*----------*/
3794
3795 bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
3796 offset = y * info->fix.line_length + x * bytes_per_pixel;
3797 ptr = info->screen_base;
3798 if (!ptr)
3799 return;
3800 ptr += offset;
3801
3802 n *= bytes_per_pixel;
3803 i=n;
3804 while (i > 0) {
3805 unsigned char value;
3806 if (in_kernel) {
3807 value = *src++;
3808 } else {
3809 if (get_user(value, src))
3810 return;
3811 src++;
3812 }
3813 fb_writeb (value, ptr);
3814 ptr++;
3815 i--;
3816 }
3817 }
3818
3819 void fb_putpixels_rgb3 (struct fb_info *info, short x,short y,
3820 short n, unsigned char *src, char in_kernel)
3821 {
3822 u32 bytes_per_pixel;
3823 u8 *src2;
3824 int offset;
3825 unsigned char *ptr;
3826 int i;
3827
3828 if (!info || !src || n<=0)
3829 return;
3830 /*----------*/
3831
3832 bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
3833 offset = y * info->fix.line_length + x * bytes_per_pixel;
3834 ptr = info->screen_base;
3835 if (!ptr)
3836 return;
3837
3838 ptr += offset;
3839
3840 src2 = (u8*) src;
3841 i=n;
3842 while (i > 0) {
3843 u32 value;
3844 u32 r,g,b;
3845 u8 byte;
3846 if (in_kernel) {
3847 r = *src2++;
3848 g = *src2++;
3849 b = *src2++;
3850 } else {
3851 if (get_user(byte, src2)) {
3852 return;
3853 }
3854 src2++;
3855 r = byte;
3856 if (get_user(byte, src2)) {
3857 return;
3858 }
3859 g = byte;
3860 src2++;
3861 if (get_user(byte, src2)) {
3862 return;
3863 }
3864 b = byte;
3865 src2++;
3866 }
3867
3868 r >>= (8 - info->var.red.length);
3869 g >>= (8 - info->var.green.length);
3870 b >>= (8 - info->var.blue.length);
3871 r <<= info->var.red.offset;
3872 g <<= info->var.green.offset;
3873 b <<= info->var.blue.offset;
3874 value = r | g | b;
3875
3876 switch (bytes_per_pixel)
3877 {
3878 case 4:
3879 fb_writel (value, ptr);
3880 ptr += 4;
3881 break;
3882
3883 case 3:
3884 fb_writeb (value, ptr); ptr++; value >>= 8;
3885 fb_writeb (value, ptr); ptr++; value >>= 8;
3886 fb_writeb (value, ptr); ptr++;
3887 break;
3888
3889 case 2:
3890 fb_writew (value, ptr);
3891 ptr += 2;
3892 break;
3893
3894 case 1:
3895 fb_writeb (value, ptr);
3896 *ptr++ = value;
3897 break;
3898
3899 default:
3900 break;
3901 }
3902 i--;
3903 }
3904 }
3905
3906
3907 static int fbui_put (struct fb_info *info, struct fbui_window *win,
3908 short x,short y, short n, unsigned char *src)
3909 {
3910 u32 length;
3911 int bytes_per_pixel;
3912 short mx,my;
3913 int i;
3914
3915 if (!info || !win || !src)
3916 return FBUI_ERR_NULLPTR;
3917 if (info->state != FBINFO_STATE_RUNNING)
3918 return FBUI_ERR_NOTRUNNING;
3919 if (win->console != info->currcon)
3920 return FBUI_SUCCESS;
3921 if (win->is_hidden)
3922 return FBUI_SUCCESS;
3923
3924 bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
3925 length = bytes_per_pixel * n;
3926 if (!access_ok (VERIFY_READ,(void*)src, length))
3927 return FBUI_ERR_BADADDR;
3928 if (x >= win->width || y<0 || y >= win->height || (x+n-1) < 0)
3929 return 0;
3930 if (x < 0) {
3931 x = -x;
3932 n -= x;
3933 src += x * bytes_per_pixel;
3934 x = 0;
3935 }
3936 i = x+n-1;
3937 if (i >= win->width) {
3938 short dif = i - win->width;
3939 n -= dif;
3940 n--;
3941 }
3942 if (info->var.red.length > 8 ||
3943 info->var.green.length > 8 ||
3944 info->var.blue.length > 8)
3945 return FBUI_ERR_BIGENDIAN;
3946 /*----------*/
3947
3948 x += win->x0;
3949 y += win->y0;
3950
3951 if (!info->have_hardware_pointer && info->pointer_active && !info->pointer_hidden) {
3952 short mx1,my1;
3953 mx = info->mouse_x0;
3954 my = info->mouse_y0;
3955 mx1 = info->mouse_x1;
3956 my1 = info->mouse_y1;
3957 if (y >= my && y <= my1) {
3958 if ((mx >= x && mx < x+n) || (mx1 >= x && mx1 < x+n))
3959 fbui_hide_pointer (info);
3960 }
3961 }
3962
3963 if (info->fbops->fb_putpixels_native)
3964 info->fbops->fb_putpixels_native (info, x, y, n, src, 0);
3965
3966 return FBUI_SUCCESS;
3967 }
3968
3969
3970 /* Source data are supposed to be ulong aligned,
3971 * and stored as RGBxRGBx... where x is unused.
3972 *
3973 * XX perhaps later, transparency would be nice.
3974 */
3975 static int fbui_put_rgb (struct fb_info *info, struct fbui_window *win,
3976 short x, short y,short n, unsigned long *src)
3977 {
3978 u32 length;
3979 short mx,my;
3980 short mx1,my1;
3981 int i;
3982
3983 if (!info || !win || !src)
3984 return FBUI_ERR_NULLPTR;
3985 if (info->state != FBINFO_STATE_RUNNING)
3986 return FBUI_ERR_NOTRUNNING;
3987 if (win->console != info->currcon)
3988 return FBUI_SUCCESS;
3989 if (win->is_hidden)
3990 return FBUI_SUCCESS;
3991 length = n << 2;
3992 if (!access_ok (VERIFY_READ,(void*)src, length))
3993 return FBUI_ERR_BADADDR;
3994 if (x >= win->width || y<0 || y >= win->height || (x+n-1) < 0)
3995 return 0;
3996 if (x < 0) {
3997 n += x;
3998 src -= x;
3999 x = 0;
4000 }
4001 i = x+n-1;
4002 if (i >= win->width) {
4003 short dif = i - win->width;
4004 n -= dif;
4005 n--;
4006 }
4007 if (info->var.red.length > 8 ||
4008 info->var.green.length > 8 ||
4009 info->var.blue.length > 8)
4010 return FBUI_ERR_BIGENDIAN;
4011 /*----------*/
4012
4013 x += win->x0;
4014 y += win->y0;
4015
4016 if (!info->have_hardware_pointer && info->pointer_active && !info->pointer_hidden) {
4017 mx = info->mouse_x0;
4018 my = info->mouse_y0;
4019 mx1 = info->mouse_x1;
4020 my1 = info->mouse_y1;
4021 if (y >= my && y <= my1) {
4022 if ((mx >= x && mx < x+n) || (mx1 >= x && mx1 <= x+n))
4023 fbui_hide_pointer (info);
4024 }
4025 }
4026
4027 if (info->fbops->fb_putpixels_rgb)
4028 info->fbops->fb_putpixels_rgb (info, x, y, n, src, 0);
4029
4030 return FBUI_SUCCESS;
4031 }
4032
4033
4034
4035
4036 /* same as fbui_put_rgb, except the source data are RGBRGBRGB... */
4037
4038 static int fbui_put_rgb3 (struct fb_info *info, struct fbui_window *win,
4039 short x,short y, short n, unsigned char *src)
4040 {
4041 u32 length;
4042 int i;
4043
4044 if (!info || !win || !src)
4045 return FBUI_ERR_NULLPTR;
4046 if (info->state != FBINFO_STATE_RUNNING)
4047 return FBUI_ERR_NOTRUNNING;
4048 if (win->console != info->currcon)
4049 return FBUI_SUCCESS;
4050 if (win->is_hidden)
4051 return FBUI_SUCCESS;
4052 if (!src)
4053 return FBUI_ERR_NULLPTR;
4054 length = n * 3;
4055 if (!access_ok (VERIFY_READ,(void*)src, length))
4056 return FBUI_ERR_BADADDR;
4057 if (x >= win->width || y<0 || y >= win->height || (x+n-1) < 0)
4058 return 0;
4059 if (x < 0) {
4060 x = -x;
4061 n -= x;
4062 src += x * 3;
4063 x = 0;
4064 }
4065 i = x+n-1;
4066 if (i >= win->width) {
4067 short dif = i - win->width;
4068 n -= dif;
4069 n--;
4070 }
4071 if (info->var.red.length > 8 ||
4072 info->var.green.length > 8 ||
4073 info->var.blue.length > 8)
4074 return FBUI_ERR_BIGENDIAN;
4075 /*----------*/
4076
4077 x += win->x0;
4078 y += win->y0;
4079
4080 if (!info->have_hardware_pointer && info->pointer_active && !info->pointer_hidden) {
4081 short mx,my;
4082 short mx1, my1;
4083 mx = info->mouse_x0;
4084 my = info->mouse_y0;
4085 mx1 = info->mouse_x1;
4086 my1 = info->mouse_y1;
4087 if (y >= my && y <= my1) {
4088 if ((mx >= x && mx < x+n) || (mx1 >= x && mx1 <= x+n))
4089 fbui_hide_pointer (info);
4090 }
4091 }
4092
4093 if (info->fbops->fb_putpixels_rgb3)
4094 info->fbops->fb_putpixels_rgb3 (info, x, y, n, src, 0);
4095
4096 return FBUI_SUCCESS;
4097 }
4098
4099
4100
4101 static void fbui_copy_within (unsigned char *dest, unsigned char *src, u32 n)
4102 {
4103 int dif = dest < src ? src - dest : dest - src;
4104 while (n) {
4105 if (dif >= 4 && n >= 64 && !(3 & (u32)src) && !(3 & (u32)dest)){
4106 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4107 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4108 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4109 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4110 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4111 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4112 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4113 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4114 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4115 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4116 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4117 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4118 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4119 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4120 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4121 fb_writel (fb_readl (src), dest); src+=4; dest+=4;
4122 n -= 64;
4123 } else {
4124 fb_writeb (fb_readb (src), dest); src++; dest++;
4125 n--;
4126 }
4127 }
4128 }
4129
4130
4131 /* XX Would be nice to be able to halt the copy prematurely when window gets hidden.
4132 */
4133 void fb_copyarea (struct fb_info *info,
4134 short xsrc,short ysrc,short w, short h,
4135 short xdest,short ydest)
4136 {
4137 u32 bytes_per_pixel, offset, linelen;
4138 unsigned char *src;
4139 unsigned char *dest;
4140 int n;
4141
4142 if (!info || w<=0 || h<=0)
4143 return;
4144 /*----------*/
4145
4146 bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
4147 linelen = info->fix.line_length;
4148 offset = ysrc * linelen + xsrc * bytes_per_pixel;
4149 src = info->screen_base;
4150 if (!src)
4151 return;
4152
4153 dest = src;
4154 src += offset;
4155 offset = ydest * linelen + xdest * bytes_per_pixel;
4156 dest += offset;
4157 n = w * bytes_per_pixel;
4158
4159 if (ydest < ysrc) {
4160 int j=0;
4161 while (j < h) {
4162 fbui_copy_within (dest,src,n);
4163 dest += linelen;
4164 src += linelen;
4165 j++;
4166 }
4167 } else
4168 if (ydest > ysrc) {
4169 int j=h-1;
4170 dest += linelen * h;
4171 src += linelen * h;
4172 while (j >= 0) {
4173 dest -= linelen;
4174 src -= linelen;
4175 fbui_copy_within (dest,src,n);
4176 j--;
4177 }
4178 } else {
4179 /* y equal */
4180 int dif = xsrc > xdest ? xsrc-xdest : xdest-xsrc;
4181
4182 /* leftgoing */
4183 if (xdest < xsrc) {
4184 int j=0;
4185 while (j < h) {
4186 register unsigned char *d = dest;
4187 register unsigned char *s = src;
4188 register int i = w * bytes_per_pixel;
4189 while (i) {
4190 if (dif>3 && !(3 & (u32) s) && i>3) {
4191 u32 v = fb_readl (s); s+= 4;
4192 if (!(3 & (u32) d)) {
4193 fb_writel (v, d);
4194 d += 4;
4195 i -= 4;
4196
4197 while (i >= 4) {
4198 v= fb_readl (s);
4199 s += 4;
4200 fb_writel(v, d);
4201 d += 4;
4202 i -= 4;
4203 }
4204 } else {
4205 fb_writeb (v, d);
4206 d++; v >>= 8;
4207 fb_writeb (v, d);
4208 d++; v >>= 8;
4209 fb_writeb (v, d);
4210 d++; v >>= 8;
4211 fb_writeb (v, d);
4212 d++;
4213 i -= 4;
4214 }
4215 } else {
4216 fb_writeb (fb_readb (s), d);
4217 s++;
4218 d++;
4219 i--;
4220 }
4221 }
4222 dest += linelen;
4223 src += linelen;
4224 j++;
4225 }
4226
4227 } else {
4228 /* rightgoing */
4229 int j=0;
4230 while (j < h) {
4231 int i = w * bytes_per_pixel;
4232 unsigned char *d = dest + i;
4233 unsigned char *s = src + i;
4234 while (i) {
4235 if (dif>3 && !(3 & (u32) s) && i>3)
4236 {
4237 u32 v;
4238 s -= 4;
4239 v = fb_readl (s);
4240 if (!(3 & (u32) d)) {
4241 d -= 4;
4242 fb_writel (v, d);
4243 i -= 4;
4244
4245 while (i >= 4) {
4246 v=fb_readl(s-3);
4247 s -= 4;
4248 fb_writel(v,d-3);
4249 d -= 4;
4250 i -= 4;
4251 }
4252 } else {
4253 d--;
4254 fb_writeb (v>>24, d);
4255 d--;
4256 fb_writeb (v>>16, d);
4257 d--;
4258 fb_writeb (v>>8, d);
4259 d--;
4260 fb_writeb (v, d);
4261 i -= 4;
4262 }
4263 } else {
4264 s--;
4265 d--;
4266 fb_writeb (fb_readb (s), d);
4267 i--;
4268 }
4269 }
4270 dest += linelen;
4271 src += linelen;
4272 j++;
4273 }
4274 }
4275 }
4276 }
4277
4278 int fbui_copy_area (struct fb_info *info, struct fbui_window *win,
4279 short xsrc,short ysrc,short w, short h, short xdest,short ydest)
4280 {
4281 short win_w, win_h;
4282
4283 if (!info || !win)
4284 return FBUI_ERR_NULLPTR;
4285 if (info->state != FBINFO_STATE_RUNNING)
4286 return FBUI_ERR_NOTRUNNING;
4287 if (win->console != info->currcon)
4288 return FBUI_SUCCESS;
4289 if (win->is_hidden)
4290 return FBUI_SUCCESS;
4291 if (xsrc==xdest && ysrc==ydest)
4292 return 0;
4293 win_w = win->width;
4294 win_h = win->height;
4295 if ((xsrc+w-1) < 0 || (ysrc+h-1) < 0)
4296 return 0;
4297 if (xsrc >= win_w || ysrc >= win_h)
4298 return 0;
4299 if ((xdest+w-1) < 0 || (ydest+h-1) < 0)
4300 return 0;
4301 if (xdest >= win_w || ydest >= win_h)
4302 return 0;
4303 if (xsrc < 0) {
4304 xdest -= xsrc;
4305 w += xsrc;
4306 xsrc=0;
4307 }
4308 if (ysrc < 0) {
4309 ydest -= ysrc;
4310 h += ysrc;
4311 ysrc=0;
4312 }
4313 if ((xsrc+w-1) >= win_w) {
4314 short dif=(xsrc+w) - win_w;
4315 w -= dif;
4316 }
4317 if ((ysrc+h-1) >= win_h) {
4318 short dif=(ysrc+h) - win_h;
4319 h -= dif;
4320 }
4321 if ((xdest+w-1) > win_w) {
4322 short dif=(xdest+w) - win_w;
4323 w -= dif;
4324 }
4325 if ((ydest+h-1) > win_h) {
4326 short dif=(ydest+h) - win_h;
4327 h -= dif;
4328 }
4329 /*----------*/
4330
4331 xsrc += win->x0;
4332 ysrc += win->y0;
4333 xdest += win->x0;
4334 ydest += win->y0;
4335
4336 if (!info->have_hardware_pointer && info->pointer_active &&
4337 !info->pointer_hidden && pointer_in_window (info, win, 0))
4338 fbui_hide_pointer (info);
4339
4340 if (info->fbops->fb_copyarea2)
4341 info->fbops->fb_copyarea2 (info, xsrc,ysrc,w,h,xdest,ydest);
4342
4343 return FBUI_SUCCESS;
4344 }
4345
4346
4347 int fbui_release (struct fb_info *info, int user)
4348 {
4349 if (!info)
4350 return 0;
4351
4352 return 0;
4353 }
4354
4355 EXPORT_SYMBOL(fbui_init);
4356 EXPORT_SYMBOL(fbui_release);
4357 EXPORT_SYMBOL(fbui_control);
4358 EXPORT_SYMBOL(fbui_open);
4359 EXPORT_SYMBOL(fbui_switch);
4360 EXPORT_SYMBOL(fbui_close);
4361 EXPORT_SYMBOL(fbui_exec);
4362
4363 EXPORT_SYMBOL(fb_clear);
4364 EXPORT_SYMBOL(fb_hline);
4365 EXPORT_SYMBOL(fb_vline);
4366 EXPORT_SYMBOL(fb_point);
4367 EXPORT_SYMBOL(fb_read_point);
4368 EXPORT_SYMBOL(fb_copyarea);
4369 EXPORT_SYMBOL(fb_putpixels_native);
4370 EXPORT_SYMBOL(fb_putpixels_rgb);
4371 EXPORT_SYMBOL(fb_getpixels_rgb);
4372 EXPORT_SYMBOL(fb_putpixels_rgb3);
4373 EXPORT_SYMBOL(pixel_from_rgb);
4374 EXPORT_SYMBOL(pixel_to_rgb);
4375
4376 MODULE_AUTHOR("Zachary T Smith <fbui@comcast.net>")
4377 MODULE_DESCRIPTION("In-kernel graphical user interface for applications");
4378 MODULE_LICENSE("GPL");
4379
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.