Author(s): Renato Sanchez
Published on Thu Jan 01 2026
Summary: simple GTK base number converter, written in C.
URL: https://github.com/renatosanz/dec2bin
A fast, native, keyboard-friendly number base converter for the GNOME desktop.

- Version: 0.1
- License: GPL-3.0-or-later
- Language: C (GNU11)
- UI Toolkit: GTK4 + Libadwaita
What is it?
dec2bin is a pure-C, GTK4 desktop application that converts numbers between the four most common numerical bases — binary (2), octal (8), decimal (10), and hexadecimal (16) — in real time, in both directions, with no web dependency and no bloat.
It is not un encrusted webview wrapped around a JavaScript snippet: the entire conversion engine, input validation, and UI are hand-written, compiled, and native.
Why?
When I started at programming C was my first programming language, but I used in just scholar-like project, nothing more complex. Just after C I jumped on web, but more recently I got tired of all the ionic and PWA’s out there. So I decided to treat myself with a small project to break the ice and work on some real tools for people like me (just at the beginning) and then build more complex apps. Open source is a must. I got a lot of fun working on this project; Is it very useful? Maybe not, but this helped me to he fear on working with UI in C (thank god for GTK4 and libadwaita).
Some key points
1. Reusable Conversion Core -> src/dec2bin.c
The heart of the app — a modular engine with a clean separation of concerns:
from_<base>(input) converts any supported base → decimal using the classic
positional-weighting algorithm (digit × base^position, summed right-to-left).
to_<base>(input) converts decimal → any base using repeated division with a custom
string buffer, complemented by an in-place reverse() routine (src/dec2bin.c:15).
convert() (src/dec2bin.c:153) orchestrates everything: optional regex validation,
base-to-decimal, then decimal-to-target in a single function. The intermediate decimal value keeps the 4×4 matrix of base-pair conversions down to only 8 total functions.
2. Signal-Loop-Proof Real-Time UI -> src/main.c
The app converts on every keystroke. The tricky part: updating the output field fires its own
"changed" signal, which would trigger a reverse conversion and an infinite feedback loop.
The solution uses signal blocking:
g_signal_handlers_block_matched(G_OBJECT(editable_to), ...); // freeze echo
gtk_editable_set_text(GTK_EDITABLE(editable_to), converted_value);
g_signal_handlers_unblock_matched(G_OBJECT(editable_to), ...); // unfreeze
(src/main.c:59) — both bidirectional callbacks (left→right, right→left) are wired symmetrically, so either field is always the authoritative input.
3. Declarative UI via Blueprint -> data/ui/dec2bin.blp
The interface is authored in Blueprint (human-friendly XML-alternative) and compiled to
.ui at build time through blueprint-compiler, then embedded in the binary as a GResource via Meson’s gnome.compile_resources() → zero runtime file dependencies.
4. Keyboard Shortcut Layer -> src/keybindings.c
A reusable add_keyboard_shortcut() helper wraps GtkShortcutController + GtkKeyvalTrigger + GtkCallbackAction, enabling:
Ctrl+Q — quit
Ctrl+X — swap input/output bases
Ctrl+Backspace — clear both fields
Architecture Map
┌─────────────────────────────────────────────────────────────┐
│ main.c │
│ window wiring · signal plumbing · widget lookup │
│ (builder loads embedded .ui from GResource) │
├──────────────────────────┬──────────────────────────────────┤
│ dec2bin.c │ keybindings.c │
│ conversion core │ GtkShortcutController layer │
│ regex validation │ Ctrl+Q / Ctrl+X / Ctrl+BC │
├──────────────────────────┴──────────────────────────────────┤
│ types.h / dec2bin.h │
│ shared state: InputData (entry, dropdown, │
│ last_state, compiled regex) │
└─────────────────────────────────────────────────────────────┘
Build pipeline: Blueprint (.blp) → Greenfield XML → GResource → single native binary
orchestrated by Meson + Ninja.