#ifndef xlesses_header #define xlesses_header #include #include #include #include #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