xolatilization/xenu.h

250 lines
9.3 KiB
C

/// __ _____ _ __ _ _
/// \ \/ / _ \ '_ \| | | |
/// > < __/ | | | |_| |
/// /_/\_\___|_| |_|\__,_|
///
/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
///
/// xolatile@chud.cyou - xenu - Tiny menu unity header, depending on Xross and XUI headers, hard to use but efficient.
///
/// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU
/// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish...
///
/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
/// for more details, if you dare, it is a lot of text that nobody wants to read...
typedef enum {
menu_layout_vertical, menu_layout_horizontal,
menu_layout_count
} menu_layout_enumeration;
typedef enum {
menu_type_empty,
menu_type_window, menu_type_menu, menu_type_status, menu_type_frame,
menu_type_button, menu_type_separator, menu_type_string, menu_type_sprite,
menu_type_check_box, menu_type_icon, menu_type_overicon, menu_type_ubericon,
menu_type_text_field, menu_type_signal_field, menu_type_cursor_field, menu_type_slider_field,
menu_type_text_box, menu_type_code_box, menu_type_help_box, menu_type_data_box,
menu_type_count
} menu_type_enumeration;
typedef struct {
character * data;
natural font;
real scale;
natural colour;
} menu_string;
typedef struct {
natural data;
real scale;
natural colour;
} menu_sprite;
typedef struct {
menu_layout_enumeration layout;
menu_type_enumeration type;
menu_string * string;
menu_string * number;
menu_sprite * sprite;
integer x;
integer y;
natural width;
natural height;
natural offset;
natural count;
generic * * array;
generic * root;
} menu_structure;
static procedure menu_append (menu_structure * root, menu_structure * menu) {
++root->count;
root->array = reallocate (root->array, root->count * sizeof (* root->array));
menu->root = root;
root->array [root->count - 1] = menu;
}
static procedure menu_remove (menu_structure * menu) {
if (menu->string != null) { menu->string = deallocate (menu->string); }
if (menu->number != null) { menu->number = deallocate (menu->number); }
if (menu->sprite != null) { menu->sprite = deallocate (menu->sprite); }
for (natural index = 0; index < menu->count; ++index) {
menu_remove (menu->array [index]);
}
if (menu->array != null) {
menu->array = deallocate (menu->array);
}
menu = deallocate (menu);
}
static menu_string * menu_create_string (character * data, natural font, real scale, natural colour) {
menu_string * string = allocate (sizeof (* string));
string->data = data;
string->font = font;
string->scale = scale;
string->colour = colour;
return (string);
}
static menu_sprite * menu_create_sprite (natural data, real scale, natural colour) {
menu_sprite * sprite = allocate (sizeof (* sprite));
sprite->data = data;
sprite->scale = scale;
sprite->colour = colour;
return (sprite);
}
static menu_structure * menu_create_base (menu_layout_enumeration layout, menu_type_enumeration type, menu_string * string,
menu_string * number, menu_sprite * sprite, integer x, integer y, natural offset) {
menu_structure * menu = allocate (sizeof (* menu));
menu->layout = layout;
menu->type = type;
menu->string = string;
menu->number = number;
menu->sprite = sprite;
menu->x = x;
menu->y = y;
menu->offset = offset;
return (menu);
}
static menu_structure * menu_create_root (menu_layout_enumeration layout, menu_type_enumeration type, natural offset) {
return (menu_create_base (layout, type, null, null, null, 0, 0, offset));
}
static menu_structure * menu_create_button (menu_layout_enumeration layout, menu_string * text, menu_sprite * icon, natural offset) {
return (menu_create_base (layout, menu_type_button, text, null, icon, 0, 0, offset));
}
static natural menu_string_width (cross_structure * cross, menu_string * string) {
return ((string == null) ? 0 : cross_string_width (cross, string->data, string->font, string->scale));
}
static natural menu_string_height (cross_structure * cross, menu_string * string) {
return ((string == null) ? 0 : cross_string_height (cross, string->data, string->font, string->scale));
}
static natural menu_sprite_width (cross_structure * cross, menu_sprite * sprite) {
return ((sprite == null) ? 0 : cross_sprite_width (cross, sprite->data));
}
static natural menu_sprite_height (cross_structure * cross, menu_sprite * sprite) {
return ((sprite == null) ? 0 : cross_sprite_height (cross, sprite->data));
}
static procedure menu_configure (cross_structure * cross, menu_structure * menu) {
for (natural index = 0; index < menu->count; ++index) {
menu_structure * submenu = menu->array [index];
menu_configure (cross, submenu);
}
for (natural index = 0; index < menu->count; ++index) {
menu_structure * submenu = menu->array [index];
if (menu->layout == menu_layout_vertical) {
menu->width = maximum_macro (menu->width, submenu->width + 2 * menu->offset);
menu->height += submenu->height;
}
if (menu->layout == menu_layout_horizontal) {
menu->width += submenu->width;
menu->height = maximum_macro (menu->height, submenu->height + 2 * menu->offset);
}
}
if (menu->layout == menu_layout_vertical) {
menu->width += maximum_natural (3, menu_sprite_width (cross, menu->sprite),
menu_string_width (cross, menu->string),
menu_string_width (cross, menu->number));
menu->height += menu_sprite_height (cross, menu->sprite)
+ menu_string_height (cross, menu->string)
+ menu_string_height (cross, menu->number);
}
if (menu->layout == menu_layout_horizontal) {
menu->width += menu_sprite_width (cross, menu->sprite)
+ menu_string_width (cross, menu->string)
+ menu_string_width (cross, menu->number);
menu->height += maximum_natural (3, menu_sprite_height (cross, menu->sprite),
menu_string_height (cross, menu->string),
menu_string_height (cross, menu->number));
}
menu->width += 2 * menu->offset;
menu->height += 2 * menu->offset;
if ((menu->count != 0) && (menu->root != null)) {
menu->width -= 2 * menu->offset * (menu->layout == menu_layout_vertical);
menu->height -= 2 * menu->offset * (menu->layout == menu_layout_horizontal);
}
}
static procedure menu_center (cross_structure * cross, menu_structure * menu) {
menu->x = cross_center_x (cross, menu->width);
menu->y = cross_center_y (cross, menu->height);
}
static procedure menu_subrender (cross_structure * cross, ui_structure * ui, menu_structure * menu) {
switch (menu->type) {
case (menu_type_empty): break;
case (menu_type_window): ui_render_window (cross, ui, menu->x, menu->y, menu->width, menu->height); break;
case (menu_type_menu): ui_render_menu (cross, ui, menu->x, menu->y, menu->width, menu->height); break;
case (menu_type_status): ui_render_status (cross, ui, menu->x, menu->y, menu->width, menu->height); break;
case (menu_type_frame): ui_render_frame (cross, ui, menu->x, menu->y, menu->width, menu->height); break;
case (menu_type_button): {
boolean sprite_is_used = (menu->sprite != null) && (menu->sprite->data != ~ 0u);
ui_render_button (cross, ui, menu->x, menu->y, menu->width, menu->height);
if (sprite_is_used == true) {
cross_render_sprite_colour (cross, menu->sprite->data, menu->x + menu->offset, menu->y + menu->offset, menu->sprite->colour);
}
if ((menu->string != null) && (menu->string->data != null)) {
integer x = menu->x + menu->offset + (sprite_is_used == true) * menu_sprite_width (cross, menu->sprite) * (menu->layout == menu_layout_horizontal);
integer y = menu->y + menu->offset + (sprite_is_used == true) * menu_sprite_height (cross, menu->sprite) * (menu->layout == menu_layout_vertical);
cross_render_string (cross, menu->string->data, menu->string->font, x, y, menu->string->scale, menu->string->colour);
}
} break;
default: break;
}
}
static procedure menu_render (cross_structure * cross, ui_structure * ui, menu_structure * menu) {
menu_subrender (cross, ui, menu);
for (natural index = 0; index < menu->count; ++index) {
menu_structure * submenu = menu->array [index];
menu_structure * root = submenu->root;
submenu->x = root->x + root->offset;
submenu->y = root->y + root->offset;
for (natural subindex = 0; subindex < index; ++subindex) {
menu_structure * base = root->array [subindex];
submenu->x += (root->layout == menu_layout_horizontal) * base->width;
submenu->y += (root->layout == menu_layout_vertical) * base->height;
}
menu_render (cross, ui, submenu);
}
}