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:
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);
}
Like this:
Like Loading...