The A-Batch code post. As stated in the previous post, the code could definitely use some sanity checks on parameters. There is also room for some optimizations throughout, and removal of a couple of magic numbers. As it stands it works for what I need it to do. The source is fairly well documented. If you want further clarification on something, email or leave a comment.
Attached to this post is the Turbo C source code and executable. The attachment is a zip file. It was renamed to “.odt” to pass upload restrictions. Rename it with a “.zip” extension and extract. It has two files in it:
- ABATCH.C
- ABATCH.EXE
The 32 bit CRC checksum (cksum -o 3) of the file is (download link next to checksum):
3183384630 14242 ABatch-Zip.odt
Following is the source code listing.
/* ---------------------------------------------------------------------- // File.......: ABATCH.PRG // Author.....: Ripdubski (inverseatascii@icloud.com) // Date.......: 2019.10.10 // Description: 2019 re-creation of A-Batch written by myself in the // early 1990's whose source was lost. // A Batch script helper for displaying nice screens. // Notes......: // Revised....: // ---------------------------------------------------------------------- */ /* ---------- Includes ---------- */ #include #include #include #include #include #include /* ---------- Definitions ---------- */ #define AB_VERSION "2.00" /* Error codes */ #define AB_ERR_NONE 0 #define AB_ERR_BADSYNTAX 100 #define AB_ERR_BADCMD 101 #define AB_ERR_MISSING 200 /* Commands */ #define AB_CMD_BACK "back" #define AB_CMD_BOX "box" #define AB_CMD_CLS "cls" #define AB_CMD_GOXY "goxy" #define AB_CMD_HELP "help" #define AB_CMD_TEXT "text" #define AB_CMD_TITLE "title" #define AB_CMD_VERSION "version" #define AB_CMD_WAIT "wait" /* Box border styles */ #define AB_STYLE_BACK "back" #define AB_STYLE_SINGLE "single" #define AB_STYLE_DOUBLE "double" #define AB_STYLE_BLOCK "block" #define AB_STYLE_FAT "fat" #define AB_STYLE_SD "sd" #define AB_STYLE_DS "ds" #define AB_STYLE_NONE "none" /* Color names */ #define AB_COLOR_BLACK "black" #define AB_COLOR_BLUE "blue" #define AB_COLOR_GREEN "green" #define AB_COLOR_CYAN "cyan" #define AB_COLOR_RED "red" #define AB_COLOR_MAGENTA "magenta" #define AB_COLOR_BROWN "brown" #define AB_COLOR_LGRAY "lgray" #define AB_COLOR_DGRAY "dgray" #define AB_COLOR_LBLUE "lblue" #define AB_COLOR_LGREEN "lgreen" #define AB_COLOR_LCYAN "lcyan" #define AB_COLOR_LRED "lred" #define AB_COLOR_LMAGENTA "lmagenta" #define AB_COLOR_YELLOW "yellow" #define AB_COLOR_WHITE "white" #define AB_COLOR_BLINK "blink" /* Box character locations in the box character string */ #define AB_BOXCH_TL 0 #define AB_BOXCH_TR 2 #define AB_BOXCH_TM 1 #define AB_BOXCH_BL 6 #define AB_BOXCH_BR 4 #define AB_BOXCH_BM 5 #define AB_BOXCH_ML 3 #define AB_BOXCH_MR 7 #define AB_BOXCH_MM 8 /* Title ornament locations in the ornament character string */ #define AB_ORNCH_L 0 #define AB_ORNCH_R 1 /* ---------- Prototypes ---------- */ void idself(void); int transcolor(char *); void cmd_text(char *, int, int, char *, char *); int main(int, char *[]); /* ---------- Functions ---------- */ /* ---------------------------------------------------------------------- // Func.......: void idself(void) // Description: Outputs program identifier // Parameters.: n/a // Returns....: n/a // ---------------------------------------------------------------------- */ void idself(void) { printf("A-Batch, version %s\nCopyright (c) 2019 Ripdubski All Rights Reserved.\n", AB_VERSION); } /* ---------------------------------------------------------------------- // Func.......: int transcolor(char *cName) // Description: Translates named color to color attribute value // Parameters.: cName = color name // Returns....: color attribute value (number) // ---------------------------------------------------------------------- */ int transcolor(char *cName) { int iColor = 0; /* Decide which color value to return */ if (stricmp(cName, AB_COLOR_BLACK) == 0) iColor = 0; if (stricmp(cName, AB_COLOR_BLUE) == 0) iColor = 1; if (stricmp(cName, AB_COLOR_GREEN) == 0) iColor = 2; if (stricmp(cName, AB_COLOR_CYAN) == 0) iColor = 3; if (stricmp(cName, AB_COLOR_RED) == 0) iColor = 4; if (stricmp(cName, AB_COLOR_MAGENTA) == 0) iColor = 5; if (stricmp(cName, AB_COLOR_BROWN) == 0) iColor = 6; if (stricmp(cName, AB_COLOR_LGRAY) == 0) iColor = 7; if (stricmp(cName, AB_COLOR_DGRAY) == 0) iColor = 8; if (stricmp(cName, AB_COLOR_LBLUE) == 0) iColor = 9; if (stricmp(cName, AB_COLOR_LGREEN) == 0) iColor = 10; if (stricmp(cName, AB_COLOR_LCYAN) == 0) iColor = 11; if (stricmp(cName, AB_COLOR_LRED) == 0) iColor = 12; if (stricmp(cName, AB_COLOR_LMAGENTA) == 0) iColor = 13; if (stricmp(cName, AB_COLOR_YELLOW) == 0) iColor = 14; if (stricmp(cName, AB_COLOR_WHITE) == 0) iColor = 15; if (stricmp(cName, AB_COLOR_BLINK) == 0) iColor = 128; return(iColor); } /* ---------------------------------------------------------------------- // Func.......: void cmd_text(char *cStr, int iX, int iY, char *cFC, char *cBC) // Description: Routine to output text and preserve text attributes // Parameters.: cStr = string of text to display // iX = X coordinate to display at // iY = Y coordinate to display at // cFC = foreground color of text // cBC = background color of text // Returns....: n/a // ---------------------------------------------------------------------- */ void cmd_text(char *cStr, int iX, int iY, char *cFC, char *cBC) { struct text_info sText; /* Save old mode */ gettextinfo(&sText); /* Set text forground and background color */ textcolor(transcolor(cFC)); textbackground(transcolor(cBC)); /* Output text at location */ gotoxy(iX,iY); cputs(cStr); /* Restore text attributes */ textattr(sText.attribute); } /* ---------------------------------------------------------------------- // Func.......: int main(int argc, char *argv[]) // Description: Main routine // Parameters.: argc = number of command line arguments // argv = array of command line arguments // Returns....: errorcode (can be tested/checked from BATCH script) // ---------------------------------------------------------------------- */ int main(int argc, char *argv[]) { /* Default return value to badcmd, set as needed throughout */ int iCnt, iLp, iRet = AB_ERR_BADCMD, iX = 0, iY = 0, iW = 0, iH = 0; /* Strings for box drawing */ char cBoxBack[11] = { 176,176,176,176,176,176,176,176,176,'\0' }; char cBoxSingle[11] = { 218,196,191,179,217,196,192,179,32,'\0' }; char cBoxDouble[11] = { 201,205,187,186,188,205,200,186,32,'\0' }; char cBoxBlock[11] = { 219,219,219,219,219,219,219,219,32,'\0' }; char cBoxFat[11] = { 220,220,220,222,223,223,223,221,32,'\0' }; char cBoxSD[11] = { 214,196,183,186,189,196,211,186,32,'\0' }; char cBoxDS[11] = { 213,205,184,179,190,205,212,179,32,'\0' }; char cBoxNone[11] = { 32,32,32,32,32,32,32,32,32,'\0' }; char *cBox; /* Strings for title ornaments */ char cOrnSingle[4] = { 180,195,'\0' }; char cOrnDouble[4] = { 181,198,'\0' }; char cOrnBlock[4] = { 221,222,'\0' }; char cOrnFat[4] = { 221,222,'\0' }; char cOrnSD[4] = { 180,195,'\0' }; char cOrnDS[4] = { 181,198,'\0' }; char cOrnNone[4] = { ' ',' ','\0' }; char *cOrn; /* Temp buffers for building output */ char cLine[81] = "", cMiddle[81] = "", cChL, cChM, cChR; /* Set actual argument count */ iCnt = argc - 1; /* Check for proper syntax */ if ((iCnt < 2) | (stricmp(argv[1], AB_CMD_HELP) == 0)) { idself(); printf("Syntax: ascreen command parameters\n"); printf(" commands: back style fc bc = draw background (style=back or 3 chars)\n"); printf(" box x y w h style fc bc = draw box in style at x y\n"); printf(" cls = clear screen and home cursor\n"); printf(" goxy x y = move cursor to x,y\n"); printf(" help = syntax\n"); printf(" text x y \"text\" fc bc = output \"text\" at x y\n"); printf(" title x y \"text\" fc bc style fc bc = box title\n"); printf(" wait n = wait n seconds\n"); printf(" version = version information\n"); printf(" x y expressed in base 1\n"); printf(" styles: single, double, block, fat, SD, DS, none, back (back only)\n"); printf(" colors: black, blue, green, cyan, red, magenta, brown, lgray,\n"); printf(" dgray, lblue, lgreen, lcyan, lred, lmagenta, yellow, white\n"); exit(AB_ERR_BADSYNTAX); } /* Decide on command and take action */ /* Output text in specific style at specific location */ if (stricmp(argv[1], AB_CMD_TEXT) == 0) { if (iCnt < 6) { iRet = AB_ERR_MISSING; } else { /* text x y fc bc string */ /* Grab x, y */ iX = atoi(argv[2]); iY = atoi(argv[3]); cmd_text(argv[6], iX, iY, argv[4], argv[5]); iRet = AB_ERR_NONE; } } /* Draw specific sized box in specific style at specific location */ if (stricmp(argv[1], AB_CMD_BOX) == 0) { if (iCnt < 8) { iRet = AB_ERR_MISSING; } else { /* box x y w h style fc bc */ /* Grab x, y, width, and height */ iX = atoi(argv[2]); iY = atoi(argv[3]); iW = atoi(argv[4]); iH = atoi(argv[5]); /* Set build string based on selection type */ if (stricmp(argv[6], AB_STYLE_BACK) == 0) cBox = cBoxBack; if (stricmp(argv[6], AB_STYLE_SINGLE) == 0) cBox = cBoxSingle; if (stricmp(argv[6], AB_STYLE_DOUBLE) == 0) cBox = cBoxDouble; if (stricmp(argv[6], AB_STYLE_BLOCK) == 0) cBox = cBoxBlock; if (stricmp(argv[6], AB_STYLE_FAT) == 0) cBox = cBoxFat; if (stricmp(argv[6], AB_STYLE_SD) == 0) cBox = cBoxSD; if (stricmp(argv[6], AB_STYLE_DS) == 0) cBox = cBoxDS; if (stricmp(argv[6], AB_STYLE_NONE) == 0) cBox = cBoxNone; /* Build box line by line and output */ for (iLp = 1; iLp <= iH; iLp++) { /* Determine line characters based on line number */ if (iLp == 1) { cChL = cBox[AB_BOXCH_TL]; cChR = cBox[AB_BOXCH_TR]; cChM = cBox[AB_BOXCH_TM]; } else { if (iLp == iH) { cChL = cBox[AB_BOXCH_BL]; cChR = cBox[AB_BOXCH_BR]; cChM = cBox[AB_BOXCH_BM]; } else { cChL = cBox[AB_BOXCH_ML]; cChR = cBox[AB_BOXCH_MR]; cChM = cBox[AB_BOXCH_MM]; } } /* Create middle portion of line, then build entire line */ memset(cMiddle, cChM, iW - 2); cMiddle[iW] = '\0'; sprintf(cLine, "%c%s%c", cChL, cMiddle, cChR); /* Output the line */ cmd_text(cLine, iX, iY + (iLp - 1), argv[7], argv[8]); } iRet = AB_ERR_NONE; } } /* Add title to box using blended delimiters */ if (stricmp(argv[1], AB_CMD_TITLE) == 0) { if (iCnt < 9) { iRet = AB_ERR_MISSING; } else { /* title x y text fc bc style fc bc */ /* Grab x, y, width, and height */ iX = atoi(argv[2]); iY = atoi(argv[3]); /* Set build string based on selection type */ if (stricmp(argv[7], AB_STYLE_SINGLE) == 0) cBox = cOrnSingle; if (stricmp(argv[7], AB_STYLE_DOUBLE) == 0) cBox = cOrnDouble; if (stricmp(argv[7], AB_STYLE_BLOCK) == 0) cBox = cOrnBlock; if (stricmp(argv[7], AB_STYLE_FAT) == 0) cBox = cOrnFat; if (stricmp(argv[7], AB_STYLE_SD) == 0) cBox = cOrnSD; if (stricmp(argv[7], AB_STYLE_DS) == 0) cBox = cOrnDS; if (stricmp(argv[7], AB_STYLE_NONE) == 0) cBox = cOrnNone; /* Get ornaments */ cChL = cBox[AB_ORNCH_L]; cChR = cBox[AB_ORNCH_R]; /* Create and output left and right ornaments */ sprintf(cLine, "%c", cChL); cmd_text(cLine, iX, iY, argv[8], argv[9]); sprintf(cLine, "%c", cChR); cmd_text(cLine, iX + strlen(argv[4]) + 3, iY, argv[8], argv[9]); sprintf(cLine, " %s ", argv[4]); cmd_text(cLine, iX + 1, iY, argv[5], argv[6]); iRet = AB_ERR_NONE; } } /* Goto X Y (cursor) screen coordinates */ if (stricmp(argv[1], AB_CMD_GOXY) == 0) { if (iCnt < 3) { iRet = AB_ERR_MISSING; } else { /* goxy x y */ iX = atoi(argv[2]); iY = atoi(argv[3]); gotoxy(iX, iY); iRet = AB_ERR_NONE; } } /* Wait number of seconds */ if (stricmp(argv[1], AB_CMD_WAIT) == 0) { if (iCnt < 2) { iRet = AB_ERR_MISSING; } else { /* wait secs */ iX = atoi(argv[2]); sleep(iX); iRet = AB_ERR_NONE; } } /* Draw background filling entire screen */ if (stricmp(argv[1], AB_CMD_BACK) == 0) { if (iCnt < 4) { iRet = AB_ERR_MISSING; } else { /* back style fc bc */ /* Set build string based on selection type - only back supported */ if (stricmp(argv[2], AB_STYLE_BACK) == 0) { cBox = cBoxBack; } else { cBox = argv[2]; /* custom string (3 char minimum: LMR) */ } /* Get background characters - only need first three */ cChL = cBox[AB_BOXCH_TL]; cChR = cBox[AB_BOXCH_TR]; cChM = cBox[AB_BOXCH_TM]; /* Create middle portion of line, then build entire line */ memset(cMiddle, cChM, 78); cMiddle[79] = '\0'; sprintf(cLine, "%c%s%c", cChL, cMiddle, cChR); /* Output line by line and output */ for (iLp = 1; iLp <= 24; iLp++) { cmd_text(cLine, 1, iLp, argv[3], argv[4]); /* If line 24, write line, push down, return to 24 and write line - prevent trailing cursor wrap. */ if (iLp == 24) { gotoxy(1, 24); insline(); gotoxy(1, 24); cmd_text(cLine, 1, iLp, argv[3], argv[4]); gotoxy(1, 24); } } iRet = AB_ERR_NONE; } } /* Clear Le Screen :D - not really needed, implemented as first parser test */ if (stricmp(argv[1], AB_CMD_CLS) == 0) { clrscr(); iRet = AB_ERR_NONE; } /* Version information */ if (stricmp(argv[1], AB_CMD_VERSION) == 0) { idself(); iRet = AB_ERR_NONE; } /* Were done, exit with errorcode */ return(iRet); }