git.y1.nz

fbui

Framebuffer-based graphical environment
download: https://git.y1.nz/archives/fbui.tar.gz
README | Files | Log | Refs

libfbui/libfbui.c

      1 
      2 /*=========================================================================
      3  *
      4  * libfbui, a library for accessing FBUI (in-kernel framebuffer GUI).
      5  * Copyright (C) 2003-2004 Zachary T Smith, fbui@comcast.net
      6  *
      7  * This module is free software; you can redistribute it and/or modify
      8  * it under the terms of the GNU General Public License as published by
      9  * the Free Software Foundation; either version 2 of the License, or
     10  * (at your option) any later version.
     11  *
     12  * This module is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  * GNU General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU General Public License
     18  * along with this module; if not, write to the Free Software
     19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
     20  *
     21  * (See the file COPYING in the main directory of this archive for
     22  * more details.)
     23  *
     24  *=======================================================================*/
     25 
     26 #include <stdio.h>
     27 #include <sys/types.h>
     28 #include <sys/stat.h>
     29 #include <fcntl.h>
     30 #include <sys/ioctl.h>
     31 #include <linux/fb.h>
     32 #include <sys/mman.h>
     33 #include <unistd.h>
     34 #include <linux/vt.h>
     35 #include <signal.h>
     36 #include <errno.h>
     37 #include <linux/input.h>
     38 #include <string.h>
     39 #include <stdlib.h>
     40 #include <ctype.h>
     41 #include <time.h>
     42 #include <sys/param.h>
     43 
     44 
     45 
     46 #include "libfbui.h"
     47 
     48 
     49 static struct fb_fix_screeninfo fi;
     50 static struct fb_var_screeninfo vi;
     51 static struct fbui_openparams oi;
     52 
     53 #define ERRLOG "/tmp/fbui.log"
     54 
     55 
     56 static int dpi = 75;
     57 
     58 
     59 /*-----------------------------------------------------------------------------
     60  * Changes:
     61  *
     62  * Sep 23, ZS: added SIGTERM handler
     63  * Sep 24, ZS: added commandline processing of console# (-c)
     64  * Sep 25, ZS: added read_point
     65  * Sep 25, ZS: added errlog
     66  * Sep 26, ZS: added commandline processing of geometry (-geo)
     67  * Sep 26, ZS: more signals supported
     68  * Oct 01, ZS: updated for new use of control ioctl
     69  * Oct 14, ZS: added support for fbui-input events 
     70  * Oct 14, ZS: added keycode->char conversion
     71  * Oct 22, ZS: fbui_open now ensures dims are available
     72  * Oct 26, ZS: added -fg and -bg
     73  *
     74  *----------------------------------------------------------------------------*/
     75 
     76 
     77 Display *my_dpy = NULL;
     78 int display_fd;
     79 
     80 
     81 static void
     82 errlog (char *s, char *s2)
     83 {
     84 	FILE *f=fopen(ERRLOG,"a"); 
     85 	if (!f) 
     86 		return;
     87 	fprintf(f, "%s(): %s\n", s,s2); 
     88 	fprintf(f, "\tsystem error(%d): %s\n",  errno,strerror(errno));
     89 	fclose(f);
     90 }
     91 
     92 
     93 int
     94 fbui_flush (Display *dpy, Window *win)
     95 {
     96 	int result=0;
     97 
     98 	if (!dpy || !win) return -1;
     99 	/*---------------*/
    100 
    101 	if (win->command_ix <= 2)
    102 		return 0;
    103 
    104 	win->command[0] = win->id;
    105 	win->command[1] = win->command_ix-2;
    106 	if (win->command[1])
    107 		result = ioctl (dpy->fd, FBIO_UI_EXEC, (void*) win->command);
    108 	win->command[0] = win->id;
    109 	win->command[1] = 0;
    110 	win->command_ix = 2;
    111 	return result;
    112 }
    113 
    114 static int
    115 check_flush (Display *dpy, Window *win, int need)
    116 {
    117 	unsigned short nwords;
    118 	int result=0;
    119 
    120 	if (!dpy || !win) return -1;
    121 	/*---------------*/
    122 	nwords = win->command_ix-2;
    123 	if (nwords + need >= LIBFBUI_COMMANDBUFLEN) {
    124 		result = fbui_flush (dpy,win);
    125 	}
    126 	return result;
    127 }
    128 
    129 
    130 
    131 /* called only by wm */
    132 int 
    133 fbui_window_info (Display* dpy, Window *wm, struct fbui_wininfo* info, int ninfo)
    134 {
    135 	int result=0;
    136 
    137 	if (!dpy || !info || ninfo<=0) return -1011;
    138 	/*---------------*/
    139 
    140 	static struct fbui_ctrlparams ctl;
    141 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    142 	ctl.op = FBUI_WININFO;
    143 	ctl.id = wm->id;
    144 	ctl.info = info;
    145 	ctl.ninfo = ninfo;
    146 
    147 	return ioctl (dpy->fd, FBIO_UI_CONTROL, (unsigned long) &ctl);
    148 }
    149 
    150 int 
    151 fbui_accelerator (Display* dpy, Window *wm, short key, short op)
    152 {
    153 	int result=0;
    154 
    155 	if (!dpy) return -1;
    156 	/*---------------*/
    157 
    158 	struct fbui_ctrlparams ctl;
    159 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    160 	ctl.op = FBUI_ACCEL;
    161 	ctl.id = wm->id;
    162 	ctl.x = key;
    163 	ctl.y = op;
    164 
    165 	return ioctl (dpy->fd, FBIO_UI_CONTROL, (unsigned long) &ctl) < 0 ? -errno : 0;
    166 }
    167 
    168 
    169 int 
    170 fbui_cut (Display* dpy, Window *win, unsigned char *data, unsigned long length)
    171 {
    172 	if (!dpy || !win || !data || !length) 
    173 		return -1;
    174 	/*---------------*/
    175 
    176 	struct fbui_ctrlparams ctl;
    177 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    178 	ctl.op = FBUI_CUT;
    179 	ctl.id = win->id;
    180 	ctl.pointer = data;
    181 	ctl.cutpaste_length = length;
    182 
    183 	return ioctl (dpy->fd, FBIO_UI_CONTROL, (unsigned long) &ctl) < 0 ? -errno : 0;
    184 }
    185 
    186 int 
    187 fbui_paste (Display* dpy, Window *win, unsigned char *data, unsigned long max)
    188 {
    189 	if (!dpy || !win || !data || !max) 
    190 		return -1;
    191 	/*---------------*/
    192 
    193 	struct fbui_ctrlparams ctl;
    194 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    195 	ctl.op = FBUI_PASTE;
    196 	ctl.id = win->id;
    197 	ctl.pointer = data;
    198 	ctl.cutpaste_length = max;
    199 
    200 	return ioctl (dpy->fd, FBIO_UI_CONTROL, (unsigned long) &ctl) < 0 ? -errno : 0;
    201 }
    202 
    203 
    204 long
    205 fbui_cut_length (Display* dpy, Window *win)
    206 {
    207 	if (!dpy || !win)
    208 		return -1;
    209 	/*---------------*/
    210 
    211 	struct fbui_ctrlparams ctl;
    212 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    213 	ctl.op = FBUI_CUTLENGTH;
    214 	ctl.id = win->id;
    215 
    216 	return ioctl (dpy->fd, FBIO_UI_CONTROL, (unsigned long) &ctl) < 0 ? -errno : 0;
    217 }
    218 
    219 
    220 /* 1 => force all windows to be auto placed
    221  */
    222 /* called only by wm */
    223 int 
    224 fbui_placement (Display* dpy, Window *wm, int yes)
    225 {
    226 	int result=0;
    227 
    228 	if (!dpy) return -1;
    229 	/*---------------*/
    230 
    231 	struct fbui_ctrlparams ctl;
    232 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    233 	ctl.op = FBUI_PLACEMENT;
    234 	ctl.id = wm->id;
    235 	ctl.x = yes;
    236 
    237 	return ioctl (dpy->fd, FBIO_UI_CONTROL, (unsigned long) &ctl) < 0 ? -errno : 0;
    238 }
    239 
    240 
    241 /* called only by wm */
    242 int
    243 fbui_redraw (Display *dpy, Window *wm, short win)
    244 {
    245 	int result=0;
    246 
    247 	if (!dpy) return -1;
    248 	/*---------------*/
    249 
    250 	struct fbui_ctrlparams ctl;
    251 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    252 	ctl.op = FBUI_REDRAW;
    253 	ctl.id = wm->id;
    254 	ctl.id2 = win;
    255 
    256 	return ioctl (dpy->fd, FBIO_UI_CONTROL, (unsigned long)&ctl) < 0 ? -errno : 0;
    257 }
    258 
    259 
    260 
    261 /* called only by wm */
    262 int
    263 fbui_move_resize (Display *dpy, Window *wm, short id, short x0, short y0, short x1, short y1)
    264 {
    265 	int result=0;
    266 
    267 	if (!dpy) return -1;
    268 	/*---------------*/
    269 
    270 	if (x0>x1) { short tmp=x0;x0=x1;x1=tmp; }
    271 	if (y0>y1) { short tmp=y0;y0=y1;y1=tmp; }
    272 
    273 	struct fbui_ctrlparams ctl;
    274 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    275 	ctl.op = FBUI_MOVE_RESIZE;
    276 	ctl.id = wm->id;
    277 	ctl.id2 = id;
    278 	ctl.x = x0;
    279 	ctl.y = y0;
    280 	ctl.width = x1-x0+1;
    281 	ctl.height = y1-y0+1;
    282 
    283 	return ioctl (dpy->fd, FBIO_UI_CONTROL, (unsigned long)&ctl) < 0 ? -errno : 0;
    284 }
    285 
    286 /* called only by wm */
    287 int
    288 fbui_delete (Display *dpy, Window *wm, short id)
    289 {
    290 	int result=0;
    291 
    292 	if (!dpy) return -1;
    293 	/*---------------*/
    294 
    295 	struct fbui_ctrlparams ctl;
    296 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    297 	ctl.op = FBUI_DELETE;
    298 	ctl.id = wm->id;
    299 	ctl.id2 = id;
    300 
    301 	int rv=1;
    302 	do {
    303 		rv = ioctl (dpy->fd, FBIO_UI_CONTROL, (unsigned long)&ctl);
    304 		if (rv < 0 && -errno != FBUI_ERR_DRAWING)
    305 			FATAL ("error when deleting window");
    306 	}
    307 	while (rv);
    308 
    309 	return 0;
    310 }
    311 
    312 /* called only by wm */
    313 int
    314 fbui_assign_keyfocus (Display *dpy, Window *wm, short id)
    315 {
    316 	int result=0;
    317 
    318 	if (!dpy) return -1;
    319 	/*---------------*/
    320 
    321 	struct fbui_ctrlparams ctl;
    322 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    323 	ctl.op = FBUI_ASSIGN_KEYFOCUS;
    324 	ctl.id = wm->id;
    325 	ctl.id2 = id;
    326 
    327 	return ioctl (dpy->fd, FBIO_UI_CONTROL, (unsigned long)&ctl) < 0 ? -errno : 0;
    328 }
    329 
    330 /* called only by wm */
    331 int
    332 fbui_assign_pointerfocus (Display *dpy, Window *wm, short id)
    333 {
    334 	int result=0;
    335 
    336 	if (!dpy) return -1;
    337 	/*---------------*/
    338 
    339 	struct fbui_ctrlparams ctl;
    340 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    341 	ctl.op = FBUI_ASSIGN_PTRFOCUS;
    342 	ctl.id = wm->id;
    343 	ctl.id2 = id;
    344 
    345 	return ioctl (dpy->fd, FBIO_UI_CONTROL, (unsigned long)&ctl) < 0 ? -errno : 0;
    346 }
    347 
    348 /* called only by wm */
    349 int
    350 fbui_hide (Display *dpy, Window *wm, short id)
    351 {
    352 	int result=0;
    353 
    354 	if (!dpy) return -1;
    355 	/*---------------*/
    356 
    357 	struct fbui_ctrlparams ctl;
    358 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    359 	ctl.op = FBUI_HIDE;
    360 	ctl.id = wm->id;
    361 	ctl.id2 = id;
    362 
    363 	return ioctl (dpy->fd, FBIO_UI_CONTROL, (unsigned long)&ctl) < 0 ? -errno : 0;
    364 }
    365 
    366 /* called only by wm */
    367 int
    368 fbui_unhide (Display *dpy, Window *wm, short id)
    369 {
    370 	int result=0;
    371 
    372 	if (!dpy) return -1;
    373 	/*---------------*/
    374 
    375 	struct fbui_ctrlparams ctl;
    376 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    377 	ctl.op = FBUI_UNHIDE;
    378 	ctl.id = wm->id;
    379 	ctl.id2 = id;
    380 
    381 	result = ioctl (dpy->fd, FBIO_UI_CONTROL, (unsigned long)&ctl);
    382 	if (result < 0)
    383 		result = -errno;
    384 	return result;
    385 }
    386 
    387 int
    388 fbui_draw_point (Display *dpy, Window *win, short x, short y, unsigned long color)
    389 {
    390 	int result=0;
    391 
    392 	if (!dpy || !win) return -1;
    393 	/*---------------*/
    394 	if (result = check_flush (dpy, win,5))
    395 		return result;
    396 
    397 	win->command [win->command_ix++] = FBUI_POINT;
    398 	win->command [win->command_ix++] = x;
    399 	win->command [win->command_ix++] = y;
    400 	win->command [win->command_ix++] = color;
    401 	win->command [win->command_ix++] = color>>16;
    402 
    403 	return 0;
    404 }
    405 
    406 unsigned long
    407 fbui_read_point (Display *dpy, Window *win, short x, short y)
    408 {
    409 	int result=0;
    410 
    411 	if (!dpy || !win) return -1;
    412 	/*---------------*/
    413 	if (result = check_flush (dpy, win,3))
    414 		return result;
    415 
    416 	win->command [win->command_ix++] = FBUI_READPOINT;
    417 	win->command [win->command_ix++] = x;
    418 	win->command [win->command_ix++] = y;
    419 
    420 	return fbui_flush (dpy, win);
    421 }
    422 
    423 int
    424 fbui_draw_vline (Display *dpy, Window *win, short x, short y0, short y1, unsigned long color)
    425 {
    426 	int result=0;
    427 
    428 	if (!dpy || !win) return -1;
    429 	/*---------------*/
    430 	if (result = check_flush (dpy, win,6))
    431 		return result;
    432 
    433 	win->command [win->command_ix++] = FBUI_VLINE;
    434 	win->command [win->command_ix++] = y0;
    435 	win->command [win->command_ix++] = y1;
    436 	win->command [win->command_ix++] = color;
    437 	win->command [win->command_ix++] = color>>16;
    438 	win->command [win->command_ix++] = x;
    439 
    440 	return 0;
    441 }
    442 
    443 int
    444 fbui_tinyblit (Display *dpy, Window *win, short x, short y, 
    445 		unsigned long color,
    446 		unsigned long bgcolor,
    447 		short width,
    448 		unsigned long bits)
    449 {
    450 	int result=0;
    451 
    452 	if (!dpy || !win) return -1;
    453 	/*---------------*/
    454 	if (result = check_flush (dpy, win,10))
    455 		return result;
    456 
    457 	win->command [win->command_ix++] = FBUI_TINYBLIT;
    458 	win->command [win->command_ix++] = x;
    459 	win->command [win->command_ix++] = y;
    460 	win->command [win->command_ix++] = color;
    461 	win->command [win->command_ix++] = color>>16;
    462 	win->command [win->command_ix++] = bgcolor;
    463 	win->command [win->command_ix++] = bgcolor>>16;
    464 	win->command [win->command_ix++] = width;
    465 	win->command [win->command_ix++] = bits;
    466 	win->command [win->command_ix++] = bits>>16;
    467 
    468 fbui_flush(dpy,win);
    469 
    470 	return 0;
    471 }
    472 
    473 int
    474 fbui_draw_hline (Display *dpy, Window *win, short x0, short x1, short y, unsigned long color)
    475 {
    476 	int result=0;
    477 
    478 	if (!dpy || !win) return -1;
    479 	/*---------------*/
    480 	if (result = check_flush (dpy, win,6))
    481 		return result;
    482 
    483 	win->command [win->command_ix++] = FBUI_HLINE;
    484 	win->command [win->command_ix++] = x0;
    485 	win->command [win->command_ix++] = x1;
    486 	win->command [win->command_ix++] = color;
    487 	win->command [win->command_ix++] = color>>16;
    488 	win->command [win->command_ix++] = y;
    489 
    490 	return 0;
    491 }
    492 
    493 int
    494 fbui_draw_line (Display *dpy, Window *win, short x0, short y0, short x1, short y1, unsigned long color)
    495 {
    496 	int result=0;
    497 
    498 	if (!dpy || !win) return -1;
    499 	/*---------------*/
    500 	if (result = check_flush (dpy, win,7))
    501 		return result;
    502 	win->command [win->command_ix++] = FBUI_LINE;
    503 	win->command [win->command_ix++] = x0;
    504 	win->command [win->command_ix++] = y0;
    505 	win->command [win->command_ix++] = x1;
    506 	win->command [win->command_ix++] = y1;
    507 	win->command [win->command_ix++] = color;
    508 	win->command [win->command_ix++] = color>>16;
    509 
    510 	return 0;
    511 }
    512 
    513 
    514 int
    515 fbui_invert_line (Display *dpy, Window *win, short x0, short y0, short x1, short y1)
    516 {
    517 	int result=0;
    518 
    519 	if (!dpy || !win) return -1;
    520 	/*---------------*/
    521 	if (result = check_flush (dpy, win,5))
    522 		return result;
    523 
    524 	win->command [win->command_ix++] = FBUI_INVERTLINE;
    525 	win->command [win->command_ix++] = x0;
    526 	win->command [win->command_ix++] = y0;
    527 	win->command [win->command_ix++] = x1;
    528 	win->command [win->command_ix++] = y1;
    529 
    530 	return 0;
    531 }
    532 
    533 
    534 int
    535 fbui_draw_string (Display *dpy, Window *win, struct fbui_font *font,
    536 	short x0, short y0, char *str_, 
    537 	unsigned long color)
    538 {
    539 	int result=0;
    540         unsigned long n;
    541         unsigned long n2;
    542 	unsigned char *str = (unsigned char*) str_;
    543 
    544 	if (!dpy || !win || !str)
    545 		return -1;
    546 	/*---------------*/
    547 
    548 	if (result = check_flush (dpy, win,10))
    549 		return result;
    550 
    551         if (!str) FATAL("null param3");
    552 
    553 	n = (unsigned long) str;
    554 	n2 = (unsigned long)font;
    555 
    556 	win->command [win->command_ix++] = FBUI_STRING;
    557 	win->command [win->command_ix++] = x0;
    558 	win->command [win->command_ix++] = y0;
    559 	win->command [win->command_ix++] = n2;
    560 	win->command [win->command_ix++] = n2>>16;
    561 	win->command [win->command_ix++] = strlen (str);
    562 	win->command [win->command_ix++] = n;
    563 	win->command [win->command_ix++] = n>>16;
    564 	win->command [win->command_ix++] = color;
    565 	win->command [win->command_ix++] = color>>16;
    566 
    567 	/* gotta flush, string may not last */
    568 	return fbui_flush (dpy, win);
    569 }
    570 
    571 int 
    572 fbui_set_subtitle (Display *dpy, Window *win, char *str)
    573 {
    574 	struct fbui_ctrlparams ctl;
    575 
    576 	if (!dpy || !win || !str)
    577 		return FBUI_ERR_NULLPTR;
    578 
    579 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    580 	ctl.op = FBUI_SUBTITLE;
    581 	ctl.id = win->id;
    582 	strncpy (ctl.string, str, FBUI_NAMELEN);
    583 
    584 	return ioctl (dpy->fd, FBIO_UI_CONTROL, &ctl) < 0 ? -errno : 0;
    585 }
    586 
    587 int
    588 fbui_set_font (Display *dpy, Window *win, struct fbui_font *font)
    589 {
    590 	if (!dpy || !win || !font)
    591 		return -1;
    592 
    593 	struct fbui_ctrlparams ctl;
    594 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    595 	ctl.op = FBUI_SETFONT;
    596 	ctl.id = win->id;
    597 	ctl.pointer = (unsigned char*) font;
    598 
    599 	return ioctl (dpy->fd, FBIO_UI_CONTROL, (unsigned long) &ctl) < 0 ? -errno : 0;
    600 }
    601 
    602 
    603 int
    604 fbui_clear (Display *dpy, Window *win)
    605 {
    606 	int result=0;
    607 
    608 	if (!dpy || !win) return -1;
    609 	/*---------------*/
    610 	if (result = check_flush (dpy, win,1))
    611 		return result;
    612 
    613 	win->command [win->command_ix++] = FBUI_CLEAR;
    614 
    615 	return 0;
    616 }
    617 
    618 int
    619 fbui_draw_rect (Display *dpy, Window *win, short x0, short y0, short x1, short y1, unsigned long color)
    620 {
    621 	int result=0;
    622 
    623 	if (!dpy || !win) return -1;
    624 	/*---------------*/
    625 	if (result = check_flush (dpy, win,7))
    626 		return result;
    627 
    628 	win->command [win->command_ix++] = FBUI_RECT;
    629 	win->command [win->command_ix++] = x0;
    630 	win->command [win->command_ix++] = y0;
    631 	win->command [win->command_ix++] = x1;
    632 	win->command [win->command_ix++] = y1;
    633 	win->command [win->command_ix++] = color;
    634 	win->command [win->command_ix++] = color>>16;
    635 
    636 	return 0;
    637 }
    638 
    639 int
    640 fbui_fill_area (Display *dpy, Window *win, short x0, short y0, short x1, short y1, unsigned long color)
    641 {
    642 	int result=0;
    643 
    644 	if (!dpy || !win) return -1;
    645 	/*---------------*/
    646 	if (result = check_flush (dpy, win,7))
    647 		return result;
    648 
    649 	win->command [win->command_ix++] = FBUI_FILLAREA;
    650 	win->command [win->command_ix++] = x0;
    651 	win->command [win->command_ix++] = y0;
    652 	win->command [win->command_ix++] = x1;
    653 	win->command [win->command_ix++] = y1;
    654 	win->command [win->command_ix++] = color;
    655 	win->command [win->command_ix++] = color>>16;
    656 
    657 	return 0;
    658 }
    659 
    660 int
    661 fbui_clear_area (Display *dpy, Window *win, short x0, short y0, short x1, short y1)
    662 {
    663 	int result=0;
    664 
    665 	if (!dpy || !win) return -1;
    666 	/*---------------*/
    667 	if (result = check_flush (dpy, win,5))
    668 		return result;
    669 
    670 	win->command [win->command_ix++] = FBUI_CLEARAREA;
    671 	win->command [win->command_ix++] = x0;
    672 	win->command [win->command_ix++] = y0;
    673 	win->command [win->command_ix++] = x1;
    674 	win->command [win->command_ix++] = y1;
    675 
    676 	return 0;
    677 }
    678 
    679 int
    680 fbui_copy_area (Display *dpy, Window *win, short xsrc, short ysrc, short xdest, short ydest, short w, short h)
    681 {
    682 	int result=0;
    683 
    684 	if (!dpy || !win) return -1;
    685 	/*---------------*/
    686 	if (result = check_flush (dpy, win,7))
    687 		return result;
    688 
    689 	win->command [win->command_ix++] = FBUI_COPYAREA;
    690 	win->command [win->command_ix++] = xsrc;
    691 	win->command [win->command_ix++] = ysrc;
    692 	win->command [win->command_ix++] = xdest;
    693 	win->command [win->command_ix++] = ydest;
    694 	win->command [win->command_ix++] = w;
    695 	win->command [win->command_ix++] = h;
    696 
    697 	return 0;
    698 }
    699 
    700 int
    701 fbui_put (Display *dpy, Window *win, short x, short y, short n, unsigned char *p)
    702 {
    703 	int result=0;
    704 
    705 	if (!dpy || !win || !p) return -1;
    706 	/*---------------*/
    707 	if (result = check_flush (dpy, win,6))
    708 		return result;
    709 
    710 	win->command [win->command_ix++] = FBUI_PUT;
    711 	win->command [win->command_ix++] = x;
    712 	win->command [win->command_ix++] = y;
    713 	win->command [win->command_ix++] = (unsigned long)p;
    714 	win->command [win->command_ix++] = ((unsigned long)p)>>16;
    715 	win->command [win->command_ix++] = n;
    716 
    717 	return 0;
    718 }
    719 
    720 int
    721 fbui_put_rgb (Display *dpy, Window *win, short x, short y, short n, unsigned long *p)
    722 {
    723 	int result=0;
    724 
    725 	if (!dpy || !win || !p) return -1;
    726 	/*---------------*/
    727 	if (result = check_flush (dpy, win,6))
    728 		return result;
    729 
    730 	win->command [win->command_ix++] = FBUI_PUTRGB;
    731 	win->command [win->command_ix++] = x;
    732 	win->command [win->command_ix++] = y;
    733 	win->command [win->command_ix++] = (unsigned long) p;
    734 	win->command [win->command_ix++] = ((unsigned long) p) >>16;
    735 	win->command [win->command_ix++] = n;
    736 
    737 	return 0;
    738 }
    739 
    740 int
    741 fbui_put_rgb3 (Display *dpy, Window *win, short x, short y, short n, unsigned char *p)
    742 {
    743 	int result=0;
    744 
    745 	if (!dpy || !win || !p) return -1;
    746 	/*---------------*/
    747 	if (result = check_flush (dpy, win,6))
    748 		return result;
    749 
    750 	win->command [win->command_ix++] = FBUI_PUTRGB3;
    751 	win->command [win->command_ix++] = x;
    752 	win->command [win->command_ix++] = y;
    753 	win->command [win->command_ix++] = (unsigned long) p;
    754 	win->command [win->command_ix++] = ((unsigned long) p) >>16;
    755 	win->command [win->command_ix++] = n;
    756 
    757 	return 0;
    758 }
    759 
    760 
    761 int
    762 fbui_window_close (Display *dpy, Window *win)
    763 {
    764 	int r;
    765 
    766 	if (!dpy || !win) return -1;
    767 	/*---------------*/
    768 	// fbui_flush (dpy, win);
    769 
    770 	r = ioctl (dpy->fd, FBIO_UI_CLOSE, win->id);
    771 
    772 	Window *prev = NULL;
    773 	Window *ptr = dpy->list;
    774 	while (ptr) {
    775 		if (win == ptr)
    776 			break;
    777 		prev = ptr;
    778 		ptr = ptr->next;
    779 	}
    780 	if (ptr) {
    781 		if (!prev)
    782 			dpy->list = win->next;
    783 		else
    784 			prev->next = win->next;
    785 	}
    786 
    787 	free (win);
    788 	return r;
    789 }
    790 
    791 
    792 
    793 // key info that comes from FBUI : bits 0-1= state 2-15=keycode
    794 int
    795 fbui_convert_key (Display *dpy, long keyinfo)
    796 {
    797 	int key,state;
    798 	unsigned short ch=0;
    799 
    800 	if (!dpy) return -1;
    801 	/*---------------*/
    802 
    803 	state = 3 & keyinfo;
    804 	key = keyinfo >> 2;
    805 
    806 	switch (key) {
    807 	case KEY_RIGHTSHIFT:
    808 	case KEY_LEFTSHIFT: 
    809 		dpy->shift = state>0;
    810 		return 0;
    811 
    812 	case KEY_RIGHTCTRL:
    813 	case KEY_LEFTCTRL: 
    814 		dpy->ctrl = state>0;
    815 		return 0;
    816 
    817 	case KEY_RIGHTALT:
    818 	case KEY_LEFTALT: 
    819 		dpy->alt = state>0;
    820 		return 0;
    821 	}
    822 
    823 	if (state==0)
    824 		return 0;
    825 
    826 	switch (key) {
    827 	case KEY_ENTER: ch = '\n'; break;
    828 	case KEY_ESC: ch = 27; break;
    829 	case KEY_SPACE: ch = ' '; break;
    830 	case KEY_MINUS: ch = !dpy->shift ? '-' : '_'; break;
    831 	case KEY_EQUAL: ch = !dpy->shift ? '=' : '+'; break;
    832 	case KEY_BACKSPACE: ch = 8; break;
    833 	case KEY_SEMICOLON: ch = !dpy->shift ? ';' : ':'; break;
    834 	case KEY_COMMA: ch = !dpy->shift ? ',' : '<'; break;
    835 	case KEY_DOT: ch = !dpy->shift ? '.' : '>'; break;
    836 	case KEY_GRAVE: ch = !dpy->shift ? '`' : '~'; break;
    837 	case KEY_BACKSLASH: ch = !dpy->shift ? '\\' : '|'; break;
    838 	case KEY_LEFTBRACE: ch = !dpy->shift ? '[' : '{'; break;
    839 	case KEY_RIGHTBRACE: ch = !dpy->shift ? ']' : '}'; break;
    840 	case KEY_APOSTROPHE: ch = !dpy->shift ? '\'' : '"'; break;
    841 	case KEY_SLASH: ch = !dpy->shift ? '/' : '?'; break;
    842 	case KEY_TAB: ch = !dpy->shift ? '\t' : FBUI_LEFTTAB; break;
    843 	case KEY_A: ch = 'a'; break;
    844 	case KEY_B: ch = 'b'; break;
    845 	case KEY_C: ch = 'c'; break;
    846 	case KEY_D: ch = 'd'; break;
    847 	case KEY_E: ch = 'e'; break;
    848 	case KEY_F: ch = 'f'; break;
    849 	case KEY_G: ch = 'g'; break;
    850 	case KEY_H: ch = 'h'; break;
    851 	case KEY_I: ch = 'i'; break;
    852 	case KEY_J: ch = 'j'; break;
    853 	case KEY_K: ch = 'k'; break;
    854 	case KEY_L: ch = 'l'; break;
    855 	case KEY_M: ch = 'm'; break;
    856 	case KEY_N: ch = 'n'; break;
    857 	case KEY_O: ch = 'o'; break;
    858 	case KEY_P: ch = 'p'; break;
    859 	case KEY_Q: ch = 'q'; break;
    860 	case KEY_R: ch = 'r'; break;
    861 	case KEY_S: ch = 's'; break;
    862 	case KEY_T: ch = 't'; break;
    863 	case KEY_U: ch = 'u'; break;
    864 	case KEY_V: ch = 'v'; break;
    865 	case KEY_W: ch = 'w'; break;
    866 	case KEY_X: ch = 'x'; break;
    867 	case KEY_Y: ch = 'y'; break;
    868 	case KEY_Z: ch = 'z'; break;
    869 	case KEY_0: ch = '0'; break;
    870 	case KEY_1: ch = '1'; break;
    871 	case KEY_2: ch = '2'; break;
    872 	case KEY_3: ch = '3'; break;
    873 	case KEY_4: ch = '4'; break;
    874 	case KEY_5: ch = '5'; break;
    875 	case KEY_6: ch = '6'; break;
    876 	case KEY_7: ch = '7'; break;
    877 	case KEY_8: ch = '8'; break;
    878 	case KEY_9: ch = '9'; break;
    879 
    880 	/* special chars section */
    881 	case KEY_UP: ch = FBUI_UP; break;
    882 	case KEY_DOWN: ch = FBUI_DOWN; break;
    883 	case KEY_LEFT: ch = FBUI_LEFT; break;
    884 	case KEY_RIGHT: ch = FBUI_RIGHT; break;
    885 
    886 	case KEY_INSERT: ch = FBUI_INS; break;
    887 	case KEY_DELETE: ch = FBUI_DEL; break;
    888 	case KEY_HOME: ch = FBUI_HOME; break;
    889 	case KEY_END: ch = FBUI_END; break;
    890 	case KEY_PAGEUP: ch = FBUI_PGUP; break;
    891 	case KEY_PAGEDOWN: ch = FBUI_PGDN; break;
    892 	case KEY_SCROLLLOCK: ch = FBUI_SCRLK; break;
    893 	case KEY_NUMLOCK: ch = FBUI_NUMLK; break;
    894 	case KEY_CAPSLOCK: ch = FBUI_CAPSLK; break;
    895 
    896 	case KEY_PRINT: ch = FBUI_PRTSC; break;
    897 
    898 	case KEY_F1: ch = FBUI_F1; break;
    899 	case KEY_F2: ch = FBUI_F2; break;
    900 	case KEY_F3: ch = FBUI_F3; break;
    901 	case KEY_F4: ch = FBUI_F4; break;
    902 	case KEY_F5: ch = FBUI_F5; break;
    903 	case KEY_F6: ch = FBUI_F6; break;
    904 	case KEY_F7: ch = FBUI_F7; break;
    905 	case KEY_F8: ch = FBUI_F8; break;
    906 	case KEY_F9: ch = FBUI_F9; break;
    907 	case KEY_F10: ch = FBUI_F10; break;
    908 	case KEY_F11: ch = FBUI_F11; break;
    909 	case KEY_F12: ch = FBUI_F12; break;
    910 
    911 	/* mouse buttons */
    912 	case BTN_LEFT: ch = FBUI_BUTTON_LEFT; break;
    913 	case BTN_RIGHT: ch = FBUI_BUTTON_RIGHT; break;
    914 	case BTN_MIDDLE: ch = FBUI_BUTTON_MIDDLE; break;
    915 	}
    916 
    917 	if (dpy->ctrl && isalpha(ch))
    918 		ch &= 31;
    919 	else
    920 	if (dpy->shift && isalpha(ch))
    921 		ch = toupper(ch);
    922 
    923 	if (dpy->shift && isdigit(ch)) {
    924 		switch (ch) {
    925 		case '0': ch = ')'; break;
    926 		case '1': ch = '!'; break;
    927 		case '2': ch = '@'; break;
    928 		case '3': ch = '#'; break;
    929 		case '4': ch = '$'; break;
    930 		case '5': ch = '%'; break;
    931 		case '6': ch = '^'; break;
    932 		case '7': ch = '&'; break;
    933 		case '8': ch = '*'; break;
    934 		case '9': ch = '('; break;
    935 		}
    936 	}
    937 
    938 	return ch;
    939 }
    940 
    941 
    942 int
    943 fbui_poll_event (Display *dpy, Event *e, unsigned short mask)
    944 {
    945 	Window *win;
    946 	short win_id;
    947 	long retval;
    948 
    949 	if (!dpy || !e) 
    950 		return -1;
    951 	/*---------------*/
    952 	win = dpy->list;
    953 	while (win) {
    954 		fbui_flush (dpy, win);
    955 		win = win->next;
    956 	}
    957 
    958 	memset (e, 0, sizeof(Event));
    959 
    960 	struct fbui_event event;
    961 	struct fbui_ctrlparams ctl;
    962 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
    963 	ctl.op = FBUI_POLLEVENT;
    964 	ctl.id = dpy->list ? dpy->list->id : -1; /* window id not required but faster */
    965 	ctl.x = (short)mask;
    966 	ctl.event = &event;
    967 	retval = ioctl (dpy->fd, FBIO_UI_CONTROL, &ctl);
    968 
    969 	if (retval < 0)
    970 		return -errno;
    971 
    972 	e->type = event.type;
    973 	e->id = win_id = event.id;
    974 	e->key = event.key;
    975 	e->x = event.x;
    976 	e->y = event.y;
    977 	e->width = event.width;
    978 	e->height = event.height;
    979 
    980 	win = dpy->list;
    981 	while (win) {
    982 		if (win->id == win_id)
    983 			break;
    984 		win = win->next;
    985 	}
    986 	e->win = win;
    987 
    988 	if (!win)
    989 		fprintf(stderr, "libfbui: cannot identify window for id %d\n", win_id);
    990 	else
    991 	if (event.type == FBUI_MOVE_RESIZE) {
    992 		win->width = event.width;
    993 		win->height = event.height;
    994 	}
    995 
    996 	return 0;
    997 }
    998 
    999 int
   1000 fbui_wait_event (Display *dpy, Event *e, unsigned short mask)
   1001 {
   1002 	Window *win;
   1003 
   1004 	if (!dpy || !e) 
   1005 		return -1;
   1006 	/*---------------*/
   1007 
   1008 	win = dpy->list;
   1009 	while (win) {
   1010 		fbui_flush (dpy, win);
   1011 		win = win->next;
   1012 	}
   1013 
   1014 	memset (e, 0, sizeof(Event));
   1015 
   1016 	struct fbui_event event;
   1017 	struct fbui_ctrlparams ctl;
   1018 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
   1019 	ctl.op = FBUI_WAITEVENT;
   1020 	ctl.id = dpy->list ? dpy->list->id : -1; /* window id not required but faster */
   1021 	ctl.x = (short)mask;
   1022 	ctl.event = &event;
   1023 	int retval = ioctl (dpy->fd, FBIO_UI_CONTROL, &ctl);
   1024 
   1025 	if (retval < 0)
   1026 		return -errno;
   1027 
   1028 	e->type = event.type;
   1029 	short win_id = event.id;
   1030 	e->id = win_id;
   1031 	e->key = event.key;
   1032 	e->x = event.x;
   1033 	e->y = event.y;
   1034 	e->width = event.width;
   1035 	e->height = event.height;
   1036 
   1037 	win = dpy->list;
   1038 	while (win) {
   1039 		if (win->id == win_id)
   1040 			break;
   1041 		win = win->next;
   1042 	}
   1043 	e->win = win;
   1044 
   1045 	if (!win)
   1046 		fprintf(stderr, "libfbui: cannot identify window for id %d\n", win_id);
   1047 	else
   1048 	if (event.type == FBUI_MOVE_RESIZE) {
   1049 		win->width = event.width;
   1050 		win->height = event.height;
   1051 	}
   1052 
   1053 
   1054 	return 0;
   1055 }
   1056 
   1057 int
   1058 fbui_get_dims (Display *dpy, Window *win, short *width, short *height)
   1059 {
   1060 	long result;
   1061 
   1062 	if (!dpy || !win || !width || !height) 
   1063 		return -1;
   1064 	/*---------------*/
   1065 
   1066 	fbui_flush (dpy, win);
   1067 
   1068 	*width = 0;
   1069 	*height = 0;
   1070 
   1071 	struct fbui_ctrlparams ctl;
   1072 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
   1073 	ctl.op = FBUI_GETDIMS;
   1074 	ctl.id = win->id;
   1075 
   1076 	result = ioctl (dpy->fd, FBIO_UI_CONTROL, &ctl);
   1077 //printf ("getdims retval %d (%d)\n",result,-errno);
   1078 	if (result < 0) 
   1079 		return -errno;
   1080 
   1081 	*width = result >> 16;
   1082 	*height = result & 0xffff;
   1083 
   1084 	win->width = *width;
   1085 	win->height = *height;
   1086 
   1087 	return 0;
   1088 }
   1089 
   1090 
   1091 /* note: mouse buttons appear as keystrokes */
   1092 int
   1093 fbui_read_mouse (Display *dpy, Window *win, short *x, short *y)
   1094 {
   1095 	long result;
   1096 
   1097 	if (!dpy || !win || !x || !y) 
   1098 		return -1;
   1099 	/*---------------*/
   1100 
   1101 	fbui_flush (dpy, win);
   1102 
   1103 	*x = 0;
   1104 	*y = 0;
   1105 
   1106 	struct fbui_ctrlparams ctl;
   1107 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
   1108 	ctl.op = FBUI_READMOUSE;
   1109 	ctl.id = win->id;
   1110 
   1111 	result = ioctl (dpy->fd, FBIO_UI_CONTROL, &ctl);
   1112 	if (result < 0) 
   1113 		return result;
   1114 
   1115 	*x = result >> 16;
   1116 	*y = result & 0xffff;
   1117 
   1118 	return 0;
   1119 }
   1120 
   1121 
   1122 int
   1123 fbui_get_position (Display *dpy, Window *win, short *x, short *y)
   1124 {
   1125 	unsigned long result;
   1126 
   1127 	if (!dpy || !win || !x || !y) 
   1128 		return -1;
   1129 	/*---------------*/
   1130 
   1131 	fbui_flush (dpy, win);
   1132 
   1133 	*x = -1;
   1134 	*y = -1;
   1135 
   1136 	struct fbui_ctrlparams ctl;
   1137 	memset (&ctl, 0, sizeof (struct fbui_ctrlparams));
   1138 	ctl.op = FBUI_GETPOSN;
   1139 
   1140 	result = ioctl (dpy->fd, FBIO_UI_CONTROL, &ctl);
   1141 	if (result < 0)
   1142 		return 0;
   1143 
   1144 	*x = result >> 16;
   1145 	*y = result & 0xffff;
   1146 
   1147 	return 1;
   1148 }
   1149 
   1150 static void kill_handler (int foo)
   1151 {
   1152 	if (my_dpy) {
   1153 		Window *win = my_dpy->list;
   1154 		while (win) {
   1155 			Window *next = win->next;
   1156 			fbui_window_close (my_dpy, win);
   1157 			win = next;
   1158 		}
   1159 		my_dpy->list = NULL;
   1160 		fbui_display_close (my_dpy);
   1161 	}
   1162 	exit(-1);
   1163 }
   1164 
   1165 static int hex_to_int (char h)
   1166 {
   1167 	h = tolower(h);
   1168 	if (h >= '0' && h <= '9')
   1169 		return h - '0';
   1170 	else
   1171 	if (h >= 'a' && h <= 'f')
   1172 		return 10 + h - 'a';
   1173 	else
   1174 		return 0;
   1175 }
   1176 
   1177 static long parse_rgb (char *s)
   1178 {
   1179 	int len;
   1180 	long c;
   1181 	if (!s) return -1;
   1182 	len = strlen (s);
   1183 	if (len == 3) {
   1184 		c = hex_to_int (*s++); 
   1185 		c <<= 8;
   1186 		c |= hex_to_int (*s++); 
   1187 		c <<= 8;
   1188 		c |= hex_to_int (*s++); 
   1189 		c <<= 4;
   1190 		return c;
   1191 	}
   1192 	if (len == 6) {
   1193 		c = hex_to_int (*s++); 
   1194 		c <<= 4;
   1195 		c |= hex_to_int (*s++); 
   1196 		c <<= 4;
   1197 		c |= hex_to_int (*s++); 
   1198 		c <<= 4;
   1199 		c |= hex_to_int (*s++); 
   1200 		c <<= 4;
   1201 		c |= hex_to_int (*s++); 
   1202 		c <<= 4;
   1203 		c |= hex_to_int (*s++); 
   1204 		return c;
   1205 	}
   1206 	return -1;
   1207 }
   1208 
   1209 
   1210 static int
   1211 getline (FILE *f, char *buf, int buflen)
   1212 {
   1213         int got;
   1214         char ch;
   1215         int ix=0;
   1216 
   1217         buf[0] = 0;
   1218 
   1219         while (ix < (buflen-1)) {
   1220                 got = fread (&ch, 1, 1, f);
   1221 
   1222                 if (!got)
   1223                         break;
   1224 
   1225                 if (ch == '\n')
   1226                         break;
   1227                 if (ch == '\r')
   1228                         continue;
   1229 
   1230                 buf [ix++] = ch;
   1231         }
   1232 
   1233         buf [ix] = 0;
   1234         return ix;
   1235 }
   1236 
   1237 long
   1238 parse_colorname (char *s)
   1239 {
   1240 	if (!strcmp(s, "red"))
   1241 		return RGB_RED;
   1242 	if (!strcmp(s, "green"))
   1243 		return RGB_GREEN;
   1244 	if (!strcmp(s, "blue"))
   1245 		return RGB_BLUE;
   1246 	if (!strcmp(s, "black"))
   1247 		return 0;
   1248 	if (!strcmp(s, "white"))
   1249 		return 0xffffff;
   1250 	if (!strcmp(s, "steelblue"))
   1251 		return RGB_STEELBLUE;
   1252 	if (!strcmp(s, "sienna"))
   1253 		return RGB_SIENNA;
   1254 	if (!strcmp(s, "cyan"))
   1255 		return RGB_CYAN;
   1256 	if (!strcmp(s, "orange"))
   1257 		return RGB_ORANGE;
   1258 	if (!strcmp(s, "yellow"))
   1259 		return RGB_YELLOW;
   1260 	if (!strcmp(s, "magenta"))
   1261 		return RGB_MAGENTA;
   1262 	if (!strcmp(s, "purple"))
   1263 		return RGB_PURPLE;
   1264 	if (!strcmp(s, "brown"))
   1265 		return RGB_BROWN;
   1266 	if (!strcmp(s, "gray"))
   1267 		return RGB_GRAY;
   1268 
   1269 	FILE *f = fopen ("/usr/X11/lib/X11/rgb.txt","r");
   1270 	char buffer [200];
   1271 	if (!f) return -1;
   1272 	while (getline (f, buffer, 199)) {
   1273 		int r,g,b;
   1274 		char name[100];
   1275 		if (4 == sscanf(buffer,"%u %u %u %s", &r, &g, &b, name)) {
   1276 			if (!strcmp (s, name)) {
   1277 				long color;
   1278 				r &= 0xff;
   1279 				g &= 0xff;
   1280 				b &= 0xff;
   1281 				color = r;
   1282 				color <<= 8;
   1283 				color |= g;
   1284 				color <<= 8;
   1285 				color |= b;
   1286 				fclose(f);
   1287 				return color;
   1288 			}
   1289 		}
   1290 	}
   1291 	fclose(f);
   1292 
   1293 	return -1;
   1294 }
   1295 
   1296 
   1297 /* not static since it's used by fbterm */
   1298 
   1299 int fbui_parse_geom (char *s1, short *w, short *h, short *xr, short *yr)
   1300 {
   1301 	short width=0,height=0,xrel=-1,yrel=-1;
   1302 	char *s2 = NULL;
   1303 	char *s3 = NULL;
   1304 	char *s4 = NULL;
   1305 
   1306 	if (!s1 || !w || !h || !xr || !yr)
   1307 		return 0;
   1308 	/*---------------*/
   1309 
   1310 	if (*s1 && isdigit(*s1)) {
   1311 		char *s2 = strchr (s1, 'x');
   1312 		if (!s2)
   1313 			return 0;
   1314 		*s2++ = 0;
   1315 
   1316 		s3 = s2;
   1317 		while (*s3 && isdigit(*s3))
   1318 			s3++;
   1319 
   1320 		if (*s3) {
   1321 			xrel = *s3=='-' ? -1 : 1;
   1322 			*s3++ = 0;
   1323 
   1324 			s4 = s3;
   1325 			while (*s4 && isdigit(*s4))
   1326 				s4++;
   1327 
   1328 			if (s4) {
   1329 				yrel = *s4=='-' ? -1 : 1;
   1330 				*s4++ = 0;
   1331 			}
   1332 		} else {
   1333 			xrel = 9999; /* no position given */
   1334 			s3 = NULL;
   1335 		}
   1336 
   1337 		width = atoi(s1);
   1338 		height = atoi(s2);
   1339 
   1340 		if (s3 && s4) {
   1341 			int a = atoi(s3);
   1342 			int b = atoi(s4);
   1343 			if (xrel == 1) {
   1344 				xrel = a;
   1345 			} else {
   1346 				xrel = -a - 1;
   1347 			}
   1348 			if (yrel == 1) {
   1349 				yrel = b;
   1350 			} else {
   1351 				yrel = -b - 1;
   1352 			}
   1353 		} else {
   1354 			xrel = 9999;
   1355 		}
   1356 		*w = width;
   1357 		*h = height;
   1358 		*xr = xrel;
   1359 		*yr = yrel;
   1360 		return 1;
   1361 	} else
   1362 		return 0;
   1363 }
   1364 
   1365 
   1366 void
   1367 fbui_display_close (Display* dpy)
   1368 {
   1369 	if (dpy) {
   1370 		Window *win = dpy->list;
   1371 		while (win) {
   1372 			fbui_window_close (dpy, win);
   1373 			win = win->next;
   1374 		}
   1375 		close (dpy->fd);
   1376 		free (dpy);
   1377 	}
   1378 }
   1379 
   1380 Display*
   1381 fbui_display_open ()
   1382 {
   1383 	Display *dpy = NULL;
   1384 	int success=0;
   1385 	int fd;
   1386 
   1387 	if (my_dpy)
   1388 		FATAL ("attempt to re-init");
   1389 
   1390 	fd = open ("/dev/fb0", O_RDWR );
   1391 	if (fd < 0)
   1392 		fd = open ("/dev/fb/0", O_RDWR );
   1393 	display_fd = fd;
   1394 	if (fd < 0)
   1395 	{
   1396 		success= 0;
   1397 		perror("open");
   1398 		errlog(__FUNCTION__, "Open failed");
   1399 	}
   1400 	else
   1401 	{
   1402 		if (ioctl (fd, FBIOGET_FSCREENINFO, &fi))
   1403 		{
   1404 			perror("ioctl");
   1405 			success= 0;
   1406 			errlog(__FUNCTION__, "ioctl1 failed");
   1407 		}
   1408 		else
   1409 		if (ioctl (fd, FBIOGET_VSCREENINFO, &vi))
   1410 		{
   1411 			perror("ioctl");
   1412 			success= 0;
   1413 			errlog(__FUNCTION__, "ioctl2 failed");
   1414 		}
   1415 		else
   1416 		{
   1417 			if (fi.visual != FB_VISUAL_TRUECOLOR &&
   1418 			    fi.visual != FB_VISUAL_DIRECTCOLOR )
   1419 			{
   1420 				FATAL ("Oops, we need a direct/truecolor display");
   1421 				success= 0;
   1422 				errlog(__FUNCTION__, "wrong visual");
   1423 			}
   1424 			else
   1425 			{
   1426 				printf ("Framebuffer resolution: %dx%d, %dbpp\n", vi.xres, vi.yres, vi.bits_per_pixel);
   1427 
   1428 				success = 1;
   1429 			}
   1430 		}
   1431 	}
   1432 
   1433 	if (success) {
   1434 		dpy = (Display*) malloc (sizeof(Display));
   1435 		if (!dpy) {
   1436 			fprintf (stderr, "out of memory\n");
   1437 			return NULL;
   1438 		} 
   1439 
   1440 		my_dpy = dpy;
   1441 		memset ((void*)dpy, 0, sizeof(Display));
   1442 		dpy->fd = fd;
   1443 
   1444 		dpy->width = vi.xres;
   1445 		dpy->height = vi.yres;
   1446 		dpy->depth = vi.bits_per_pixel;
   1447 
   1448 		dpy->red_offset = vi.red.offset;
   1449 		dpy->green_offset = vi.green.offset;
   1450 		dpy->blue_offset = vi.blue.offset;
   1451 		dpy->red_length = vi.red.length;
   1452 		dpy->green_length = vi.green.length;
   1453 		dpy->blue_length = vi.blue.length;
   1454 
   1455 		signal (SIGTERM, kill_handler);
   1456 		signal (SIGINT, kill_handler);
   1457 		signal (SIGSEGV, kill_handler);
   1458 	}
   1459 	return dpy;
   1460 }
   1461 
   1462 Window*
   1463 fbui_window_open (Display *dpy,
   1464 	   short width, short height, 
   1465 	   short *width_return, short *height_return,
   1466 	   short max_width, short max_height,
   1467 	   short xrel, short yrel, 
   1468 	   unsigned long *fgcolor_inout, 
   1469 	   unsigned long *bgcolor_inout, 
   1470 	   char *name, char *subtitle, 
   1471 	   char program_type, 
   1472 	   char request_control, 
   1473 	   char doing_autopositioning,
   1474 	   char vc_, 
   1475 	   char need_keys,
   1476 	   char receive_all_motion,
   1477 	   char initially_hidden,
   1478 	   int argc, char **argv)
   1479 {
   1480 	int i;
   1481 	char vc=-1;
   1482 	long fgcolor;
   1483 	long bgcolor;
   1484 	Window *win = NULL;
   1485 	char force_type = -1;
   1486 
   1487 	if (!dpy || !name || !width_return || !height_return || 
   1488 	    !fgcolor_inout || !bgcolor_inout)
   1489 	{
   1490 		WARNING ("null param");
   1491 		return NULL;
   1492 	}
   1493 	/*---------------*/
   1494 	fgcolor = *fgcolor_inout;
   1495 	bgcolor = *bgcolor_inout;
   1496 
   1497         i=1;
   1498 	if (argv)
   1499         while(i < argc) {
   1500 		char *str = argv[i];
   1501                 if (!strncmp(str, "-type=",6)) {
   1502 			char *tstr = str+6;
   1503 			if (!strcmp (tstr, "app"))
   1504 				force_type = FBUI_PROGTYPE_APP;
   1505 			else if (strcmp (tstr, "launcher"))
   1506 				force_type = FBUI_PROGTYPE_LAUNCHER;
   1507 			else if (strcmp (tstr, "tool"))
   1508 				force_type = FBUI_PROGTYPE_TOOL;
   1509 			else if (strcmp (tstr, "emphemeral"))
   1510 				force_type = FBUI_PROGTYPE_EPHEMERAL;
   1511 			else if (strcmp (tstr, "none"))
   1512 				force_type = FBUI_PROGTYPE_NONE;
   1513 		}
   1514                 else if (!strncmp(str, "-geo",4)) {
   1515 			int ch = str[4];
   1516 			char *values=NULL;
   1517 			*str = 0;
   1518 			if (ch && isdigit(ch)) {
   1519 				values = str+4;
   1520 			} else {
   1521 				if (i != (argc-1)) {
   1522 					values = argv[++i];
   1523 					argv[i][0] = 0;
   1524 				}
   1525 			}
   1526 				
   1527 			if (values) {
   1528 				short w,h,xr,yr;
   1529 				if (fbui_parse_geom (values,&w,&h,&xr,&yr)) {
   1530 					width = w;
   1531 					height = h;
   1532 					if (xr != 9999) {
   1533 						xrel = xr;
   1534 						yrel = yr;
   1535 					}
   1536 				}
   1537                         }
   1538 		}
   1539 		else
   1540                 if (!strncmp (str, "-bg", 3) || !strncmp(str, "-fg",3)) {
   1541 			char *s = 3 + str;
   1542 			char which = str[1];
   1543 			char ch = *s;
   1544 			long color = -1;
   1545 			*str = 0;
   1546 			if (ch == '=')
   1547 				ch = *++s;
   1548 			if (!ch) {
   1549 				s = argv[++i];
   1550 				ch = s ? *s : 0;
   1551 			}
   1552 			if (ch == '#') {
   1553 				color = parse_rgb (s+1);
   1554 			} 
   1555 			else if (ch) {
   1556 				color = parse_colorname (s);
   1557 			}
   1558 			if (color != -1) {
   1559 				if (which == 'f')
   1560 					fgcolor = color;
   1561 				else
   1562 					bgcolor = color;
   1563 			}
   1564 			argv[i][0] = 0;
   1565 		}
   1566 		else
   1567                 if (!strncmp(str, "-c",2)) {
   1568                         char *s = 2 + str;
   1569                         if (*s && isdigit(*s)) {
   1570                                 vc = atoi(s);
   1571 				*str = 0;
   1572                         } else {
   1573 				*str = 0;
   1574                                 if (i != (argc-1)) {
   1575                                         vc = atoi(argv[++i]);
   1576 					*argv[i] = 0;
   1577                                 } else { 
   1578 					fprintf(stderr, "Usage: %s [-cCONSOLE#] [-fgCOLOR] [-bgCOLOR]\n", argv[0]); 
   1579 				}
   1580                         }
   1581                 }
   1582                 i++;
   1583         }
   1584 	if (vc_ != -1 && vc == -1)
   1585 		vc = vc_;
   1586 
   1587 	if (width > max_width)
   1588 		width = max_width;
   1589 	if (height > max_height)
   1590 		height = max_height;
   1591 
   1592 	int result;
   1593 
   1594 	oi.req_control = request_control ? 1 : 0;
   1595 	oi.x0 = xrel >= 0 ? xrel : vi.xres + xrel + 1 - width;
   1596 	oi.y0 = yrel >= 0 ? yrel : vi.yres + yrel + 1 - height;
   1597 	oi.x1= oi.x0 + width - 1;
   1598 	oi.y1= oi.y0 + height - 1;
   1599 	oi.max_width = 	max_width;
   1600 	oi.max_height = max_height;
   1601 	oi.bgcolor =	bgcolor;
   1602 	oi.initially_hidden = initially_hidden;
   1603 	*fgcolor_inout = fgcolor;
   1604 	*bgcolor_inout = bgcolor;
   1605 printf ("vc=%d\n",vc);
   1606 	oi.desired_vc =	vc;
   1607 	oi.doing_autoposition =	doing_autopositioning ? 1 : 0;
   1608 	oi.need_keys =	need_keys ? 1 : 0;
   1609 	oi.receive_all_motion =	receive_all_motion ? 1 : 0;
   1610 	oi.program_type = force_type >= 0 ? force_type : program_type;
   1611 	strncpy (oi.name, name, FBUI_NAMELEN);
   1612 	strncpy (oi.subtitle, subtitle, FBUI_NAMELEN);
   1613 	result = ioctl (dpy->fd, FBIO_UI_OPEN, &oi);
   1614 	if (result < 0)
   1615 	{
   1616 		char expr[100];
   1617 		sprintf (expr, "errcode %d\n",result);
   1618 		errlog(__FUNCTION__, expr);
   1619 		return NULL;
   1620 	}
   1621 
   1622 	win = (Window*) malloc (sizeof(Window));
   1623 	if (!win)
   1624 		FATAL ("out of memory");
   1625 	memset (win, 0, sizeof (Window));
   1626 
   1627 	win->id = result;
   1628 	win->command_ix = 2;
   1629 	win->next = dpy->list;
   1630 	dpy->list = win;
   1631 
   1632 	short w,h;
   1633 
   1634 	while (fbui_get_dims (dpy, win, &w, &h)) {
   1635 		printf ("%s: waiting for window dimensions\n", __FUNCTION__);
   1636 		sleep (1);
   1637 	}
   1638 
   1639 	*width_return = w;
   1640 	*height_return = h;
   1641 
   1642 	return win;
   1643 }
   1644 
   1645 
   1646 Font *
   1647 font_new (void)
   1648 {
   1649 	Font *nu;
   1650 	nu = (Font*) malloc(sizeof (Font));
   1651 	if (!nu)
   1652 		FATAL("out of memory")
   1653 	else
   1654 	{
   1655 		memset ((void*) nu, 0, sizeof (Font));
   1656 		nu->bitmap_buffer = NULL;
   1657 		// nu->dpi = 0;
   1658 		nu->ascent = 0;
   1659 		nu->descent = 0;
   1660 	}
   1661 	return nu;
   1662 }
   1663 
   1664 void
   1665 font_free (Font* font)
   1666 {
   1667 	int i;
   1668 	if (!font)
   1669 		return; // error
   1670 
   1671 	if (font->lefts) 
   1672 		free ((void*) font->lefts);
   1673 	if (font->widths) 
   1674 		free ((void*) font->widths);
   1675 	if (font->descents) 
   1676 		free ((void*) font->descents);
   1677 	if (font->widths) 
   1678 		free ((void*) font->widths);
   1679 	if (font->heights) 
   1680 		free ((void*) font->heights);
   1681 	if (font->bitmaps) 
   1682 		free ((void*) font->bitmaps);
   1683 
   1684 	free ((void*)font);
   1685 }
   1686 
   1687 
   1688 void 
   1689 font_char_dims (Font *font, uchar ch, short *w, short *asc, short *desc)
   1690 {
   1691 	if (!font || !w || !asc || !desc)
   1692 		return; // error
   1693 
   1694 	ch -= font->first_char;
   1695 	*w = font->widths[ch];
   1696 	*asc = font->ascent;
   1697 	*desc = font->descent;
   1698 }
   1699 
   1700 
   1701 void
   1702 font_string_dims (Font *font, unsigned char *str, short *w, short *a, short *d)
   1703 {
   1704 	if (!font || !str || !w || !a || !d)
   1705 		return; // error
   1706 
   1707 	short w0 = 0;
   1708 	int ch;
   1709 
   1710 	while ((ch = *str++)) {
   1711 		ch -= font->first_char;
   1712 		if (ch >= 0)
   1713 			w0 += font->widths [ch];
   1714 	}
   1715 
   1716 	*w = w0;
   1717 	*a = font->ascent;
   1718 	*d = font->descent;
   1719 }
   1720 
   1721 
   1722 
   1723 static uchar bit_reversal_array [256] =
   1724 {
   1725 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 
   1726 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, 
   1727 };
   1728 
   1729 
   1730 #define ZZ(a,b,c,d) ((((unsigned long)d)<<24)|(((unsigned long)c)<<16)|(((unsigned short)b)<<8)|a)
   1731 
   1732 
   1733 inline unsigned long ULONG(char endian, unsigned char* pp) 
   1734 {
   1735 	if (endian) 
   1736 		return (((unsigned long)pp[0]) << 24) | (((unsigned long)pp[1]) << 16) | (((unsigned short)pp[2]) << 8) | pp[3];
   1737 	else
   1738 		return (((unsigned long)pp[3]) << 24) | (((unsigned long)pp[2]) << 16) | (((unsigned short)pp[1]) << 8) | pp[0];
   1739 }
   1740 
   1741 
   1742 inline unsigned short USHORT(char endian, unsigned char* pp)
   1743 {
   1744 	unsigned short i;
   1745 
   1746 	if (endian) 
   1747 		i = (((unsigned short)pp[0]) << 8) | pp[1];
   1748 	else
   1749 		i = (((unsigned short)pp[1]) << 8) | pp[0];
   1750 
   1751 	return i;
   1752 }
   1753 
   1754 
   1755 enum {
   1756 	PCF_PROPS = 1,
   1757 	PCF_ACCEL = 2,
   1758 	PCF_METRICS = 4,
   1759 	PCF_BITMAPS = 8,
   1760 	PCF_INK_METRICS = 16,
   1761 	PCF_BDF_ENCODINGS = 32,
   1762 	PCF_SWIDTHS = 64,
   1763 	PCF_GLYPH_NAMES = 128,
   1764 	PCF_BDF_ACCEL = 256,
   1765 
   1766 };
   1767 
   1768 enum {
   1769 	PCF_BIG_ENDIAN = (1<<2),
   1770 	PCF_COMPRESSED = 256,	
   1771 };
   1772 
   1773 // A pcf that is "compressed" has smaller metrics info
   1774 // but the bitmap data is the same.
   1775 
   1776 
   1777 static unsigned char *read_buffer = NULL;
   1778 
   1779 char
   1780 pcf_read_encodings (Font* pcf, unsigned char* orig)
   1781 {
   1782 	unsigned char *ptr = orig;
   1783 	unsigned long format;
   1784 	char endian;
   1785 
   1786 	format = ULONG(0,ptr); ptr += 4;
   1787 	endian = (format & PCF_BIG_ENDIAN) ? true : false;
   1788 
   1789 	ptr += 2; // skip: first column
   1790 	ptr += 2; // skip: last column
   1791 
   1792 	ptr += 2; // skip: first row
   1793 	ptr += 2; // skip: last row
   1794 
   1795 	// read default char
   1796 
   1797 	unsigned short defaultChar = USHORT(endian,ptr); ptr += 2;
   1798 	unsigned short numChars = USHORT(endian,ptr); ptr += 2;
   1799 
   1800 #if 0
   1801 	printf ("pcf_read_encodings(): default char = %d, num chars = %d\n",
   1802 		pcf->first_char, numChars);
   1803 #endif
   1804 
   1805 	/* kludge */
   1806 	pcf->first_char = 31;
   1807 	pcf->last_char = 255;
   1808 
   1809 	return true;
   1810 }
   1811 
   1812 
   1813 char
   1814 pcf_read_bitmaps (Font* pcf, unsigned char* orig)
   1815 {
   1816 	unsigned char *ptr = orig;
   1817 	unsigned long format;
   1818 	char endian;
   1819 	char compressed;
   1820 	unsigned long nChars;
   1821 	int i, j;
   1822 	unsigned char *offsets;
   1823 
   1824 	format = ULONG(0,ptr); ptr += 4;
   1825 	endian = (format & PCF_BIG_ENDIAN) ? true : false;
   1826 	compressed = (format & PCF_COMPRESSED) ? true : false;
   1827 
   1828 	int storage_unit = (format >> 4) & 3;
   1829 	int row_unit = format & 3;
   1830 	int bit_order = format & 8;
   1831 
   1832 	nChars = ULONG(endian,ptr); ptr += 4;
   1833 	if (pcf->nchars)
   1834 	{
   1835 		if (pcf->nchars != nChars)
   1836 			FATAL ("#metrics != #chars");
   1837 	}
   1838 	else
   1839 	{
   1840 		pcf->nchars = nChars;
   1841 	}
   1842 
   1843 	offsets = ptr;
   1844 	ptr += 4 * nChars;
   1845 
   1846 	unsigned char *ptr2 = ptr + 4 * (3 & format);
   1847 	unsigned long data_size = ULONG(endian,ptr2);
   1848 
   1849 	ptr += 16;
   1850 
   1851 	pcf->bitmap_buffer = malloc (data_size);
   1852 	if (!pcf->widths)
   1853 	{
   1854 		pcf->lefts = malloc (nChars);
   1855 		pcf->widths = malloc (nChars);
   1856 		pcf->bitwidths = malloc (nChars);
   1857 		pcf->descents = malloc (nChars);
   1858 		pcf->heights = malloc (nChars);
   1859 
   1860 		if (!pcf->lefts || !pcf->heights)
   1861 			FATAL ("out of memory");
   1862 	}
   1863 
   1864 	pcf->bitmaps = malloc (nChars * sizeof(char*));
   1865 
   1866 	if (!pcf->bitmap_buffer || !pcf->lefts || !pcf->widths || !pcf->heights 
   1867 	    || !pcf->bitmaps)
   1868 		FATAL ("unable to allocate font data");
   1869 
   1870 	// Copy over bitmap data.
   1871 	for (i=0; i < data_size; i++)
   1872 	{
   1873 		pcf->bitmap_buffer[i] = ptr[i];
   1874 	}
   1875 
   1876 	// Need to ensure that the leftmost font bit is bit 7.
   1877 	//
   1878 	if (!bit_order)
   1879 	{
   1880 		unsigned char *p = pcf->bitmap_buffer;
   1881 		i = data_size;
   1882 		while (i--) {
   1883 			*p++ = bit_reversal_array[*p];
   1884 		}
   1885 	}
   1886 
   1887 	// Need to re-order the bytes to make them
   1888 	// little-endian, if they were written in big-endian format.
   1889 	//
   1890 	unsigned char *p;
   1891 	switch (row_unit) {
   1892 	default:
   1893 	case 0: // row = 1 byte
   1894 		break;
   1895 
   1896 	case 1: // row = 1 short
   1897 		if (storage_unit == 0 && endian) {
   1898 			unsigned char *p = pcf->bitmap_buffer;
   1899 			i = nChars / 2;
   1900 			while (i)
   1901 			{
   1902 				int tmp = *p;
   1903 				*p = *(p+1);
   1904 				*++p = tmp;
   1905 				i--;
   1906 			}
   1907 		}
   1908 		break;
   1909 
   1910 	case 2: // row = 1 long
   1911 		if (endian) {
   1912 			switch (storage_unit) {
   1913 			case 0:
   1914 				p = pcf->bitmap_buffer;
   1915 				i = nChars / 4;
   1916 				while (i)
   1917 				{
   1918 					int tmp = *p;
   1919 					*p = *(p+3);
   1920 					*(p+3) = tmp;
   1921 
   1922 					p++;
   1923 					tmp = *p;
   1924 					*p = *(p+1);
   1925 					*(p+1) = tmp;
   1926 
   1927 					p += 3;
   1928 
   1929 					i--;
   1930 				}
   1931 				break;
   1932 			case 1:
   1933 				p = pcf->bitmap_buffer;
   1934 				i = nChars / 4;
   1935 				while (i)
   1936 				{
   1937 					int tmp = *p;
   1938 					int tmp2 = *(p+1);
   1939 					*p = *(p+2);
   1940 					*(p+1) = *(p+3);
   1941 					*(p+2) = tmp;
   1942 					*(p+3) = tmp2;
   1943 
   1944 					p += 4;
   1945 
   1946 					i--;
   1947 				}
   1948 				break;
   1949 			default:
   1950 				break;
   1951 			}
   1952 		}
   1953 		break;
   1954 	}
   1955 
   1956 	// Now generate pointers for character data.
   1957 	//
   1958 	j = 8 << row_unit;
   1959 
   1960 	for (i=0; i < nChars; i++)
   1961 	{
   1962 		unsigned long offset = ULONG(endian,offsets); offsets += 4;
   1963 		pcf->bitmaps [i] = pcf->bitmap_buffer + offset;
   1964 		pcf->bitwidths [i] = j;
   1965 	}
   1966 
   1967 	return true;
   1968 }
   1969 
   1970 
   1971 char
   1972 pcf_read_metrics (Font* pcf, unsigned char* orig)
   1973 {
   1974 	unsigned char *ptr = orig;
   1975 	unsigned long format;
   1976 	char endian;
   1977 	char compressed;
   1978 	unsigned long nMetrics;
   1979 	int i;
   1980 
   1981 	format = ULONG(0,ptr); ptr += 4;
   1982 	endian = (format & PCF_BIG_ENDIAN) ? true : false;
   1983 	compressed = (format & PCF_COMPRESSED) ? true : false;
   1984 
   1985 	if (compressed)
   1986 	{
   1987 		nMetrics = USHORT(endian,ptr);
   1988 		ptr += 2;
   1989 	} 
   1990 	else
   1991 	{
   1992 		nMetrics = ULONG(endian,ptr);
   1993 		ptr += 4;
   1994 	}
   1995 
   1996 	if (!pcf->nchars && !pcf->widths)
   1997 	{
   1998 		pcf->lefts = malloc (nMetrics);
   1999 		pcf->widths = malloc (nMetrics);
   2000 		pcf->bitwidths = malloc (nMetrics);
   2001 		pcf->descents = malloc (nMetrics);
   2002 		pcf->heights = malloc (nMetrics);
   2003 
   2004 		if (!pcf->lefts || !pcf->heights)
   2005 			FATAL ("out of memory");
   2006 	}
   2007 
   2008 	if (compressed)
   2009 	{
   2010 		for (i=0; i < nMetrics; i++)
   2011 		{
   2012 			pcf->lefts[i] = ((short)*ptr++) - 0x80; 
   2013 			ptr++; // skip right-bearing
   2014 			pcf->widths[i] = ((short)*ptr++) - 0x80;
   2015 			pcf->heights [i] = ((short)*ptr++) - 0x80; // get ascent
   2016 			pcf->descents[i] = ((short)*ptr++) - 0x80;
   2017 			pcf->heights [i] += pcf->descents[i]; // height=ascent+descent
   2018 			// There is no attr byte in compressed version.
   2019 
   2020 			pcf->bitwidths[i] = pcf->widths[i];
   2021 
   2022 #if 0
   2023 printf ("char %c(%d): w=%d ht=%d desc=%d\n", i+32,i+32, pcf->widths[i], pcf->heights[i], pcf->descents[i]);
   2024 #endif
   2025 		}
   2026 	}
   2027 	else
   2028 	{
   2029 		for (i=0; i < nMetrics; i++)
   2030 		{
   2031 			pcf->lefts [i] = USHORT (endian,ptr); ptr += 2;
   2032 			ptr += 2;
   2033 			pcf->widths[i] = USHORT (endian,ptr); ptr += 2;
   2034 			pcf->heights [i] = USHORT (endian,ptr); ptr += 2;
   2035 			pcf->descents[i] = USHORT (endian,ptr); ptr += 2;
   2036 			ptr += 2; // skip attr word
   2037 
   2038 			pcf->bitwidths[i] = pcf->widths[i];
   2039 		}
   2040 	}
   2041 
   2042 	return true;
   2043 }
   2044 
   2045 char
   2046 pcf_read_accelerator (Font* pcf, unsigned char* orig)
   2047 {
   2048 	unsigned char *ptr = orig;
   2049 	unsigned long format;
   2050 	char endian;
   2051 	int i;
   2052 
   2053 	format = ULONG(0,ptr); ptr += 4;
   2054 	endian= (format & PCF_BIG_ENDIAN) ? 1 : 0;
   2055 
   2056 	ptr += 8;
   2057 
   2058 	pcf->ascent = ULONG(endian,ptr); ptr += 4;
   2059 	pcf->descent = ULONG(endian,ptr); ptr += 4;
   2060 
   2061 // printf ("ascent = %u , descent = %d\n", ascent, descent);
   2062 
   2063 	return true;
   2064 }
   2065 
   2066 
   2067 
   2068 char
   2069 pcf_read_properties (Font* pcf, unsigned char* orig)
   2070 {
   2071 	unsigned char *ptr = orig;
   2072 	unsigned long format, nprops;
   2073 	char endian;
   2074 	int i;
   2075 
   2076 	format = ULONG(0,ptr); ptr += 4;
   2077 	endian = (format & PCF_BIG_ENDIAN) ? 1 : 0;
   2078 	nprops = ULONG(endian,ptr); ptr += 4;
   2079 
   2080 	unsigned char* str_buffer = ptr + nprops*9 + 4;
   2081 
   2082 // printf ("format=%08lx\n", format);
   2083 // printf ("nprops=%08lx\n", nprops);
   2084 
   2085 	i = ((unsigned long)str_buffer) & 3;
   2086 	if (i) str_buffer += (4-i);
   2087 
   2088 	for (i = 0; i < nprops; i++)
   2089 	{
   2090 		unsigned long name = ULONG(endian,ptr); ptr += 4;
   2091 		unsigned char is_string = *ptr++;
   2092 		unsigned long value = ULONG(endian,ptr); ptr += 4;
   2093 
   2094 		char *str = ((char*)str_buffer) + name;
   2095 		if (is_string)
   2096 		{
   2097 			char *str2 = ((char*)str_buffer) + value;
   2098 
   2099 			switch (*str) {
   2100 
   2101 			case 'F':
   2102 
   2103 			if (!strcmp ("FAMILY_NAME", str)) 
   2104 			{
   2105 //printf ("family-name=%s\n", str2);
   2106 #if 0
   2107 				if (strlen (str2) < 63)
   2108 					strcpy (pcf->family, str2);
   2109 				else
   2110 					strncpy (pcf->family, str2, 63);
   2111 #endif
   2112 			} 
   2113 			else
   2114 			if (!strcmp ("FULL_NAME", str)) 
   2115 			{
   2116 //printf ("full-name=%s\n", str2);
   2117 #if 0
   2118 				if (strlen (str2) < 63)
   2119 					strcpy (pcf->fullname, str2);
   2120 				else
   2121 					strncpy (pcf->fullname, str2, 63);
   2122 #endif
   2123 			} 
   2124 			break;
   2125 
   2126 			case 'C':
   2127 
   2128 			if (!strcmp ("CHARSET_REGISTRY", str)) 
   2129 			{
   2130 // printf ("charset registry=%s\n", str2);
   2131 #if 0
   2132 				if (strcmp ("ISO8859", str2))
   2133 					return false;
   2134 #endif
   2135 			}
   2136 			break;
   2137 
   2138 			case 'S':
   2139 
   2140 			if (!strcmp ("SLANT", str)) 
   2141 			{
   2142 //printf ("slant=%s\n", str2);
   2143 #if 0
   2144 				char angle=*str2;
   2145 				if (angle=='R')
   2146 					pcf->italic=0;
   2147 				else
   2148 					pcf->italic=1;
   2149 #endif
   2150 			} 
   2151 			break;
   2152 			
   2153 			case 'W':
   2154 
   2155 			if (!strcmp ("WEIGHT_NAME", str)) 
   2156 			{
   2157 //prf ("weight-name=%s\n", str2);
   2158 #if 0
   2159 				if (!strcmp(str2, "Bold")) {
   2160 					pcf->weight = FONT_WEIGHT_BOLD;
   2161 				}
   2162 				else
   2163 				if (!strcmp(str2, "Medium")) {
   2164 					pcf->weight = FONT_WEIGHT_MEDIUM;
   2165 				}
   2166 				else
   2167 					pcf->weight = FONT_WEIGHT_MEDIUM;
   2168 #endif
   2169 			}
   2170 			break;
   2171 			
   2172 			default:
   2173 				break;
   2174 
   2175 			//printf ("\tunused property name(%ld) %s value(%ld) %s\n",
   2176 			 //	name, str, value, str2);
   2177 			}
   2178 		}
   2179 		else
   2180 		{
   2181 			switch (*str) {
   2182 
   2183 			case 'P':
   2184 
   2185 			if (!strcmp ("POINT_SIZE", str)) 
   2186 			{
   2187 //printf ("point size=%lu\n", value);
   2188 #if 0
   2189 				double sz = value;
   2190 				pcf->size = sz / 10.0;
   2191 #endif
   2192 			}
   2193 			break;
   2194 
   2195 			case 'R':
   2196 
   2197 			if (!strcmp ("RESOLUTION_X", str)) 
   2198 			{
   2199 //printf ("resolution x=%lu\n", value);
   2200 #if 0
   2201 				pcf->dpi = value;
   2202 #endif
   2203 			} 
   2204 			break;
   2205 
   2206 			case 'C':
   2207 
   2208 			// We're using only iso8859-1 fonts.
   2209 			//
   2210 			if (!strcmp ("CHARSET_ENCODING", str))
   2211 			{
   2212 // printf ("encoding=%d\n", value);
   2213 				if (value != 1)
   2214 					return false;
   2215 			}
   2216 			default:
   2217 				break;
   2218 
   2219 			// printf ("\tunused property name %s value %lu\n", str, value);
   2220 			}
   2221 		}
   2222 	}
   2223 	return true;
   2224 }
   2225 
   2226 
   2227 char
   2228 pcf_read (Font* pcf, char *path)
   2229 {
   2230 	int i;
   2231 	FILE *f;
   2232 	static char *line;
   2233 	char *param;
   2234 	char *param_end;
   2235 	short param_length;
   2236 	unsigned char *us;
   2237 	char *s;
   2238 	char *s2;
   2239 	char *s3;
   2240 	int char_num = 0;
   2241 	static char got_start = false;
   2242 	static char got_encoding = false;
   2243 	static char got_end = false;
   2244 	static char got_bitmap = false;
   2245 	struct stat statbuf;
   2246 	char path2[PATH_MAX];
   2247 
   2248 	if (*path != '/') {
   2249 		char *dir = getenv("PCFFONTDIR");
   2250 		if (dir) {
   2251 			strcpy (path2, dir);
   2252 			if ('/' != dir[strlen(dir)-1])
   2253 				strcat (path2, "/");
   2254 		} else
   2255 			sprintf (path2, "/usr/X11R6/lib/fonts/%d%s", dpi, "dpi/");
   2256 
   2257 		strcat (path2, path);
   2258 	}
   2259 	else
   2260 		strcpy (path2, path);
   2261 
   2262 // printf ("path='%s'\n", path2);
   2263 	if (stat (path2, &statbuf))
   2264 		return false;
   2265 
   2266 	unsigned long size = statbuf.st_size;
   2267 
   2268 #if 0
   2269 	pcf->fullname[0]=0;
   2270 	pcf->family[0]=0;
   2271 #endif
   2272 
   2273 	f = fopen (path2, "rb");
   2274 	if (!f)
   2275 		return false;
   2276 
   2277         read_buffer = malloc (size);
   2278         if (!read_buffer)
   2279 		FATAL ("unable to allocate font read buffer!");
   2280         i = fread (read_buffer,1,size,f);
   2281         if (i != size)
   2282 		FATAL ("cannot read entire font file");
   2283         fclose (f);
   2284         f = NULL;
   2285         uchar *ptr = read_buffer;
   2286 
   2287 	// Read the TOC
   2288 	unsigned long toc_type;
   2289 	unsigned long toc_total;
   2290 
   2291 	toc_type = ULONG(0,ptr); ptr += 4; 
   2292 	toc_total = ULONG(0,ptr); ptr += 4;
   2293 	if (toc_type != ZZ(1, 'f','c','p'))
   2294 		FATAL ("pcf file has bad header");
   2295 
   2296 	for (i=0; i < toc_total; i++)
   2297 	{
   2298 		unsigned long j;
   2299 		unsigned short type;
   2300 		unsigned char *table;
   2301 
   2302 // printf ("toc entry %d:\n", i);
   2303 		
   2304 		type = ULONG(0,ptr); ptr += 4;
   2305 //		printf ("  type=%u, ", type);
   2306 
   2307 		j = ULONG(0,ptr); ptr += 4;
   2308 		// printf (" format=%lu, ", j);
   2309 
   2310 		j = ULONG(0,ptr); ptr += 4;
   2311 		// printf (" size=%lu, ", j);
   2312 
   2313 		j = ULONG(0,ptr); ptr += 4;
   2314    //		printf (" offset=%lu\n", j);
   2315 
   2316 		table = read_buffer + j;
   2317 
   2318 		switch (type)
   2319 		{
   2320 		case PCF_PROPS:
   2321 			if (!pcf_read_properties (pcf, table))
   2322 				return false;
   2323 			break;
   2324 
   2325 		case PCF_BDF_ENCODINGS :
   2326 			if (!pcf_read_encodings (pcf, table))
   2327 				return false;
   2328 			break;
   2329 
   2330 		case PCF_ACCEL:
   2331 			if (!pcf_read_accelerator (pcf, table))
   2332 				return false;
   2333 			break;
   2334 
   2335 		case PCF_METRICS:
   2336 			if (!pcf_read_metrics (pcf, table))
   2337 				return false;
   2338 			break;
   2339 
   2340 		case PCF_BITMAPS:
   2341 			if (!pcf_read_bitmaps (pcf, table))
   2342 				return false;
   2343 			break;
   2344 
   2345 		default:
   2346 			;
   2347 		}
   2348 	}
   2349 
   2350 	if (read_buffer)
   2351 	{
   2352 		free (read_buffer);
   2353 		read_buffer = NULL;
   2354 	}
   2355 
   2356 	return true;
   2357 }
   2358 
   2359 
   2360 char *fbui_get_event_name (int type)
   2361 {
   2362 	char *s="(unknown)";
   2363 	switch (type) {
   2364 	case FBUI_EVENT_NONE: s="(none)"; break;
   2365 	case FBUI_EVENT_EXPOSE: s="Expose"; break;
   2366 	case FBUI_EVENT_HIDE: s="Hide"; break;
   2367 	case FBUI_EVENT_UNHIDE: s="Unhide"; break;
   2368 	case FBUI_EVENT_ENTER: s="Enter"; break;
   2369 	case FBUI_EVENT_LEAVE: s="Leave"; break;
   2370 	case FBUI_EVENT_KEY: s="Key"; break;
   2371 	case FBUI_EVENT_MOVE_RESIZE: s="MoveResize"; break;
   2372 	case FBUI_EVENT_ACCEL: s="Accel"; break;
   2373 	case FBUI_EVENT_WINCHANGE: s="WinChange"; break;
   2374 	case FBUI_EVENT_MOTION: s="Motion"; break;
   2375 	case FBUI_EVENT_BUTTON: s="Button"; break;
   2376 	}
   2377 	return s;
   2378 }
   2379 
   2380 
   2381 void fbui_print_error (int value)
   2382 {
   2383 	printf ("FBUI error: %s\n", fbui_error_name(value));
   2384 }
   2385 
   2386 char *fbui_error_name (int value)
   2387 {
   2388 	char *s = "(none)";
   2389 
   2390 	if (value >= 0)
   2391 		value = -value;
   2392 
   2393 	switch (value) {
   2394 	case FBUI_ERR_BADADDR: s = "bad address"; break;
   2395 	case FBUI_ERR_NULLPTR: s = "null pointer"; break;
   2396 	case FBUI_ERR_OFFSCREEN: s = "offscreen"; break;
   2397 	case FBUI_ERR_NOTRUNNING: s = "not running"; break;
   2398 	case FBUI_ERR_WRONGVISUAL: s = "wrong visual"; break;
   2399 	case FBUI_ERR_NOTPLACED: s = "not placed"; break;
   2400 	case FBUI_ERR_BIGENDIAN: s = "big endian"; break;
   2401 	case FBUI_ERR_INVALIDCMD: s = "invalid command"; break;
   2402 	case FBUI_ERR_BADPID: s = "bad process id"; break;
   2403 	case FBUI_ERR_ACCELBUSY: s = "accelerator key in use"; break;
   2404 	case FBUI_ERR_NOFONT: s = "no font"; break;
   2405 	case FBUI_ERR_NOMEM: s = "out of memory"; break;
   2406 	case FBUI_ERR_NOTOPEN: s = "not open"; break;
   2407 	case FBUI_ERR_OVERLAP: s = "window overlap"; break;
   2408 	case FBUI_ERR_ALREADYOPEN: s = "already open"; break;
   2409 	case FBUI_ERR_MISSINGWIN: s = "missing window"; break;
   2410 	case FBUI_ERR_NOTWM: s = "not a window manager"; break;
   2411 	case FBUI_ERR_WRONGWM: s = "wrong window manager"; break;
   2412 	case FBUI_ERR_HAVEWM: s = "already have window manager"; break;
   2413 	case FBUI_ERR_KEYFOCUSDENIED: s = "key focus request denied"; break;
   2414 	case FBUI_ERR_KEYFOCUSERR: s = "key focus error"; break;
   2415 	case FBUI_ERR_BADPARAM: s = "bad parameter"; break;
   2416 	case FBUI_ERR_NOMOUSE: s = "no mouse"; break;
   2417 	case FBUI_ERR_MOUSEREAD: s = "mouse read error"; break;
   2418 	case FBUI_ERR_OVERLARGECUT: s = "overlarge cut"; break;
   2419 	case FBUI_ERR_BADWIN: s = "bad window"; break;
   2420 	case FBUI_ERR_PASTEFAIL: s = "paste failed"; break;
   2421 	case FBUI_ERR_CUTFAIL: s = "cut failed"; break;
   2422 	case FBUI_ERR_NOEVENT: s = "no events"; break;
   2423 	case FBUI_ERR_DRAWING: s = "busy drawing"; break;
   2424 	case FBUI_ERR_MISSINGPROCENT: s = "missing process entry"; break;
   2425 	case FBUI_ERR_BADVC: s = "bad virtual console number"; break;
   2426 	}
   2427 	return s;
   2428 }

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.