* See LICENSE for license information
*
*/
-#define _IS_KASSE
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include "print.h"
#include "version.h"
#include "vdc_patch_charset.h"
+#include "globals.h"
// drucker 4 oder 5
// graphic 4,0,10
void print_item(BYTE i) {
- char profit[10];
+ char profit[EUR_FORMAT_MINLEN + 1];
if (format_euro(profit, sizeof(profit), status.status[i].price) == NULL) {
cprintf("Preis %ld konnte nicht umgerechnet werden\r\n",
status.status[i].price);
/* Hauptbildschirm ausgeben */
static void print_screen(void) {
BYTE i = 0;
- char *time = get_time();
- char profit[10];
+ char profit[EUR_FORMAT_MINLEN + 1];
clrscr();
if (format_euro(profit, sizeof(profit), money) == NULL) {
cprintf("Einnahme %ld konnte nicht umgerechnet werden\r\n", money);
- exit(1);
+ profit[0] = '\0';
}
textcolor(TC_CYAN);
- cprintf("C128-Kassenprogramm (phil_fry, sECuRE, sur5r, mxf) " GV "\r\n");
+ /* fill whole line with cyan, so color bits are set up for the clock */
+ cprintf("%-80s", "C128-Kasse (phil_fry, sECuRE, sur5r, mxf) " GV);
textcolor(TC_LIGHT_GRAY);
- cprintf("\r\nUhrzeit: %s (wird nicht aktualisiert)\r\n"
- "Eingenommen: %s, Verkauft: %ld Dinge, Drucken: %s\r\n",
- time, profit, items_sold, (printing == 1 ? "ein" : "aus"));
+ cprintf("\r\n\r\n"
+ "Ertrag: %s (%ld Artikel); Drucken: %s\r\n",
+ profit, items_sold, (printing == 1 ? "ein" : "aus"));
textcolor(TC_LIGHT_GRAY);
cprintf(" \xB0"
"\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xC0\xB2"
* Prints a line and logs it to file. Every line can be at max 80 characters.
*
*/
-static void print_log(char *name, int item_price, int einheiten, char *nickname,
- char *rest) {
+static void print_log(char *name, int32_t item_price, int16_t einheiten,
+ char *nickname, char *rest) {
char *time = get_time();
- char price[10];
- /* Format:
- Transaction-ID (Anzahl verkaufter Einträge, inklusive des zu druckenden!)
- -- 6-stellig
- Uhrzeit -- 8-stellig
- Eintragname (= Getränk) -- 9-stellig
- Preis (in Cents) -- 9-stellig
- Anzahl -- 2-stellig
- Nickname (falls es vom Guthaben abgezogen wird) -- 10-stellig
- restguthaben (9-stellig)
-
- + 7 leerzeichen
- --> 48 zeichen
- */
+ char *ptr = NULL;
+ uint8_t n;
+ char price[EUR_FORMAT_MINLEN + 1];
if (format_euro(price, sizeof(price), item_price) == NULL) {
cprintf("Preis %d konnte nicht umgerechnet werden\r\n", item_price);
exit(1);
}
- sprintf(print_buffer, "%c[%3u] %s - %-" xstr(
- MAX_ITEM_NAME_LENGTH) "s - %s - %s - %d - an %s\r",
- 17, status.transaction_id, time, name, price, rest, einheiten,
- (*nickname != '\0' ? nickname : "Unbekannt"));
+ /* clang-format off */
+ n = snprintf(print_buffer, sizeof(print_buffer),
+ /* enable lower case letters -- 1 */
+ "%c"
+ /* Transaction-ID (Anzahl verkaufter Einträge, inklusive des zu druckenden!)
+ -- 6-stellig */
+ "[%3u] "
+ /* Uhrzeit -- 8-stellig + 3 */
+ "%8s - "
+ /* Eintragname (= Getränk) -- 9-stellig + 3 */
+ "%-" xstr(MAX_ITEM_NAME_LENGTH) "s - "
+ /* Preis (in Cents) -- 8-stellig + 3 */
+ "%" xstr(EUR_FORMAT_MINLEN) "s - "
+ /* restguthaben (8-stellig) + 3 */
+ "%" xstr(EUR_FORMAT_MINLEN) "s - "
+ /* Anzahl -- 2-stellig + 3 */
+ "%2d - "
+ /* Nickname (falls es vom Guthaben abgezogen wird) -- 10-stellig + 4 */
+ "an %" xstr(NICKNAME_MAX_LEN)"s\r",
+ 17, status.transaction_id, time, name, price, rest, einheiten,
+ (*nickname != '\0' ? nickname : "Unbekannt"));
+ /* clang-format on */
+
+ /* TODO: teach the EUR sign to the printer.
+ * Until then, we just overwrite it with "E" */
+ ptr = print_buffer;
+ while (ptr = strchr(ptr, EURSYM[0])) {
+ *ptr = 'E';
+ }
+
+ if (n > sizeof(print_buffer)) {
+ cprintf("\r\nprint_log(): print_buffer overflowed!\r\n"
+ "Wanted to write %d bytes\r\n%s\r\n",
+ n, print_buffer);
+ exit(1);
+ }
+
status.transaction_id++;
print_the_buffer();
}
/* dialog which is called for each bought item */
-static signed int buy(char *name, unsigned int price) {
- int negative = 1;
- char entered[5] = {'1', 0, 0, 0, 0};
- BYTE i = 0, matches = 0;
- BYTE c, x, y, nickname_len;
- int einheiten;
+static signed int buy(char *name, int32_t price) {
+ BYTE matches = 0;
+ BYTE c, nickname_len;
+ int16_t einheiten;
char nickname[NICKNAME_MAX_LEN + 1];
- char rest[10];
+ char rest[EUR_FORMAT_MINLEN + 1];
struct credits_t *credit;
- memset(nickname, '\0', sizeof(nickname));
- memset(rest, '\0', sizeof(rest));
-
clrscr();
cprintf("Wieviel Einheiten \"%s\"? [1] \r\n", name);
- x = wherex();
- y = wherey();
- while (1) {
- /* Buffer-Ende erreicht? */
- if (i == (sizeof(entered) - 1))
- break;
- c = cgetc();
- /* Enter */
- if (c == PETSCII_CR)
- break;
- /* Backspace */
- if (c == PETSCII_DEL) {
- if (i == 0)
- continue;
- entered[--i] = '\0';
- cputcxy(x + i, y, ' ');
- gotoxy(x + i, y);
- continue;
- }
- if (c == PETSCII_ESC) {
- cprintf("Kauf abgebrochen, dr" uUML "cke RETURN...\r\n");
- cget_return();
- return 1;
- }
- if (c == '-' && i == 0) {
- negative = -1;
- cputc(c);
- } else if (c >= PETSCII_0 && c <= PETSCII_9) {
- entered[i++] = c;
- cputc(c);
- }
-
- /* Ungültige Eingabe (keine Ziffer), einfach ignorieren */
- }
- einheiten = atoi(entered) * negative;
+ einheiten = cget_number(1);
if (einheiten > 100 || einheiten < -100 || einheiten == 0) {
cprintf("\r\nEinheit nicht in [-100, 100] oder 0, Abbruch, dr" uUML "cke "
"RETURN...\r\n");
- cgetc();
+ cget_return();
return 1;
}
cprintf("\r\nAuf ein Guthaben kaufen? Wenn ja, Nickname eingeben:\r\n");
- {
- BYTE i;
- BYTE x;
- BYTE y;
- BYTE matches;
- char *uniquematch;
- input_terminator_t terminator;
- while (1) {
- terminator = get_input_terminated_by(INPUT_TERMINATOR_RETURN |
- INPUT_TERMINATOR_SPACE,
- nickname, sizeof(nickname));
-
- /* Clear the screen from any previous completions */
- x = wherex();
- y = wherey();
- for (i = 1; i < 7; i++) {
- /* "Completion:" is longer than NICKNAME_MAX_LEN */
- cclearxy(0, y + i, strlen("Completion:"));
- }
- gotoxy(x, y);
+ nickname_len = cget_nickname(nickname, sizeof(nickname));
- if (terminator != INPUT_TERMINATOR_SPACE) {
- break;
- }
-
- matches = 0;
- uniquematch = NULL;
- for (i = 0; i < credits.num_items; i++) {
- if (strncmp(nickname, credits.credits[i].nickname, strlen(nickname)) !=
- 0) {
- continue;
- }
- matches++;
- if (matches > 1) {
- break;
- }
- uniquematch = credits.credits[i].nickname;
- }
- if (matches == 1) {
- /* Display the rest of the nickname */
- textcolor(TC_LIGHT_GREEN);
- cprintf("%s", uniquematch + strlen(nickname));
- textcolor(TC_LIGHT_GRAY);
- strcat(nickname, uniquematch + strlen(nickname));
- } else {
- /* Multiple nicknames match what was entered so far. Abort and
- * display all matches, then prompt the user again. */
- char completion[NICKNAME_MAX_LEN + 1];
- BYTE len = strlen(nickname);
- x = wherex();
- y = wherey();
- cprintf("\r\nCompletion:\r\n");
- matches = 0;
- for (i = 0; i < credits.num_items; i++) {
- if (strncmp(nickname, credits.credits[i].nickname, len) != 0) {
- continue;
- }
- if (++matches == 5) {
- cprintf("...\r\n");
- break;
- }
- strcpy(completion, credits.credits[i].nickname);
- *(completion + len) = '\0';
- cprintf("%s", completion);
- textcolor(TC_LIGHT_GREEN);
- cprintf("%c", *(credits.credits[i].nickname + len));
- textcolor(TC_LIGHT_GRAY);
- cprintf("%s\r\n", completion + len + 1);
- }
- gotoxy(x, y);
- }
- }
- }
-
- if (*nickname != '\0' && *nickname != PETSCII_SP) {
- nickname_len = strlen(nickname);
+ if (nickname_len && *nickname != '\0' && *nickname != PETSCII_SP) {
/* go through credits and remove the amount of money or set nickname
* to NULL if no such credit could be found */
credit = find_credit(nickname);
if (credit != NULL) {
- while ((signed int)credit->credit < ((signed int)price * einheiten)) {
+ while ((int32_t)credit->credit < (price * einheiten)) {
if (format_euro(rest, sizeof(rest), credit->credit) == NULL) {
cprintf("Preis %d konnte nicht umgerechnet werden\r\n",
credit->credit);
cget_return();
return 0;
}
- } else {
- /* Ensure that nickname is NULL if it's empty because it's used in print_log
- */
- *nickname = '\0';
}
money += price * einheiten;
}
void buy_custom(void) {
- BYTE c = 0, i = 0;
- int negative = 1;
- char entered[5] = {'1', 0, 0, 0, 0};
- char *input, name[20];
+ char name[MAX_ITEM_NAME_LENGTH + 1];
int price;
clrscr();
- memset(name, '\0', sizeof(name));
cprintf("\r\nWas soll gekauft werden?\r\n");
- input = get_input();
- strncpy(name, input, sizeof(name));
- if (*name == '\0')
+ if (cgetn_input(name, sizeof(name)) == 0)
return;
cprintf("\r\nWie teuer ist \"%s\" (in cents)?\r\n", name);
- while (1) {
- c = cgetc();
- if (c == PETSCII_CR)
- break;
- cputc(c);
- if (c == PETSCII_ESC) {
- cprintf("Kauf abgebrochen, dr" uUML "cke RETURN...\r\n");
- cget_return();
- return;
- } else if (c == '-' && i == 0)
- negative = -1;
- else if (c >= PETSCII_0 && c <= PETSCII_9)
- entered[i++] = c;
- }
- price = atoi(entered) * negative;
- cprintf("\r\n");
+ price = cget_number(0);
+
+ if (price == 0) {
+ cprintf("Kauf abgebrochen, dr" uUML "cke RETURN...\r\n");
+ cget_return();
+ return;
+ }
buy(name, price);
}
void set_time_interactive(void) {
- BYTE part[3] = {'0', '0', '\0'};
- BYTE tp1, tp2, tp3;
+ char part[3] = {'\0', '\0', '\0'};
+ uint8_t day, tp1, tp2, tp3;
char *time_input, *time;
- cprintf("Gib die aktuelle Uhrzeit ein (Format HHMMSS):\r\n");
+ cprintf("Gib den aktuellen Tag des Events und Uhrzeit ein\r\n"
+ "Format DHHMMSS, 0-indexiert, z.B. 0174259 für \"erster Tag um "
+ "17:42:59\":\r\n");
time_input = get_input();
part[0] = time_input[0];
- part[1] = time_input[1];
+ day = atoi(part);
+ part[0] = time_input[1];
+ part[1] = time_input[2];
tp1 = atoi(part);
- part[0] = time_input[2];
- part[1] = time_input[3];
+ part[0] = time_input[3];
+ part[1] = time_input[4];
tp2 = atoi(part);
- part[0] = time_input[4];
- part[1] = time_input[5];
+ part[0] = time_input[5];
+ part[1] = time_input[6];
tp3 = atoi(part);
- set_time(tp1, tp2, tp3);
+ set_time(day, tp1, tp2, tp3);
time = get_time();
cprintf("\r\nZeit gesetzt: %s\r\n", time);
char *c;
char *time;
+ printing = 1;
+ /* initialize daytime global, start the CIA TOD */
+ set_time(0, 0, 0, 0);
+ kasse_menu = MENU_UNDEFINED;
+
videomode(VIDEOMODE_80x25);
/* clock CPU at double the speed (a whopping 2 Mhz!) */
clrscr();
+ install_daytime_irq();
+
/* Allocate logging buffer memory */
init_log();
while (1) {
print_screen();
+ kasse_menu = MENU_MAIN;
c = get_input();
+ kasse_menu = MENU_UNDEFINED;
/* ...display dialogs eventually */
if (*c >= PETSCII_0 && *c <= PETSCII_9) {
/* if the input starts with a digit, we will interpret it as a number