234 lines
9.8 KiB
C
Executable File
234 lines
9.8 KiB
C
Executable File
#ifndef xlesses_header
|
|
#define xlesses_header
|
|
|
|
#include <xolatile/xtandard.h>
|
|
|
|
#include <xcb/xcb.h>
|
|
#include <xcb/xcb_atom.h>
|
|
#include <xcb/xcb_image.h>
|
|
|
|
#define xlesses_font_width (8)
|
|
#define xlesses_font_height (8)
|
|
#define xlesses_font_tabulator (4)
|
|
/*
|
|
static void (* xlesses_action [signal_count]) (void) = { null };
|
|
*/
|
|
static xcb_connection_t * xlesses_connection = null;
|
|
static xcb_screen_t * xlesses_screen = null;
|
|
static xcb_window_t xlesses_window = 0;
|
|
static xcb_gcontext_t xlesses_context = 0;
|
|
static xcb_pixmap_t xlesses_pixmap = 0;
|
|
static xcb_image_t * xlesses_image = null;
|
|
|
|
static int xlesses_active = false;
|
|
static int xlesses_window_width = 0;
|
|
static int xlesses_window_height = 0;
|
|
static int xlesses_cursor_x = 0;
|
|
static int xlesses_cursor_y = 0;
|
|
static int xlesses_signal = 0;
|
|
static int * xlesses_framebuffer = null;
|
|
|
|
static void xlesses (void) {
|
|
xlesses_framebuffer = deallocate (xlesses_framebuffer);
|
|
|
|
xcb_free_gc (xlesses_connection, xlesses_context);
|
|
xcb_free_pixmap (xlesses_connection, xlesses_pixmap);
|
|
xcb_destroy_window (xlesses_connection, xlesses_window);
|
|
xcb_disconnect (xlesses_connection);
|
|
}
|
|
|
|
static int xlesses_screen_length (void) {
|
|
return (xlesses_window_width * xlesses_window_height * (int) sizeof (* xlesses_framebuffer));
|
|
}
|
|
|
|
static void xlesses_configure (int width, int height, char * title) {
|
|
unsigned int window_flags [2];
|
|
|
|
if (xlesses_active == true) {
|
|
return;
|
|
} else {
|
|
clean_up (xlesses);
|
|
}
|
|
|
|
xlesses_window_width = width;
|
|
xlesses_window_height = height;
|
|
|
|
xlesses_connection = xcb_connect (null, null);
|
|
|
|
xlesses_screen = xcb_setup_roots_iterator (xcb_get_setup (xlesses_connection)).data;
|
|
|
|
xlesses_window = xcb_generate_id (xlesses_connection);
|
|
xlesses_context = xcb_generate_id (xlesses_connection);
|
|
xlesses_pixmap = xcb_generate_id (xlesses_connection);
|
|
|
|
window_flags [0] = xlesses_screen->black_pixel;
|
|
window_flags [1] = XCB_EVENT_MASK_NO_EVENT |
|
|
XCB_EVENT_MASK_EXPOSURE |
|
|
XCB_EVENT_MASK_RESIZE_REDIRECT |
|
|
XCB_EVENT_MASK_KEY_RELEASE |
|
|
XCB_EVENT_MASK_KEY_PRESS |
|
|
XCB_EVENT_MASK_BUTTON_RELEASE |
|
|
XCB_EVENT_MASK_BUTTON_PRESS;
|
|
|
|
xcb_create_window (xlesses_connection, xlesses_screen->root_depth, xlesses_window, xlesses_screen->root, 0, 0,
|
|
(unsigned short int) width, (unsigned short int) height, 10, XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
|
xlesses_screen->root_visual, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, window_flags);
|
|
|
|
xcb_map_window (xlesses_connection, xlesses_window);
|
|
|
|
xcb_change_property (xlesses_connection, XCB_PROP_MODE_REPLACE, xlesses_window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
|
|
string_length (title), title);
|
|
|
|
xcb_create_pixmap (xlesses_connection, xlesses_screen->root_depth, xlesses_pixmap, xlesses_window, (unsigned short int) width,
|
|
(unsigned short int) height);
|
|
|
|
xcb_create_gc (xlesses_connection, xlesses_context, xlesses_pixmap, 0, null);
|
|
|
|
xcb_flush (xlesses_connection);
|
|
|
|
xlesses_framebuffer = allocate (xlesses_screen_length ());
|
|
|
|
xlesses_active = true;
|
|
}
|
|
|
|
static void xlesses_synchronize (void) {
|
|
xcb_generic_event_t * generic_event;
|
|
|
|
if (xlesses_active == false) {
|
|
return;
|
|
}
|
|
|
|
generic_event = xcb_wait_for_event (xlesses_connection);
|
|
|
|
switch (generic_event->response_type & 127) {
|
|
case XCB_EXPOSE: {
|
|
xcb_flush (xlesses_connection);
|
|
} break;
|
|
case XCB_KEY_PRESS: {
|
|
xlesses_signal = (int) ((xcb_key_press_event_t *) generic_event)->detail;
|
|
if (xlesses_signal == 24) {
|
|
xlesses_active = false;
|
|
}
|
|
} break;
|
|
default: {
|
|
} break;
|
|
}
|
|
|
|
generic_event = deallocate (generic_event);
|
|
|
|
xlesses_image = xcb_image_create_native (xlesses_connection, xlesses_window_width, xlesses_window_height, XCB_IMAGE_FORMAT_Z_PIXMAP,
|
|
xlesses_screen->root_depth, xlesses_framebuffer, (unsigned int) (xlesses_screen_length ()),
|
|
(unsigned char *) xlesses_framebuffer);
|
|
|
|
xcb_image_put (xlesses_connection, xlesses_pixmap, xlesses_context, xlesses_image, 0, 0, 0);
|
|
|
|
xcb_image_destroy (xlesses_image);
|
|
|
|
xcb_copy_area (xlesses_connection, xlesses_pixmap, xlesses_window, xlesses_context, 0, 0, 0, 0, xlesses_window_width,
|
|
xlesses_window_height);
|
|
|
|
xlesses_framebuffer = allocate (xlesses_screen_length ());
|
|
}
|
|
|
|
static void xlesses_render_background_colour (int colour) {
|
|
int x, y;
|
|
|
|
if ((xlesses_framebuffer == null) || (xlesses_active == false)) {
|
|
return;
|
|
}
|
|
|
|
for (y = 0; y != xlesses_window_height; ++y) {
|
|
for (x = 0; x != xlesses_window_width; ++x) {
|
|
xlesses_framebuffer [y * xlesses_window_width + x] = 0xff000000 | colour;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void xlesses_render_sprite (unsigned int * sprite, int width, int height, int x, int y) {
|
|
int offset_x, offset_y;
|
|
|
|
if ((xlesses_framebuffer == null) || (xlesses_active == false)) {
|
|
return;
|
|
}
|
|
|
|
for (offset_y = 0; offset_y != height; ++offset_y) {
|
|
for (offset_x = 0; offset_x != width; ++offset_x) {
|
|
xlesses_framebuffer [(y + offset_y) * xlesses_window_width + (x + offset_x)] = sprite [offset_y * width + offset_x];
|
|
}
|
|
}
|
|
}
|
|
|
|
static void xlesses_render_character (char character, int foreground, int background, int x, int y) {
|
|
const unsigned long int font_code ['~' - ' ' + 2] = {
|
|
0x0000000000000000, 0x00180018183c3c18, 0x0000000000363636, 0x006c6cfe6cfe6c6c,
|
|
0x00187ed07c16fc30, 0x0060660c18306606, 0x00dc66b61c36361c, 0x0000000000181818,
|
|
0x0030180c0c0c1830, 0x000c18303030180c, 0x0000187e3c7e1800, 0x000018187e181800,
|
|
0x0c18180000000000, 0x000000007e000000, 0x0018180000000000, 0x0000060c18306000,
|
|
0x003c666e7e76663c, 0x007e181818181c18, 0x007e0c183060663c, 0x003c66603860663c,
|
|
0x0030307e363c3830, 0x003c6660603e067e, 0x003c66663e060c38, 0x000c0c0c1830607e,
|
|
0x003c66663c66663c, 0x001c30607c66663c, 0x0018180018180000, 0x0c18180018180000,
|
|
0x0030180c060c1830, 0x0000007e007e0000, 0x000c18306030180c, 0x001800181830663c,
|
|
0x003c06765676663c, 0x006666667e66663c, 0x003e66663e66663e, 0x003c66060606663c,
|
|
0x001e36666666361e, 0x007e06063e06067e, 0x000606063e06067e, 0x003c66667606663c,
|
|
0x006666667e666666, 0x007e18181818187e, 0x001c36303030307c, 0x0066361e0e1e3666,
|
|
0x007e060606060606, 0x00c6c6d6d6feeec6, 0x006666767e6e6666, 0x003c66666666663c,
|
|
0x000606063e66663e, 0x006c36566666663c, 0x006666363e66663e, 0x003c66603c06663c,
|
|
0x001818181818187e, 0x003c666666666666, 0x00183c6666666666, 0x00c6eefed6d6c6c6,
|
|
0x0066663c183c6666, 0x001818183c666666, 0x007e060c1830607e, 0x003e06060606063e,
|
|
0x00006030180c0600, 0x007c60606060607c, 0x000000000000663c, 0xffff000000000000,
|
|
0x000000000030180c, 0x007c667c603c0000, 0x003e6666663e0606, 0x003c6606663c0000,
|
|
0x007c6666667c6060, 0x003c067e663c0000, 0x000c0c0c3e0c0c38, 0x3c607c66667c0000,
|
|
0x00666666663e0606, 0x003c1818181c0018, 0x0e181818181c0018, 0x0066361e36660606,
|
|
0x003c18181818181c, 0x00c6d6d6fe6c0000, 0x00666666663e0000, 0x003c6666663c0000,
|
|
0x06063e66663e0000, 0xe0607c66667c0000, 0x000606066e360000, 0x003e603c067c0000,
|
|
0x00380c0c0c3e0c0c, 0x007c666666660000, 0x00183c6666660000, 0x006cfed6d6c60000,
|
|
0x00663c183c660000, 0x3c607c6666660000, 0x007e0c18307e0000, 0x003018180e181830,
|
|
0x0018181818181818, 0x000c18187018180c, 0x000000000062d68c, 0x0000000000000000
|
|
};
|
|
|
|
int offset;
|
|
|
|
fatal_failure (xlesses_active == false, "xlesses_render_character: Library is not active.");
|
|
fatal_failure (xlesses_framebuffer == null, "xlesses_render_character: Framebuffer was not allocated.");
|
|
|
|
if ((x < 0) || (x > xlesses_window_width - xlesses_font_width - 1)
|
|
|| (y < 0) || (y > xlesses_window_height - xlesses_font_height - 1)) {
|
|
return;
|
|
}
|
|
|
|
for (offset = 0; offset != xlesses_font_width * xlesses_font_height; ++offset) {
|
|
int u = offset / xlesses_font_width + y;
|
|
int v = offset % xlesses_font_width + x;
|
|
|
|
int code = (font_code [(int) (character - ' ')] >> offset) & 1;
|
|
|
|
xlesses_framebuffer [u * (xlesses_window_width) + v] = (code) ? foreground : background;
|
|
}
|
|
}
|
|
|
|
static void xlesses_render_string (char * string, int foreground, int background, int x, int y) {
|
|
int index;
|
|
|
|
for (index = 0; string [index] != '\0'; ++index) {
|
|
xlesses_render_character (string [index], foreground, background, x + index * xlesses_font_width, y);
|
|
}
|
|
}
|
|
|
|
static void xlesses_render_number (int number, int foreground, int background, int x, int y) {
|
|
xlesses_render_string (number_to_string (number), foreground, background, x, y);
|
|
}
|
|
|
|
static void xlesses_render_string_crop (char * string, int foreground, int background, int x, int y, int crop) {
|
|
int index;
|
|
|
|
for (index = 0; (string [index] != '\0') && (crop < index * xlesses_font_width); ++index) {
|
|
xlesses_render_character (string [index], foreground, background, x + index * xlesses_font_width, y);
|
|
}
|
|
}
|
|
|
|
static void xlesses_render_number_crop (int number, int foreground, int background, int x, int y, int crop) {
|
|
xlesses_render_string_crop (number_to_string (number), foreground, background, x, y, crop);
|
|
}
|
|
|
|
#endif
|