Atlas - escpos.c
Home / toolkits / ESCPOS / src Lines: 5 | Size: 5022 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* SPDX-License-Identifier: GPL-3.0 2 * ESCPOS 4248 Print Standard 3 * 4 * Main parser 5 * 6 * COPYRIGHT NOTICE 7 * Copyright (C) 2026 0x4248, Sparky and contributors 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the license is not changed. 10 * 11 * This software is free and open source. Licensed under the GNU general 12 * public license version 3.0 as published by the Free Software Foundation. 13*/ 14 15#include <stdio.h> 16#include <string.h> 17#include <ctype.h> 18#include <stdlib.h> 19 20 21#include "escpos_commands.h" 22 23#define PRINTER_COLS 48 24 25static int nl_enabled = 1; 26 27/* ---- helpers ---- */ 28 29#define EMIT(cmd) do { \ 30 static const unsigned char _c[] = { cmd }; \ 31 fwrite(_c, 1, sizeof(_c), stdout); \ 32} while (0) 33 34static void hr(void) 35{ 36 for (int i = 0; i < PRINTER_COLS; i++) 37 putchar('-'); 38 putchar('\n'); 39} 40 41static void box(int height) 42{ 43 putchar('+'); 44 for (int i = 0; i < PRINTER_COLS - 2; i++) 45 putchar('-'); 46 puts("+"); 47 48 for (int h = 0; h < height; h++) { 49 putchar('|'); 50 for (int i = 0; i < PRINTER_COLS - 2; i++) 51 putchar(' '); 52 puts("|"); 53 } 54 55 putchar('+'); 56 for (int i = 0; i < PRINTER_COLS - 2; i++) 57 putchar('-'); 58 puts("+"); 59} 60 61static void set_normal(void) 62{ 63 EMIT(CMD_ALIGN_LEFT); 64 EMIT(CMD_SIZE_NORMAL); 65 EMIT(CMD_BOLD_OFF); 66 EMIT(CMD_UNDERLINE_OFF); 67 EMIT(CMD_INVERT_OFF); 68 EMIT(CMD_EMPHASIS_OFF); 69 EMIT(CMD_VERTICAL_OFF); 70 EMIT(CMD_FONT_A); 71} 72 73/* ---- token handling ---- */ 74 75enum token_type { 76 TOK_SIMPLE, 77 TOK_ARG, 78}; 79 80struct token { 81 const char *name; 82 enum token_type type; 83 void (*handler)(const char *arg); 84}; 85 86 87static void t_bold_on(const char *arg) { (void)arg; EMIT(CMD_BOLD_ON); } 88static void t_normal(const char *arg) { (void)arg; set_normal(); } 89static void t_center(const char *arg) { (void)arg; EMIT(CMD_ALIGN_CENTER); } 90static void t_left(const char *arg) { (void)arg; EMIT(CMD_ALIGN_LEFT); } 91static void t_wide(const char *arg) { (void)arg; EMIT(CMD_SIZE_WIDE); } 92 93static void t_nl_off(const char *arg) { (void)arg; nl_enabled = 0; } 94static void t_nl_on(const char *arg) { (void)arg; nl_enabled = 1; } 95static void t_nl(const char *arg) { (void)arg; putchar('\n'); } 96 97static void t_hr(const char *arg) { (void)arg; hr(); } 98static void t_cut(const char *arg) { (void)arg; EMIT(CMD_CUT_SAFE); } 99 100 101static void t_font(const char *arg) 102{ 103 if (!arg) return; 104 105 if (!strcmp(arg, "A")) 106 EMIT(CMD_FONT_A); 107 else if (!strcmp(arg, "B")) 108 EMIT(CMD_FONT_B); 109 else if (!strcmp(arg, "C")) 110 EMIT(CMD_FONT_C); 111} 112 113static void t_invert(const char *arg) 114{ 115 if (!arg) return; 116 117 if (!strcmp(arg, "ON")) 118 EMIT(CMD_INVERT_ON); 119 else if (!strcmp(arg, "OFF")) 120 EMIT(CMD_INVERT_OFF); 121} 122 123static void t_box(const char *arg) 124{ 125 int h; 126 127 if (!arg) 128 return; 129 130 h = atoi(arg); 131 if (h <= 0 || h > 20) 132 return; 133 134 box(h); 135} 136 137static const struct token tokens[] = { 138 { "BOLD", TOK_SIMPLE, t_bold_on }, 139 { "NORMAL", TOK_SIMPLE, t_normal }, 140 { "HR", TOK_SIMPLE, t_hr }, 141 { "CUT", TOK_SIMPLE, t_cut }, 142 { "CENTER", TOK_SIMPLE, t_center }, 143 { "LEFT", TOK_SIMPLE, t_left }, 144 { "WIDE", TOK_SIMPLE, t_wide }, 145 { "NL_OFF", TOK_SIMPLE, t_nl_off }, 146 { "NL_ON", TOK_SIMPLE, t_nl_on }, 147 { "NL", TOK_SIMPLE, t_nl }, 148 149 { "FONT", TOK_ARG, t_font }, 150 { "INVERT", TOK_ARG, t_invert }, 151 { "BOX", TOK_ARG, t_box }, 152}; 153 154static int try_token(const char *s, size_t *consumed) 155{ 156 char name[16] = {0}; 157 char arg[16] = {0}; 158 size_t i = 1, n = 0, a = 0; 159 160 if (s[0] != '[') 161 return 0; 162 163 /* parse NAME */ 164 while (s[i] && s[i] != ' ' && s[i] != ']' && n < sizeof(name) - 1) 165 name[n++] = s[i++]; 166 167 /* parse optional arg */ 168 if (s[i] == ' ') { 169 i++; 170 while (s[i] && s[i] != ']' && a < sizeof(arg) - 1) 171 arg[a++] = s[i++]; 172 } 173 174 if (s[i] != ']') 175 return 0; 176 177 i++; /* include ']' */ 178 179 for (size_t t = 0; t < sizeof(tokens)/sizeof(tokens[0]); t++) { 180 if (strcmp(name, tokens[t].name) == 0) { 181 tokens[t].handler(a ? arg : NULL); 182 *consumed = i; 183 return 1; 184 } 185 } 186 187 return 0; 188} 189 190/* ---- main ---- */ 191 192int main(void) 193{ 194 char buf[512]; 195 196 EMIT(CMD_INIT); 197 set_normal(); 198 199 while (fgets(buf, sizeof(buf), stdin)) { 200 size_t i = 0; 201 202 while (buf[i]) { 203 size_t consumed; 204 205 if (buf[i] == '[' && try_token(&buf[i], &consumed)) { 206 i += consumed; 207 continue; 208 } 209 210 if (buf[i] == '\n') { 211 if (nl_enabled) 212 putchar('\n'); 213 i++; 214 continue; 215 } 216 217 putchar(buf[i++]); 218 } 219 } 220 221 EMIT(CMD_BEEP(1, 100)); 222 return 0; 223} 224[FILE 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.