Project Overview
FGUI is a lightweight, game-oriented C++ GUI library optimized for DirectX and OpenGL applications. It delivers a minimal-overhead, header-only toolkit with runtime-configurable widgets using JSON, making it ideal for in-game overlays, tools, and modding interfaces.
Main Goals
- Lightweight: Zero external dependencies outside of your graphics API.
- Game-Oriented: Designed for low-latency, in-game overlays and utilities.
- Graphics API Friendly: Seamless integration with DirectX 9/11/12 and OpenGL.
- Configurable: Define layouts, styles, and themes via JSON files.
- Header-Only: Single
FGUI.hpp
include for all widgets and builders.
When to Choose FGUI
- You need a performant, in-game GUI with minimal footprint.
- You prefer runtime theme/layout changes without recompilation.
- You want a clean, self-contained codebase without Boost or other heavy dependencies.
- You build game hacks, overlays, trainers, or engine tools targeting DirectX/OpenGL.
Quick Start
Include the main header and create a simple window with a button:
#include "FGUI/FGUI.hpp"
using namespace fgui;
int main()
{
// Initialize your graphics (DirectX/OpenGL) here...
// Create a GUI window
window settings("Settings", { 400, 300 });
// Add a button
settings.add<widgets::button>("Apply")
.setSize({ 100, 30 })
.setPosition({ 150, 200 })
.setCallback([]() {
// handle button click
});
// Main loop
while (running)
{
// Begin frame (your renderer)
settings.draw(); // Render FGUI
// Present frame...
}
return 0;
}
Licensing
FGUI is released under the MIT License. Include the LICENSE
file in your distributions to comply with usage and attribution requirements.
Getting Started
This guide walks you through cloning the repo, configuring your build, and rendering your first FGUI window with a clickable button.
1. Clone the Repository
git clone https://github.com/otvv/fgui.git
2. Configure Your Build
CMake
Create CMakeLists.txt
in your project root:
cmake_minimum_required(VERSION 3.10)
project(FGUIApp)
# Add the FGUI library
add_subdirectory(fgui)
# Your executable
add_executable(FGUIApp main.cpp)
# Include FGUI headers and link the library
target_include_directories(FGUIApp PRIVATE ${CMAKE_SOURCE_DIR}/fgui)
target_link_libraries(FGUIApp PRIVATE fgui)
set_target_properties(FGUIApp PROPERTIES CXX_STANDARD 17)
Then:
mkdir build && cd build
cmake ..
cmake --build . --config Release
Manual (GCC/Clang)
g++ main.cpp fgui/src/*.cpp -I fgui -std=c++17 -ld3d9 -o FGUIApp
3. Minimal Win32 + Direct3D9 Example
Create main.cpp
alongside your CMakeLists.txt
or compile directly.
#include <windows.h>
#include <d3d9.h>
#include "FGUI/FGUI.hpp"
// Direct3D globals
static IDirect3D9* g_d3d = nullptr;
static IDirect3DDevice9* g_device= nullptr;
// Main FGUI window
static std::shared_ptr<FGUI::CContainer> g_Window;
// Forward declarations
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
bool InitD3D(HWND);
void CleanupD3D();
void RenderFrame();
void BindInput();
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, PSTR, int nShow) {
// Register and create a Win32 window
WNDCLASSEX wc = { sizeof(wc), CS_CLASSDC, WndProc, 0,0, hInst, nullptr, nullptr, nullptr, nullptr, "FGUIApp", nullptr };
RegisterClassEx(&wc);
HWND hwnd = CreateWindow("FGUIApp", "FGUI Demo", WS_OVERLAPPEDWINDOW,
100,100,800,600, nullptr,nullptr,wc.hInstance,nullptr);
if (!InitD3D(hwnd)) return 0;
// Bind Win32 input callbacks
BindInput();
// Configure the FGUI window
g_Window = std::make_shared<FGUI::CContainer>();
g_Window->SetTitle("Demo Window");
g_Window->SetKey(VK_INSERT);
g_Window->SetState(true);
// Add a button via the CBuilder API
FGUI::CBuilder()
.Widget(std::make_shared<FGUI::CButton>())
.Title("Click Me")
.Position(50, 60)
.Size(100, 30)
.Callback([](){
MessageBox(nullptr, "Button clicked!", "FGUI", MB_OK);
})
.SpawnIn(g_Window);
ShowWindow(hwnd, nShow);
// Main loop
MSG msg = {};
while (msg.message != WM_QUIT) {
if (PeekMessage(&msg, nullptr,0,0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
// Poll input and render
FGUI::INPUT.PullInput();
RenderFrame();
}
}
CleanupD3D();
UnregisterClass("FGUIApp", wc.hInstance);
return 0;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
if (msg == WM_DESTROY) {
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
bool InitD3D(HWND hwnd) {
g_d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (!g_d3d) return false;
D3DPRESENT_PARAMETERS pp = {};
pp.Windowed = TRUE;
pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
pp.BackBufferFormat = D3DFMT_UNKNOWN;
if (FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &pp, &g_device))) {
return false;
}
return true;
}
void CleanupD3D() {
if (g_device) g_device->Release();
if (g_d3d) g_d3d->Release();
}
void RenderFrame() {
g_device->BeginScene();
g_device->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_XRGB(30,30,30), 1.0f, 0);
// Render all widgets in the container
g_Window->Render(*g_device);
g_device->EndScene();
g_device->Present(nullptr, nullptr, nullptr, nullptr);
}
void BindInput() {
// Pull Win32 messages into FGUI
FGUI::INPUT.PullInput = [](){
MSG msg;
while (PeekMessage(&msg, nullptr,0,0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
};
// Key edge tracking
static bool prevState[256] = {};
FGUI::INPUT.IsKeyHeld = [](https://github.com/otvv/fgui/blob/master/unsigned int vk){
return (GetAsyncKeyState(vk) & 0x8000) != 0;
};
FGUI::INPUT.IsKeyPressed = [&](https://github.com/otvv/fgui/blob/master/unsigned int vk){
bool down = (GetAsyncKeyState(vk)&0x8000)!=0;
bool pressed = down && !prevState[vk];
prevState[vk] = down;
return pressed;
};
FGUI::INPUT.IsKeyReleased = [&](https://github.com/otvv/fgui/blob/master/unsigned int vk){
bool down = (GetAsyncKeyState(vk)&0x8000)!=0;
bool released = !down && prevState[vk];
prevState[vk] = down;
return released;
};
FGUI::INPUT.GetCursorPos = [](){
POINT pt; GetCursorPos(&pt);
return FGUI::POINT{pt.x, pt.y};
};
FGUI::INPUT.GetCursorPosDelta = [](){
static FGUI::POINT last{0,0};
auto cur = FGUI::INPUT.GetCursorPos();
FGUI::POINT d{cur.x - last.x, cur.y - last.y};
last = cur;
return d;
};
FGUI::INPUT.IsCursorInArea = [](https://github.com/otvv/fgui/blob/master/FGUI::AREA a){
auto p = FGUI::INPUT.GetCursorPos();
return p.x >= a.x && p.x < a.x + a.w
&& p.y >= a.y && p.y < a.y + a.h;
};
FGUI::INPUT.SetInputType(FGUI::INPUT_TYPE::WIN_32);
}
4. Verify and Run
- Build via CMake or your compiler command above.
- Run the resulting executable.
- Press INS to toggle the window, then click Click Me.
You now have a working FGUI window. Explore more widgets in FGUI/FGUI.hpp
and customize rendering/input by inspecting the internal headers.
Widgets Reference
A catalogue of all ready-made controls shipped with FGUI. Each entry includes purpose, key methods, and a quick usage snippet.
CButton Widget
Purpose
Render a clickable button with built-in hover styling and optional tooltip. Invoke a user-supplied callback when clicked.
Essential API
- Constructor
Initializes title = “Button”, size = (100×25), no font, no tooltip, no callback. - void AddCallback(std::function<void()> fn)
Register a single click handler (replaces any existing). - Geometry(status)
Draws the body (default or hovered colors) and centers the title text. - Input()
Invoked on click; calls your callback if set. - Tooltip()
If a non-empty tooltip is set and the cursor hovers, draws a styled tooltip box.
Common Configuration Methods (inherited from CWidgets)
- SetTitle(const std::string& title)
- SetSize(DIMENSION size)
- SetPosition(POINT pos)
- SetFont(FontID font)
- SetTooltip(const std::string& tip)
Code Examples
Instantiate and configure a button, then handle its click:
// assume `window` is your FGUI page or container
auto btn = window->AddWidget<FGUI::CButton>(); // create and add to UI
btn->SetTitle("Submit"); // change label
btn->SetSize({120, 30}); // wider button
btn->SetPosition({50, 100}); // x=50, y=100
btn->SetFont(myFontHandle); // previously loaded font
btn->SetTooltip("Send your data to the server"); // optional hover text
btn->AddCallback([](){
std::cout << "Submit clicked!\n";
SendFormData();
});
Handling button state in your main loop:
while (running)
{
renderer.BeginFrame();
ui.ProcessInput(); // routes mouse events into widgets
ui.UpdateWidgets(); // calls Update() on each widget
ui.RenderWidgets(); // calls Geometry(status) and Tooltip()
renderer.EndFrame();
}
Practical Guidance
- Only one callback can be registered. Calling
AddCallback
again replaces the previous handler. - To disable, subclass CButton or guard your callback logic.
- Tooltip appears only if
m_strTooltip.length() > 0
. - For custom theming, derive from CButton and override Geometry().
- Title text auto-centers; adjust m_dmSize first if you change font or title after construction.
CComboBox Widget
Purpose
Display a drop-down list of entries with optional values, allow selection, and react via callbacks.
Essential API
- void AddEntry(const std::string& name, unsigned int value = 0)
Append an entry with display string and optional custom value. - void SetIndex(std::size_t index) / std::size_t GetIndex()
Programmatically select or query the active entry (0-based). - void SetValue(std::size_t index, unsigned int value) / unsigned int GetValue()
Modify or retrieve the custom value of an entry. - void AddCallback(std::function<void()> fn)
Register a function fired whenever the user picks an entry.
Code Examples
Instantiate and populate a combo box:
auto combo = std::make_shared<FGUI::CComboBox>();
combo->SetTitle("Quality");
combo->AddEntry("Low", 1);
combo->AddEntry("Medium", 2);
combo->AddEntry("High", 3);
// Default to "Medium"
combo->SetIndex(1);
React to user selection:
combo->AddCallback([combo](){
size_t idx = combo->GetIndex();
unsigned val = combo->GetValue();
std::cout << "User picked index=" << idx
<< ", value=" << val << "\n";
});
Read the selection elsewhere:
if (combo->GetIndex() == 2) {
enableHighQualityRendering();
}
Saving and Loading State
ComboBox implements Save/Load with nlohmann::json, using the widget’s title (spaces→underscores) as the key.
// Saving
nlohmann::json cfg;
combo->Save(cfg);
// cfg["Quality"] == combo->GetIndex()
// Loading
combo->Load(cfg);
// restores combo->GetIndex() from JSON
Practical Tips
- Always call
AddEntry
before readingGetValue
/GetIndex
to avoid out-of-bounds. - Omit the
value
parameter to default it to 0 when you only care about the display string. - Use
SetIndex
to preset a default selection. - Register callbacks before entering the GUI loop for immediate handling.
- Titles must be unique within a container if you rely on Save/Load.
CColorPicker Widget
Purpose
Integrate a color-selection widget into your GUI, configure its appearance and behavior, retrieve RGBA values, and persist state via JSON.
Instantiation & Setup
#include "FGUI/widgets/colorpicker.hpp"
// ...
auto color_picker = std::make_shared<FGUI::CColorPicker>();
color_picker->SetTitle("Background Color"); // Widget label
color_picker->SetColor({255, 128, 0, 255}); // Default RGBA (orange)
color_picker->SetPixelation(4); // Granularity of the color grid
color_picker->SetRelativePosition({10.f, 10.f}); // Position inside parent container
color_picker->SetTooltip("Pick your background color");
parent_container->AddWidget(color_picker);
Runtime Interaction
- Toggling: Clicking the color swatch opens or closes the picker panel.
- Adjusting: Drag the hue bar or alpha bar; saturation/value updates in the main square.
- Retrieving:
FGUI::COLOR current = color_picker->GetColor();
// current.m_ucRed, current.m_ucGreen, current.m_ucBlue, current.m_ucAlpha
Pixelation Tuning
color_picker->SetPixelation(2); // finer grid, more rectangles drawn
color_picker->SetPixelation(8); // coarser grid, faster rendering
Persistence (Save / Load)
nlohmann::json module_json;
// Saving
color_picker->Save(module_json);
// module_json["Background_Color"] == { red, green, blue, alpha }
// Loading
if (module_json.contains("Background_Color"))
color_picker->Load(module_json);
The widget auto-formats its title (spaces→underscores) as the JSON key.
Practical Tips
- Choose pixelation ~2–4 for balance between smooth gradients and CPU use.
- The picker keeps focus while open; clicking elsewhere closes it.
- Use
GetColor()
in real time (e.g., update materials or shaders each frame). - Customize widget size via inherited
SetSize(width, height)
for a larger swatch.
CContainer::AddWidget
Purpose
Populate a window or groupbox (CContainer) with arbitrary child widgets, automatically handling parent assignment, optional padding, scrollbar adjustments, and draw order.
Signature
void AddWidget(std::shared_ptr<FGUI::CWidgets> widget, bool padding);
Key Details
- Parent assignment:
widget->SetParentWidget(shared_from_this());
- Padding:
true
: widget width = container width minus 2× its X offset (and minus scrollbar width if enabled)false
: widget width unchanged
- Draw order:
Containers flaggedDRAW_FIRST
(e.g., groupboxes) move to the front ofm_prgpWidgets
.
Code Example
auto mainWindow = std::make_shared<FGUI::CContainer>();
mainWindow->SetPosition({50, 50});
mainWindow->SetSize({400, 300});
mainWindow->SetKey(VK_INSERT); // toggle with INSERT
mainWindow->AddCallback([](){ // custom draw before children
// draw background image
});
// Add a checkbox at (10,40) with padding
auto checkbox = std::make_shared<FGUI::CCheckBox>();
checkbox->SetTitle("Enable feature");
checkbox->SetPosition({10, 40});
mainWindow->AddWidget(checkbox, true);
// Add a nested groupbox
auto groupbox = std::make_shared<FGUI::CContainer>();
groupbox->SetTitle("Options");
groupbox->SetPosition({10, 80});
groupbox->SetSize({380, 150});
groupbox->SetScrollBarState(true); // enable scrolling
mainWindow->AddWidget(groupbox, false);
// Populate groupbox
auto option1 = std::make_shared<FGUI::CCheckBox>();
option1->SetTitle("Option A");
option1->SetPosition({10, 10});
groupbox->AddWidget(option1, true);
// In your render loop:
mainWindow->Render();
Practical Usage Guidance
- Padding = true
- Applies horizontal margins equal to the widget’s X position on both sides.
- If scrollbar is on, subtract ~15px scrollbar width.
- Padding = false
- Retains original widget width; useful for full-width panels.
- Nested containers
- Use
SetScrollBarState(true)
to enable vertical scrolling on overflow. - Child positions are relative to the container’s client area; scroll offset shifts rendering and input.
- Use
- Layout changes
- After adding/removing widgets, the container recalculates sizes and scrollbar thumb positions on next render/update.
- Focus and input
- Clicking a child with CLICKABLE & FOCUSABLE flags focuses it, suspending other children until unfocused.
By following these conventions, you ensure consistent padding, scrollbar behavior, parent/child linkage, and correct draw and input ordering within FGUI containers.
Advanced Usage & Customization
Power-user patterns for large, skinnable menus: precise layout control, backend integration, and input remapping.
Widget Positioning and Sizing
Control each widget’s local and absolute coordinates in nested containers.
API
void SetPosition(unsigned x, unsigned y)
FGUI::POINT GetPosition()
FGUI::POINT GetAbsolutePosition()
void SetSize(unsigned w, unsigned h)
FGUI::DIMENSION GetSize()
Example
#include "FGUI/widgets/widgets.hpp"
// Create container and button
auto panel = std::make_shared<FGUI::CContainer>();
auto button = std::make_shared<FGUI::CButton>("Submit");
panel->AddChild(button);
// Set panel layout
panel->SetPosition(100, 200);
panel->SetSize(300, 400);
// Position and size the button
button->SetPosition(20, 50);
button->SetSize(120, 30);
// Query positions
FGUI::POINT local = button->GetPosition(); // {20,50}
FGUI::POINT absolute = button->GetAbsolutePosition(); // {120,250}
Tips
- Call setters during your container’s setup phase.
- On window resize, update positions/sizes then invoke
panel->Update()
. - Use
GetAbsolutePosition()
for tooltips or pop-ups in nested layouts. - Pass around
DIMENSION
when configuring bulk layouts.
Backend Hooking: Rendering and Input
Wire your engine’s draw and input functions into FGUI for backend-agnostic widgets.
Rendering
Assign your drawing primitives to FGUI::RENDER
.
#include "FGUI/backend/render.hpp"
// Engine wrappers
void MyCreateFont(FGUI::FONT &f, std::string fam, int sz, int wt, bool aa) { /*...*/ }
FGUI::DIMENSION MyGetScreenSize() { return {800, 600}; }
FGUI::DIMENSION MyGetTextSize(FGUI::FONT f, const std::string &s) { /*...*/ }
void MyDrawRect(int x, int y, int w, int h, FGUI::COLOR c) { /*...*/ }
void MyDrawText(int x, int y, FGUI::FONT f, FGUI::COLOR c, const std::string &s) { /*...*/ }
void InitFGUIRenderer() {
FGUI::RENDER.CreateFont = MyCreateFont;
FGUI::RENDER.GetScreenSize = MyGetScreenSize;
FGUI::RENDER.GetTextSize = MyGetTextSize;
FGUI::RENDER.Rectangle = MyDrawRect;
FGUI::RENDER.Outline = MyDrawRect;
FGUI::RENDER.Gradient = /* your gradient impl */;
FGUI::RENDER.Line = /* your line impl */;
FGUI::RENDER.Text = MyDrawText;
}
Always assign render callbacks before instantiating any widgets.
Input
Bind your input polling and queries to FGUI::INPUT
.
#include "FGUI/backend/input.hpp"
#include <Windows.h>
void Win32Pull() {
MSG m;
while (PeekMessage(&m, 0, 0, 0, PM_REMOVE))
DispatchMessage(&m);
}
bool Win32KeyHeld(unsigned vk) { return (GetAsyncKeyState(vk) & 0x8000); }
FGUI::POINT Win32GetCursor() {
POINT p;
GetCursorPos(&p);
ScreenToClient(hWnd, &p);
return p;
}
void InitFGUIInput() {
FGUI::INPUT.PullInput = Win32Pull;
FGUI::INPUT.IsKeyHeld = Win32KeyHeld;
FGUI::INPUT.IsKeyPressed = /* your press-detection logic */;
FGUI::INPUT.IsKeyReleased = /* your release-detection logic */;
FGUI::INPUT.GetCursorPos = Win32GetCursor;
FGUI::INPUT.GetCursorPosDelta = []{ return FGUI::POINT{0,0}; }; // optional
FGUI::INPUT.IsCursorInArea = [](https://github.com/otvv/fgui/blob/master/FGUI::AREA a){
auto p = FGUI::INPUT.GetCursorPos();
return p.m_iX >= a.m_iLeft && p.m_iX <= a.m_iRight
&& p.m_iY >= a.m_iTop && p.m_iY <= a.m_iBottom;
};
FGUI::INPUT.SetInputType(FGUI::INPUT_TYPE::WIN_32);
}
Usage:
- Call
FGUI::INPUT.PullInput()
once per frame before UI update. - Query
IsKeyPressed
/IsKeyHeld
in widget event loops. - Use
SetInputType()
to adjust widget behavior per platform.
Keycodes & Remapping
FGUI defines platform-agnostic key and mouse macros. Override them to integrate custom input APIs.
Default Macros
MOUSE_1, MOUSE_2, KEY_ESCAPE, KEY_ENTER, KEY_BACKSPACE,
KEY_LSHIFT, KEY_RSHIFT, KEY_DELETE, KEY_LEFT, KEY_RIGHT,
KEY_UP, KEY_DOWN, KEY_PAGEUP, KEY_PAGEDOWN, KEY_LCONTROL,
KEY_RCONTROL, KEY_A, KEY_SPACE
Windows maps these to VK_*; other platforms use Source Engine codes.
Custom Mapping
Create a central header to redefine before including FGUI:
// MyInputConfig.hpp
#undef KEY_SPACE
#define KEY_SPACE 0x20
#undef MOUSE_1
#define MOUSE_1 0x01
#include "FGUI/internal/helpers.hpp"
Example
#include "MyInputConfig.hpp"
#include "FGUI/widgets/widgets.hpp"
if (FGUI::INPUT.IsKeyPressed(KEY_SPACE)) {
button->Toggle();
}
if (FGUI::INPUT.IsKeyPressed(MOUSE_1)) {
auto pos = FGUI::INPUT.GetCursorPos();
FGUI::RENDER.Rectangle(pos.m_iX, pos.m_iY, 10, 10, {255,0,0,255});
}
Best Practices:
- Use macros throughout your code for single-point remapping.
- Keep redefinitions in one header to avoid mismatches.
Contributing Guide
This guide explains how to build the FGUI library, run tests, follow coding standards, prepare pull requests, and comply with licensing requirements.
Building FGUI
Prerequisites
- C++17-compatible compiler (MSVC 2019+, GCC 9+, Clang 10+)
- CMake 3.15+
- DirectX SDK (Windows)
- nlohmann/json (optional: bundled via submodule)
Clone and Configure
git clone https://github.com/otvv/fgui.git
cd fgui
git submodule update --init --recursive
Unix/macOS
mkdir build && cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DFGUI_BUILD_EXAMPLES=ON \
-DFGUI_BUILD_TESTS=ON
cmake --build . -- -j$(nproc)
Windows (PowerShell)
mkdir build; cd build
cmake .. `
-G "Visual Studio 16 2019" `
-A x64 `
-DFGUI_BUILD_EXAMPLES=ON `
-DFGUI_BUILD_TESTS=ON
cmake --build . --config Release
Running Tests
Unit Tests
FGUI uses GoogleTest for unit testing. Enable with -DFGUI_BUILD_TESTS=ON
.
cd build
ctest --output-on-failure
# or invoke directly
./tests/FGUITestRunner
UI/Integration Tests
Example applications serve as manual UI tests.
# After build
./bin/ExampleApp # Linux/macOS
.\bin\Release\ExampleApp.exe # Windows
Coding Standards
- Language: C++17, RAII, avoid raw pointers when possible.
- Naming:
- Classes/Structs: PascalCase (e.g.
WidgetRenderer
) - Methods/Variables: camelCase (e.g.
renderFrame
) - Constants/Macros: UPPER_SNAKE_CASE (e.g.
FGUI_MAX_CONTROLS
)
- Classes/Structs: PascalCase (e.g.
- Indentation: 4 spaces, no tabs.
- Bracing style: Allman (brace on new line).
- Formatting: run clang-format against
.clang-format
at repo root.clang-format -i src/**/*.h src/**/*.cpp
- Commit messages:
TYPE(scope): brief description • More detailed description (if needed) • References: #<issue-number>
Pull Request Checklist
- Branch off
develop
or issue-specific branch. - All unit tests pass (
ctest
exit code 0). - Examples compile and run.
- Code formatted (
clang-format
) and linted. - Add or update unit tests for new behavior.
- Update documentation in
docs/
orREADME.md
. - Include license header in new source files:
// SPDX-License-Identifier: MIT // Copyright (c) <Year> otvv
- Link related issue or feature request.
- Use clear, descriptive PR title and description.
Licensing Reminder
FGUI is MIT-licensed. Derivative works must include the LICENSE
file and retain copyright
and warranty disclaimer. For details, see LICENSE.