git.y1.nz

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.