Commit c427fc9fdda7782e25a1f7bc61b924c8c9d210db
Commits[COMMIT BEGIN]commit c427fc9fdda7782e25a1f7bc61b924c8c9d210db Author: 0x4248 <[email protected]> Date: Sat Jan 31 23:59:26 2026 +0000 escpos: init diff --git a/toolkits/ESCPOS/src/escpos.c b/toolkits/ESCPOS/src/escpos.c new file mode 100644 index 0000000..1967ec9 --- /dev/null +++ b/toolkits/ESCPOS/src/escpos.c @@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: GPL-3.0 + * ESCPOS 4248 Print Standard + * + * Main parser + * + * COPYRIGHT NOTICE + * Copyright (C) 2026 0x4248, Sparky and contributors + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the license is not changed. + * + * This software is free and open source. Licensed under the GNU general + * public license version 3.0 as published by the Free Software Foundation. +*/ + +/* SPDX-License-Identifier: GPL-3.0 + * + * escpos-filter.c + * Simple ESC/POS text filter + */ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <stdlib.h> + + +#include "escpos_commands.h" + +#define PRINTER_COLS 48 + +static int nl_enabled = 1; + +/* ---- helpers ---- */ + +#define EMIT(cmd) do { \ + static const unsigned char _c[] = { cmd }; \ + fwrite(_c, 1, sizeof(_c), stdout); \ +} while (0) + +static void hr(void) +{ + for (int i = 0; i < PRINTER_COLS; i++) + putchar('-'); + putchar('\n'); +} + +static void box(int height) +{ + putchar('+'); + for (int i = 0; i < PRINTER_COLS - 2; i++) + putchar('-'); + puts("+"); + + for (int h = 0; h < height; h++) { + putchar('|'); + for (int i = 0; i < PRINTER_COLS - 2; i++) + putchar(' '); + puts("|"); + } + + putchar('+'); + for (int i = 0; i < PRINTER_COLS - 2; i++) + putchar('-'); + puts("+"); +} + +static void set_normal(void) +{ + EMIT(CMD_ALIGN_LEFT); + EMIT(CMD_SIZE_NORMAL); + EMIT(CMD_BOLD_OFF); + EMIT(CMD_UNDERLINE_OFF); + EMIT(CMD_INVERT_OFF); + EMIT(CMD_EMPHASIS_OFF); + EMIT(CMD_VERTICAL_OFF); + EMIT(CMD_FONT_A); +} + +/* ---- token handling ---- */ + +enum token_type { + TOK_SIMPLE, + TOK_ARG, +}; + +struct token { + const char *name; + enum token_type type; + void (*handler)(const char *arg); +}; + + +static void t_bold_on(const char *arg) { (void)arg; EMIT(CMD_BOLD_ON); } +static void t_normal(const char *arg) { (void)arg; set_normal(); } +static void t_center(const char *arg) { (void)arg; EMIT(CMD_ALIGN_CENTER); } +static void t_left(const char *arg) { (void)arg; EMIT(CMD_ALIGN_LEFT); } +static void t_wide(const char *arg) { (void)arg; EMIT(CMD_SIZE_WIDE); } + +static void t_nl_off(const char *arg) { (void)arg; nl_enabled = 0; } +static void t_nl_on(const char *arg) { (void)arg; nl_enabled = 1; } +static void t_nl(const char *arg) { (void)arg; putchar('\n'); } + +static void t_hr(const char *arg) { (void)arg; hr(); } +static void t_cut(const char *arg) { (void)arg; EMIT(CMD_CUT_SAFE); } + + +static void t_font(const char *arg) +{ + if (!arg) return; + + if (!strcmp(arg, "A")) + EMIT(CMD_FONT_A); + else if (!strcmp(arg, "B")) + EMIT(CMD_FONT_B); + else if (!strcmp(arg, "C")) + EMIT(CMD_FONT_C); +} + +static void t_invert(const char *arg) +{ + if (!arg) return; + + if (!strcmp(arg, "ON")) + EMIT(CMD_INVERT_ON); + else if (!strcmp(arg, "OFF")) + EMIT(CMD_INVERT_OFF); +} + +static void t_box(const char *arg) +{ + int h; + + if (!arg) + return; + + h = atoi(arg); + if (h <= 0 || h > 20) + return; + + box(h); +} + +static const struct token tokens[] = { + { "BOLD", TOK_SIMPLE, t_bold_on }, + { "NORMAL", TOK_SIMPLE, t_normal }, + { "HR", TOK_SIMPLE, t_hr }, + { "CUT", TOK_SIMPLE, t_cut }, + { "CENTER", TOK_SIMPLE, t_center }, + { "LEFT", TOK_SIMPLE, t_left }, + { "WIDE", TOK_SIMPLE, t_wide }, + { "NL_OFF", TOK_SIMPLE, t_nl_off }, + { "NL_ON", TOK_SIMPLE, t_nl_on }, + { "NL", TOK_SIMPLE, t_nl }, + + { "FONT", TOK_ARG, t_font }, + { "INVERT", TOK_ARG, t_invert }, + { "BOX", TOK_ARG, t_box }, +}; + +static int try_token(const char *s, size_t *consumed) +{ + char name[16] = {0}; + char arg[16] = {0}; + size_t i = 1, n = 0, a = 0; + + if (s[0] != '[') + return 0; + + /* parse NAME */ + while (s[i] && s[i] != ' ' && s[i] != ']' && n < sizeof(name) - 1) + name[n++] = s[i++]; + + /* parse optional arg */ + if (s[i] == ' ') { + i++; + while (s[i] && s[i] != ']' && a < sizeof(arg) - 1) + arg[a++] = s[i++]; + } + + if (s[i] != ']') + return 0; + + i++; /* include ']' */ + + for (size_t t = 0; t < sizeof(tokens)/sizeof(tokens[0]); t++) { + if (strcmp(name, tokens[t].name) == 0) { + tokens[t].handler(a ? arg : NULL); + *consumed = i; + return 1; + } + } + + return 0; +} + +/* ---- main ---- */ + +int main(void) +{ + char buf[512]; + + EMIT(CMD_INIT); + set_normal(); + + while (fgets(buf, sizeof(buf), stdin)) { + size_t i = 0; + + while (buf[i]) { + size_t consumed; + + if (buf[i] == '[' && try_token(&buf[i], &consumed)) { + i += consumed; + continue; + } + + if (buf[i] == '\n') { + if (nl_enabled) + // putchar('\n'); + i++; + continue; + } + + putchar(buf[i++]); + } + } + + EMIT(CMD_BEEP(1, 100)); + return 0; +} diff --git a/toolkits/ESCPOS/src/escpos_commands.h b/toolkits/ESCPOS/src/escpos_commands.h new file mode 100644 index 0000000..ce2e43a --- /dev/null +++ b/toolkits/ESCPOS/src/escpos_commands.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-3.0 + * ESCPOS X42 Print Standard + * + * ESC / POS Command Definitions + * + * COPYRIGHT NOTICE + * Copyright (C) 2026 0x4248, Sparky and contributors + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the license is not changed. + * + * This software is free and open source. Licensed under the GNU general + * public license version 3.0 as published by the Free Software Foundation. +*/ + + +#ifndef ESCPOS_COMMANDS_H +#define ESCPOS_COMMANDS_H + +/* ASCII control chars */ +#define CHR_NUL 0x00 +#define CHR_LF 0x0A + +/* ESC/POS prefixes */ +#define CHR_ESC 0x1B +#define CHR_GS 0x1D + +/* ---- Printer control ---- */ + +/* Initialize */ +#define CMD_INIT CHR_ESC, '@' + +/* Line feed */ +#define CMD_LF CHR_LF + +/* ---- Text formatting ---- */ + +/* Bold */ +#define CMD_BOLD_ON CHR_ESC, 'E', 0x01 +#define CMD_BOLD_OFF CHR_ESC, 'E', 0x00 + +/* Underline */ +#define CMD_UNDERLINE_ON CHR_ESC, '-', 0x01 +#define CMD_UNDERLINE_OFF CHR_ESC, '-', 0x00 + +/* Alignment */ +#define CMD_ALIGN_LEFT CHR_ESC, 'a', 0x00 +#define CMD_ALIGN_CENTER CHR_ESC, 'a', 0x01 +#define CMD_ALIGN_RIGHT CHR_ESC, 'a', 0x02 + +/* Character size (GS ! n) */ +#define CMD_SIZE_NORMAL CHR_GS, '!', 0x00 +#define CMD_SIZE_WIDE CHR_GS, '!', 0x11 /* 2x width + height */ + +/* ---- Font selection ---- */ +#define CMD_FONT_A CHR_ESC, 'M', 0x00 +#define CMD_FONT_B CHR_ESC, 'M', 0x01 +#define CMD_FONT_C CHR_ESC, 'M', 0x02 + +#define CMD_INVERT_ON CHR_GS, 'B', 0x01 +#define CMD_INVERT_OFF CHR_GS, 'B', 0x00 + +#define CMD_EMPHASIS_ON CHR_ESC, 'G', 0x01 +#define CMD_EMPHASIS_OFF CHR_ESC, 'G', 0x00 + +#define CMD_VERTICAL_ON CHR_ESC, 'V', 0x01 +#define CMD_VERTICAL_OFF CHR_ESC, 'V', 0x00 + +/* ---- Paper handling ---- */ + +/* Feed n lines */ +#define CMD_FEED(n) CHR_ESC, 'd', (n) + +/* Cut paper */ +#define CMD_CUT_FULL CHR_GS, 'V', 0x00 +#define CMD_CUT_PARTIAL CHR_GS, 'V', 0x01 +#define CMD_CUT_SAFE CHR_GS, 'V', 'B', 0x00 + +/* ---- Beeper ---- */ +#define CMD_BEEP(n, t) CHR_ESC, 'B', (n), (t) + + + +#endif /* ESCPOS_COMMANDS_H */[COMMIT END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.