Source Code
Project File EOE.PR
#system epoc img
#set epocinit=iplib
#model small jpi
#compile eoe.c
#compile tcom.c
#compile reply.c
#pragma link(hwif.lib)
#pragma link(misc.lib)
#link eoe
#include <hwif.h>
#include <p_file.h>
#include <p_gen.h>
#include <epoc.h>
#include <p_serial.h>
#include <p_date.h>
//#include <p_object.h> ///
//#include <rscfile.xg> ///
// This application uses Binary File IO with Random Access & Updates
#define bNew P_FSTREAM | P_FUPDATE | P_FRANDOM | P_FCREATE
#define bOld P_FSTREAM | P_FUPDATE | P_FRANDOM | P_FOPEN
#define A_MASK_HideSWin 0x01 // B0: Hide Status Window
#define A_MASK_Edit 0x02 // B1: Edit Mode (TAB pressed)
#define A_MASK_Connected 0x80 // B7: connected to host
#define C_MASK_AckOdd 0x01 // B0: Ack Odd/Even
#define C_MASK_RVI 0x02 // B1: request RVI (Receive state)
#define C_MASK_StopTx 0x04 // B2: supress Transmit state
#define L_MASK_ToFollow 1 // B0: Request To Follow if no stock
#define L_MASK_Cases 2 // B1: Quantity is in Cases
#define O_MASK_NoToFollow 1 // B0: No "To Follow" facility
#define O_MASK_CasesOnly 2 // B1: Case orders only
#define dX 7 // pixels between characters (cursor.width)
#define dY 8 // pixels between lines (font.height)
#define iMax 8 // max chars in Item Code
#define qMax 5 // max digits in Qty
#define pip 1,150
#define beep 6,320
#define rasp 3,5000
#define LinesPerBlock 10
// Record Layouts
typedef struct {
UINT oLine1; // bytes offset to first Line Record (=128)
UINT max; // maximum number of lines
UINT lines; // current number of lines
UINT state;
ULONG stamp; // time sent
UINT iblk; // length of RVI block
UBYTE oblk; // length of outcome block
TEXT fill1;
TEXT cref[9]; // (BCS) customer's Order Reference
TEXT host[31]; // (BCS) wholesaler's name
UINT acode; // Access Code
TEXT pword[6]; // (BCS) Password
TEXT fill2[34];
UINT undo;
TEXT fill3;
UBYTE opts; // wholesaler options (see O_MASKs)
UINT unsend;
unsigned int signal: 4; // 0=ring, 1=chime, 2=mute
unsigned int zlead: 4; // zero lead-in for PIP Code
UBYTE phone; // last dial selection
UBYTE flags; // default LINE.flags
UBYTE modem;
UBYTE bps;
TEXT dial[3][17]; // 3x (BCS) Host Phone No
} HEADER;
typedef struct {
UINT qty; // quantity ordered
UBYTE flags; // see L_MASKs
UBYTE rblk; // length of reply block
TEXT item[iMax]; // Item Code
} LINE;
typedef struct {
TEXT ver[2];
unsigned int class: 6;
unsigned int type: 2; // 0=direct, 1=generic, 2=exclusive, 3=(spare)
UWORD key;
} USER;
typedef struct {
USER user;
UWORD acode;
UBYTE pword[5];
TEXT cref[9];
} TxHEAD;
typedef struct {
UWORD qty; // quantity ordered
UBYTE bcd[4]; // item code & flags
} TxLINE;
typedef struct { // reply progress frame
UWORD line; // line number in source
TEXT flag;
UWORD qshort;
UBYTE description[44]; // max length including NUL
} RxLINE;
typedef struct { // reply trailer
UWORD shorts; // lines short+1 (0=Stock not checked)
UBYTE flag; // [EOT]
UBYTE outcome[24];
} RxTAIL;
typedef struct {
VOID *ccb;
VOID *timer;
VOID *dir;
WORD rxstate; // Rx completion status
WORD txstate; // Tx completion status
UBYTE state; // see C_MASKs
HEADER host;
union {
UBYTE data[256];
P_CRC crc;
TxHEAD head;
TxLINE line[LinesPerBlock];
RxLINE progress;
RxTAIL tail;
} frame;
} ASYNC;
typedef struct {
UWORD state; // Application Status flags (see A_MASKs)
LINE *pLine1;
VOID *fcb;
UINT MainW; // Id of Main Window
W_CURSOR spot;
INT Normal, Bold; // Graphics contexts
P_RECT boxB; // Main Border
P_RECT boxS; // ShowState window
TEXT *pHost; // -> BCS Host
LONG SeekTo;
VOID (*HotKey)(INT);
} CTLBLK;
// Global references defined in libraries
GLREF_D TEXT *DatCommandPtr;
GLREF_D TEXT *DatUsedPathNamePtr; // points to dsname[0]
GLREF_D TEXT *DatStatusNamePtr;
GLREF_D UWORD DatLocked;
GLREF_D WSERV_SPEC *wserv_channel;
#pragma save, call(reg_param=>(bx,cx,dx,di,si),\
reg_saved=>(bx,cx,dx,si,di,EPOC_SAVE))
extern void wsScreenExt(P_EXTENT *); // missing from wlib.h
#pragma call(reg_param =>(di,bx,cx),reg_saved =>(bx,cx,dx,si,di,EPOC_SAVE))
extern void PackLn(void *,void *);
#pragma call(reg_param =>(di,si,cx),reg_saved =>(bx,cx,dx,si,di,EPOC_SAVE))
extern void CRC16(unsigned short int *,unsigned char *,unsigned int);
extern void MovePw(unsigned char *,unsigned char *);
extern int FormItm(TEXT *,LINE *); // format Item Code
extern int FormTxt(TEXT *,TEXT *); // format Compressed ZTS
#pragma restore
// Global references defined in EOE
GLREF_D CTLBLK m;
GLREF_D ASYNC *com;
GLREF_D HEADER head;
GLREF_D WMSG_KEY key; // keyboard event structure
GLREF_C INT SwitchIf(INT, TEXT *); // prepare for possible file switch
GLREF_C INT SwitchFile(INT); // execute file switch & layout screen
GLREF_C VOID AgeFile(VOID); // rename file & prepare next
GLREF_C VOID Char(VOID); // keyboard event handler
GLREF_C VOID Wait(VOID); // wait for event
GLREF_C VOID StowAll(VOID); //rewrite all lines
GLREF_C VOID ShowDone(TEXT *msg); // show Done Msg
GLREF_C VOID ShowState(TEXT *); // show Send State
GLREF_C VOID TileWindow(INT tile); // size & clear window
GLREF_C VOID Flash(INT); // debug utility
// Global references defined in TCOM
#pragma save, ENTER_CALL
GLREF_C INT Call(TEXT *);
#pragma restore
GLREF_C VOID Connect(VOID); // wait for connect to host
// Global references defined in REPLY
GLREF_C VOID ShowReply(VOID); // display Reply Window
C Module EOE.C
#include "oe.h"
//#include "eoe.h" ///
// V1.2 1 Apr 93: Reject Send if <6000 bytes memory available.
// V1.3 11 May 93: Reject [Enter] on unmodified edits.
// V1.4 14 Oct 94: Display correct free memory when >64K.
// 16 Nov 94: Terminate other apps if memory too low for Send.
#define vMax 6 // max order lines in viewer window
// S3 Screen Layout pixel coords
#define ColL 4 // x for start of Line column
#define ColV1 32 // x for first vertical line
#define ColV2 99 // x for second vertical line
#define ColQ0 101 // x for Quantity prefix
#define ColQ1 109 // x for Quantity start
#define ColQ2 144 // x for Quantity end
#define ColQ3 152 // x for Case start
#define ColQ4 186 // x for Case end
#define XEsc 0 // x for Send Escape msg
#define YEsc 75 // y for Send Escape msg baseline
#define XSend 144 // x for Send Status window split
#define YSend 18 // y for Send Status
#define Head 7 // y for Header row
#define Foot 77 // y for Footer row
// Global variables defined here
GLDEF_D TEXT ** _cmds;
GLDEF_D H_MENU_DATA * _mdata;
GLDEF_D CTLBLK m = {0,NULL,NULL};
GLDEF_D ASYNC *com = NULL;
GLDEF_D HEADER head;
GLDEF_D WMSG_KEY key; // keyboard event structure
// Static variables local to this module
LOCAL_D INT cmd1, cmd2, enable; // workspace
LOCAL_D INT y1; // bottom y for 1st View row (base+1)
LOCAL_D TEXT dsname[P_FNAMESIZE+1]; // current file spec in ZTS form
LOCAL_D VOID *newfcb, *scb = NULL, *rcb;
LOCAL_D WORD soundstate, keystate, keybusy=FALSE;
LOCAL_D P_RECT boxD = {XEsc+36+26+6,YEsc+1-dY,0,YEsc+1}; //Disconnect msg
LOCAL_D P_RECT boxE = {XEsc+36,YEsc-9,XEsc+36+26,YEsc-9+14}; // Send Esc
LOCAL_D P_RECT boxI = {ColV1+8,Foot+1-dY,ColV2-4,Foot+1} ; // Item Code
LOCAL_D P_RECT boxN = {ColL,Foot+1-dY,ColV1-1,Foot+1} ; // Next Line
LOCAL_D P_RECT boxQ = {ColQ1,Foot+1-dY,ColQ2,Foot+1} ; // Quantity
LOCAL_D P_RECT boxR = {68,Head+1-dY,68+64,Head+1}; // Customer Reference
LOCAL_D LINE *pThis, *pNext;
LOCAL_D INT base, this, next;
LOCAL_D UBYTE weight[iMax-1] = {3,5,4,6,8,0,0};
LOCAL_D TEXT tws[32]; // transient work space
LOCAL_D TEXT exit1[] = "Done with phone";
LOCAL_D TEXT exit2[] = "Nothing to send!";
LOCAL_D TEXT *exit[3] = {exit1, exit1, exit2};
LOCAL_D H_MENU_DATA mCard[]= { // Main Menu
"File",6,"Edit",4,"Format",2,NULL
};
LOCAL_D TEXT *mList[]= { // Main Menu Presentation
"sSend...","vView reply...","oOpen...","nNew...","fFree space","xExit",
"rorder Ref...","aAccess...","dDelete all items...","",
"zZero lead-in...","tauto To Follow...",
NULL
};
LOCAL_D H_MENU_DATA rCard[]= { // Reply Menu
"File",5,"Edit",1,NULL
};
LOCAL_D TEXT *rList[]= { // Reply Menu Presentation
"oOpen...","nNew...","vView reply...","fFree space","xExit",
"uUndo send...",
NULL
};
// Procedure Prototypes local to this module
#pragma save, ENTER_CALL
LOCAL_C INT EOE(VOID);
LOCAL_C INT StartUp(VOID); // application initialization
#pragma restore
LOCAL_C INT ItemCode(VOID); // get Item Code
LOCAL_C INT CheckDigit(VOID); // verify Check Digit
LOCAL_C INT CheckLetter(INT); // verify Check Letter
LOCAL_C INT Qty(VOID); // get Quantity
LOCAL_C INT EditQty(VOID); // edit Quantity
LOCAL_C VOID InfoTF(LINE *); // inform about To Follow flag
LOCAL_C VOID View(VOID); // display order lines
LOCAL_C VOID ShowHost(VOID); // display current wholesaler's name
LOCAL_C VOID ShowTF(INT col, LINE *pLine); // display To Follow flag
LOCAL_C VOID ShowCase(INT col, LINE *pLine); // display Case flag
LOCAL_C VOID HotKeyM(INT); // Main Menu selection & HotKey handler
LOCAL_C VOID HotKeyR(INT); // Reply Menu selection & HotKey handler
LOCAL_C VOID Access(VOID); // define access to host
LOCAL_C VOID Void(VOID); // delete all lines
LOCAL_C VOID ChooseFile(INT); // File switching dialog handler
LOCAL_C VOID CRef(VOID); // edit Customer Reference
LOCAL_C VOID Send(VOID); // send order(s)
LOCAL_C VOID SwitchNewTF(VOID); // switch To Follow flag default
LOCAL_C VOID UnSend(VOID); // Undo Send
LOCAL_C VOID UnDo(VOID); // Undo last action
LOCAL_C VOID ZLeadIn(VOID); // set Zero lead-in for PIP Code
LOCAL_C VOID ButtonDance(P_RECT *, TEXT *);
LOCAL_C VOID User1(VOID); // Kybd exit proc (ItemCode & Qty)
LOCAL_C INT User2(VOID); // Kybd exit proc (EditQty)
LOCAL_C VOID Help(VOID); // Help system
LOCAL_C VOID ExecSysCmd(VOID); // S3 System Command handler
LOCAL_C VOID StowThis(VOID); // rewrite/append line
LOCAL_C VOID StowHead(VOID); // rewrite Header Record
LOCAL_C VOID UpCase(TEXT *); // convert BCS to upper case
LOCAL_C VOID Jingle(UWORD tune);
LOCAL_C ULONG FlashFree(VOID); // display free bytes on drive
//****************************************************************
GLDEF_C VOID main(VOID) {
INT outcome;
for (outcome=p_enter1(StartUp); outcome==1; )
outcome=p_enter1(EOE);
p_exit(outcome);
} //******************************** END main
LOCAL_C INT EOE(VOID) {
while (SwitchFile(head.state)) {ShowReply();}
base=0; this=head.lines; next=head.lines+1; View();
while(1) {
pNext=m.pLine1+head.lines;
pNext->flags=head.flags; pNext->rblk=0;
gPrintBoxText(&boxN,m.spot.ascent,G_TEXT_ALIGN_RIGHT,0,
tws,p_itob(tws,next)); // Line Number
if (ItemCode() && !EditQty() && Qty()) { // add new line
if ((p_toupper(key.keycode)=='C') || (head.opts & O_MASK_CasesOnly))
pNext->flags|=L_MASK_Cases;
head.lines=this=next++; StowThis(); View();
m.pLine1=f_realloc(m.pLine1,next*sizeof(LINE));
}
}
} //******************************** END EOE
LOCAL_C INT ItemCode(VOID) {
INT i,len,zlead;
if (m.state & A_MASK_Edit) return TRUE; // edit Qty
len=0; m.spot.pos.y=Foot; m.spot.pos.x=boxI.tl.x;
gClrRect(&boxI,G_TRMODE_CLR); // clear Item Code
ShowTF(Foot+1,pNext);
zlead=head.zlead; key.keycode='0';
while(1) {
if (len>=zlead) {zlead=0; Char();}
if (key.keycode==W_KEY_DELETE_LEFT) { // backsace
if (len) {
len--; m.spot.pos.x-=dX;
gPrintText(m.spot.pos.x,m.spot.pos.y," ",2);
if (len==2) {
m.spot.pos.x-=dX-1;
gPrintText(m.spot.pos.x,m.spot.pos.y," ",2);
}
continue;
}
}
else if (key.keycode==W_KEY_ESCAPE) return FALSE; // restart line
else if ((key.keycode==W_KEY_TAB) && head.lines) {
m.state|=A_MASK_Edit; return TRUE; // edit Qty
}
else if (len==7); // discard
else if ((key.keycode>='0') && (key.keycode<='9')) { // insert
gPrintText(m.spot.pos.x,m.spot.pos.y,(TEXT *)&key.keycode,1);
len++; *(pNext->item+len)=key.keycode;
m.spot.pos.x+=dX;
if (len==3) {
gPrintText(m.spot.pos.x,m.spot.pos.y,"-",1); m.spot.pos.x+=dX-1;
}
if (len<7) continue;
*(pNext->item)='0';
if(CheckDigit()==0) return TRUE;
}
else if (p_isalpha(key.keycode) && CheckLetter(len)) {
len++; *(pNext->item+len)=p_toupper(key.keycode);
gPrintBoxText(&boxI,m.spot.ascent,G_TEXT_ALIGN_RIGHT,0,
pNext->item+1,len);
i=iMax;
do { // right justify Item Code
*(pNext->item+(--i))=(len ? *(pNext->item+(len--)) : '0');
} while(i);
return TRUE;
}
User1();
}
} //******************************** END ItemCode
LOCAL_C INT CheckDigit(VOID) {
INT i, j, w;
i=j=w=0;
do {
if (j) {
j++; w=(*(pNext->item+j)&0xf)<<1;
if (w>9) w-=9;
}
j++; i+=w+(*(pNext->item+j)&0xf);
} while (j<7);
return i % 10;
} //******************************** END CheckDigit
LOCAL_C INT CheckLetter(INT j) {
INT i,w;
for (i=w=0;j;j--,i++) w+=weight[i] * (*(pNext->item+j)&0xf);
if (w && ((w % 26)+65 == p_toupper(key.keycode))) return TRUE;
return FALSE;
} //******************************** END CheckLetter
LOCAL_C INT Qty(VOID) {
INT len, view;
TEXT sQty[qMax+1], *psQty;
if (next>head.max) {
wInfoMsg("Maximum number of lines reached");
p_sound(beep); return 0;
}
len=0; *sQty='1';
while(1) {
m.spot.pos.x=ColQ2; view=len;
if (!len) {m.spot.pos.x-=dX; view=1;}
gPrintBoxText(&boxQ,m.spot.ascent,G_TEXT_ALIGN_RIGHT,0,sQty,view);
Char();
if (key.keycode==W_KEY_DELETE_LEFT) { // backsace
if (len) len--;
if (!len) *sQty='0';
continue;
}
else if ((key.keycode==W_KEY_RETURN)
|| (p_toupper(key.keycode)=='C')) { // enter line
*(sQty+view)=0; psQty=sQty;
if (!p_stog(&psQty,&(UWORD)(pNext->qty),10)) break;
len=0; *sQty='0'; // discard (qty too large)
}
else if (key.keycode==W_KEY_ESCAPE) { // restart line
pNext->qty=0; break;
}
else if (len==qMax); // discard
else if ((key.keycode>='0') && (key.keycode<='9')) { // insert
*(sQty+len)=key.keycode;
if (len || (key.keycode!='0')) len++;
continue;
}
User1();
}
gClrRect(&boxQ,G_TRMODE_CLR); // clear Qty
return pNext->qty;
} //******************************** END Qty
LOCAL_C INT EditQty(VOID) {
INT len, view;
P_RECT box;
TEXT sQty[qMax+1], *psQty;
if (m.state & A_MASK_Edit) m.state&=~A_MASK_Edit; // edit 'this'
else { // search for matching Item Code
for (this=1, pThis=m.pLine1; this<next; this++, pThis++)
if (!p_bcmp(pThis->item,iMax,pNext->item,iMax)) break;
if (this>=next) return FALSE; // no match (new item code)
}
View(); gClrRect(&boxI,G_TRMODE_CLR); // clear Item Code
pThis=m.pLine1-1+this;
box.br.y=y1+(this-base-1)*dY; box.tl.y=box.br.y-dY;
len=p_gtob(sQty,pThis->qty,10);
m.spot.pos.y=box.br.y-1;
enable=FALSE;
while(1) {
m.spot.pos.x=ColQ2; view=len;
if (!len) {m.spot.pos.x-=dX; view=1;}
box.tl.x=ColQ1; box.br.x=ColQ2;
gPrintBoxText(&box,m.spot.ascent,G_TEXT_ALIGN_RIGHT,0,sQty,view);
Char();
switch (key.keycode) {
case W_KEY_DELETE_LEFT: // backsace
if (len) len--;
enable=TRUE; break;
case W_KEY_ESCAPE: // cancel
View(); return TRUE;
case '-':
if ((!enable) && (pThis->qty>1)) {
pThis->qty--;
StowThis(); m.state|=A_MASK_Edit; return TRUE;
}
User2(); break;
case '+':
if ((!enable) && (pThis->qty<0xffff)) {
pThis->qty++;
StowThis(); m.state|=A_MASK_Edit; return TRUE;
}
User2(); break;
default:
if (enable && (len<qMax)
&& (key.keycode>='0') && (key.keycode<='9')) { // insert
*(sQty+len)=key.keycode;
if (len || (key.keycode!='0')) len++;
break;
}
if (!User2()) break; // discard keystroke
if (enable) { // update Qty
*(sQty+view)=0; psQty=sQty;
if (p_stog(&psQty,&(UWORD)(pThis->qty),10)) { // Qty too large
len=p_gtob(sQty,pThis->qty,10);
enable=FALSE; p_sound(beep); break; // discard
}
if (pThis->qty) StowThis();
else { // delete line
m.pLine1=p_adjust(m.pLine1,(this-1)*sizeof(LINE),-sizeof(LINE));
if (m.pLine1==NULL) p_leave(E_GEN_NOMEMORY);
--next; --head.lines; head.undo=head.unsend=0; StowAll();
p_sound(pip); wInfoMsg("Line erased");
}
}
if (!head.lines) m.state&=~A_MASK_Edit;
if (m.state & A_MASK_Edit) {this=cmd1; base+=cmd2;}
else View();
return TRUE;
}
}
} //******************************** END EditQty
LOCAL_C VOID InfoTF(LINE *pLine) {
if (pLine->flags & L_MASK_ToFollow) wInfoMsg("To follow if no stock");
else wInfoMsg("Only if in stock");
} //******************************** END InfoTF
GLDEF_C INT SwitchIf(INT mode, TEXT *newname) {
INT outcome, ret;
HEADER newhead;
TEXT name[P_FNAMESIZE+1];
do {
if (mode=='S') { // send
p_close(m.fcb); m.fcb=NULL;
if (com->dir==NULL) f_open(&com->dir,newname,P_FDIR);
outcome=p_iow(com->dir,P_FREAD,name,NULL);
if (outcome==E_FILE_EOF) return outcome; // no more files
f_leave(outcome);
f_fparse(name,newname,name,NULL);
}
else p_scpy(name,newname);
hEnsurePath(name);
outcome=p_open(&newfcb,name,mode=='C'? bNew: bOld);
if (!outcome) { // newfcb is open
ret=p_read(newfcb,&newhead,sizeof(HEADER));
if ((ret==E_FILE_EOF) && (mode=='C')) { // end of (empty) file
newhead=head;
newhead.oLine1=sizeof(HEADER);
newhead.lines=newhead.state=newhead.iblk=*newhead.cref=0;
if (!newhead.max) newhead.max=200;
f_write(newfcb,&newhead,sizeof(HEADER));
ret=sizeof(HEADER);
}
if ((ret!=sizeof(HEADER))
|| (newhead.oLine1!=sizeof(HEADER))
|| ((mode=='S') && ((newhead.lines==0) || newhead.state))) {
outcome=E_FILE_INVALID; p_close(newfcb);
}
else { // (file switch is now committed)
head=newhead;
p_scpy(dsname,name);
p_close(m.fcb); m.fcb=newfcb;
return outcome;
}
}
} while (mode=='S'); // skip invalid files during Send
return (mode=='M')? outcome: uErrorValue(outcome);
} //******************************** END SwitchIf
GLDEF_C INT SwitchFile(INT layout) {
UINT mem;
TEXT string[32];
p_free(m.pLine1); m.pLine1=NULL;
mem=head.lines*sizeof(LINE);
hSetUpStatusNames(dsname); // notify S3 that file has changed
wsUpdate(WS_UPDATE_NAME); // update name in Status Window
switch (layout) {
case -1: // layout Send Window & connect to host
if (!(m.state & A_MASK_Connected)) {
m.boxS.tl.x=m.boxB.tl.x; m.boxS.br.x=m.boxB.br.x;
m.boxS.tl.y=YSend-dY; m.boxS.br.y=YSend;
Connect();
}
p_atos(string,"File %s (%u lines):",DatStatusNamePtr,head.lines);
m.boxS.tl.x=m.boxB.tl.x; m.boxS.br.x=XSend; ShowState(string);
m.boxS.tl.x=XSend; m.boxS.br.x=m.boxB.br.x; ShowState("Trying to log on");
break;
case 0: // layout Main Window
m.HotKey=HotKeyM; _cmds=mList; _mdata=mCard;
mCard[2].nlines=(head.opts & O_MASK_NoToFollow)? 1: 2;
mem+=sizeof(LINE);
gSetGC0(m.Bold);
TileWindow(TRUE); // clear Tile Window
m.boxB.tl.y=Head+1;
gBorderRect(&m.boxB,W_BORD_SHADOW_S | W_BORD_SHADOW_ON);
gPrintText(ColL,Head,"Order Ref:",10);
gPrintText(ColL,17,"Line Item Code Qty",28);
gDrawLine(1,18,m.boxB.br.x,18);
gDrawLine(1,Foot-dY-1,m.boxB.br.x,Foot-dY-1);
gDrawLine(ColV1,Head+2,ColV1,m.boxB.br.y);
gDrawLine(ColV2,Head+2,ColV2,m.boxB.br.y);
gPrintText(68,Head,head.cref+1,*head.cref); // Customer reference
break;
default: // layout Reply Window
m.HotKey=HotKeyR; _cmds=rList; _mdata=rCard;
mem+=head.iblk+head.oblk+sizeof(UWORD); // (UWORD for shorts & ZTS)
gSetGC0(m.Normal);
TileWindow(FALSE); // clear Full Window
m.boxB.tl.y=Head+1+dY+2; m.boxB.br.y-=dY+1;
gBorderRect(&m.boxB,W_BORD_SHADOW_S | W_BORD_SHADOW_ON);
gDrawLine(1,30,m.boxB.br.x,30);
}
m.pLine1=f_alloc(mem);
if (head.lines) { // fetch all lines +iblk +(maybe)oblk
m.SeekTo=head.oLine1; f_seek(m.fcb,P_FABS,&m.SeekTo);
f_read(m.fcb,m.pLine1,mem);
}
m.pHost=(head.state)? (TEXT *)(m.pLine1+head.lines): head.host;
ShowHost();
return head.state;
} //******************************** END SwitchFile
GLDEF_C VOID AgeFile(VOID) {
TEXT newname[P_FNAMESIZE+1];
StowAll();
p_close(m.fcb); m.fcb=NULL;
if (!head.state) return;
f_fparse(".BAK",dsname,newname,NULL);
if (p_scmp(dsname,newname)) {
head.state=0; // forestall recall if ageing fails
p_close(com->dir); com->dir=NULL;
p_delete(newname);
f_leave(p_rename(dsname,newname));
f_leave(SwitchIf('C',dsname));
}
} //******************************** END AgeFile
LOCAL_C VOID View(VOID) {
INT rows,i;
LINE *pLine;
P_RECT box; // Next Line
TEXT flag, string[iMax];
if (this < 1) this=1;
if (this > head.lines) this=head.lines;
rows=head.lines;
if (rows > vMax) { // full screen
if (base < 0) base=0;
else if (base > rows-vMax) base=rows-vMax;
rows=vMax;
if (this <= base) base=this-1;
else if (this > base+vMax) base=this-vMax;
}
else { // partial screen
base=0;
if (rows<vMax) {
box.br.y=Foot-1-(rows+1)*dY; box.tl.y=Foot-1-(vMax+1)*dY;
box.br.x=boxN.br.x; box.tl.x=boxN.tl.x; gClrRect(&box,G_TRMODE_CLR);
box.br.x=boxI.br.x; box.tl.x=boxI.tl.x; gClrRect(&box,G_TRMODE_CLR);
box.br.x=ColQ4; box.tl.x=ColQ0; gClrRect(&box,G_TRMODE_CLR);
}
}
y1=Foot-1-rows*dY;
for (i=base, box.br.y=y1; rows; rows--, i++, box.br.y+=dY) {
box.tl.y=box.br.y-dY;
box.tl.x=boxN.tl.x; box.br.x=boxN.br.x;
gPrintBoxText(&box,m.spot.ascent,G_TEXT_ALIGN_RIGHT,0,
tws,p_itob(tws,i+1)); // Line number
pLine=m.pLine1+i;
box.tl.x=boxI.tl.x; box.br.x=boxI.br.x;
gPrintBoxText(&box,m.spot.ascent,G_TEXT_ALIGN_RIGHT,0,
string,FormItm(string,pLine)); // Item Code
flag=(pLine->flags & L_MASK_ToFollow)? '*': ' ';
box.tl.x=ColQ0; box.br.x=ColQ1;
gPrintBoxText(&box,m.spot.ascent,G_TEXT_ALIGN_LEFT,0,&flag,1); // Flag
box.tl.x=ColQ1; box.br.x=ColQ2;
gPrintBoxText(&box,m.spot.ascent,G_TEXT_ALIGN_RIGHT,0,
tws,p_gtob(tws,pLine->qty,10)); // Quantity
ShowCase(box.br.y,pLine); // Case
}
} //******************************** END View
LOCAL_C VOID ShowHost(VOID) {
TEXT string[40];
*p_bcpy(p_scpy(string,(head.state)? "From: ": "To: "),
m.pHost+1,*m.pHost)=0;
wInfoMsg(string);
} //******************************** END ShowHost
LOCAL_C VOID ShowTF(INT col, LINE *pLine) {
TEXT flag;
P_RECT box;
flag=(pLine->flags & L_MASK_ToFollow)? '*': ' ';
box.br.y=col; box.tl.y=col-dY;
box.tl.x=ColQ0; box.br.x=ColQ1;
gPrintBoxText(&box,m.spot.ascent,G_TEXT_ALIGN_LEFT,0,&flag,1);
} //******************************** END ShowTF
LOCAL_C VOID ShowCase(INT col, LINE *pLine) {
UINT len=0;
TEXT *pCase="";
P_RECT box;
if (pLine->flags & L_MASK_Cases)
if (pLine->qty > 1) {pCase="Cases"; len=5;}
else {pCase="Case"; len=4;}
box.br.y=col; box.tl.y=col-dY;
box.tl.x=ColQ3; box.br.x=ColQ4;
gPrintBoxText(&box,m.spot.ascent,G_TEXT_ALIGN_RIGHT,0,pCase,len);
} //******************************** END ShowCase
LOCAL_C VOID HotKeyM(INT keycode) {
switch (keycode) {
case 'a': // Access
Access(); break;
case 't': // To follow flag
SwitchNewTF(); break;
case 'd': // Delete all items
Void(); break;
case 'f':
FlashFree(); break;
case 'n': // New
ChooseFile('C'); break;
case 'o': // Open
ChooseFile('O'); break;
case 'r': // order Reference
CRef(); break;
case 's': // Send
Send(); break;
case 'u': // Undo
UnDo(); break;
case W_KEY_MODE:
case 'v': // View reply
ChooseFile('V'); break;
case 'x':
p_leave(0);
case 'z':
ZLeadIn(); break;
}
} //******************************** END HotKeyM
LOCAL_C VOID HotKeyR(INT keycode) {
switch (keycode) {
case 'f':
FlashFree(); break;
case W_KEY_MODE:
case 'o': // Open
ChooseFile('O'); break;
case 'n': // New
ChooseFile('C'); break;
case 'u': // Undo send
UnSend(); break;
case 'v': // View reply
ChooseFile('V'); break;
case 'x':
p_leave(0);
}
} //******************************** END HotKeyR
LOCAL_C VOID Access(VOID) {
INT i;
UWORD modem, bps, backord, cases;
LONG Max, ACode;
TEXT title[10+sizeof(head.host)], PWord[9];
H_DI_EDIT phone[3], host;
H_DI_TEXT etc;
H_DI_NUMBER max, acode;
H_DI_XINPUT pword;
*p_bcpy(p_bcpy(title,"Access to ",10),head.host+1,*head.host)=0;
if (uOpenDialog(title)) return;
modem=head.modem+1; bps=head.bps+1;
for (i=0;i<3;i++) {
phone[i].str=head.dial[i]; phone[i].len=sizeof(head.dial[0])-1;
if (uAddDialogItem(H_DIALOG_EDIT,"Phone No",phone+i)) return;
}
etc.type=H_DTEXT_SELECTABLE; etc.str="\xAPIN etc...";
if (uAddChoiceList("Modem",&modem,
"Hayes (Tone dial)",
"Hayes (Pulse dial)",
"Manual",
"VX-543",
NULL)
|| uAddChoiceList("Speed (bps)",&bps,
"V21(300)",
"V22(1200)",
"V22bis(2400)",
NULL)
|| uAddDialogItem(H_DIALOG_TEXT,NULL,&etc)) return;
i=uRunDialog();
if (i>0) { // did not escape or fail
head.modem=modem-1; head.bps=bps-1;
Max=head.max; ACode=head.acode;
backord=(head.opts & O_MASK_NoToFollow)? 1: 2;
cases=(head.opts & O_MASK_CasesOnly)? 2: 1;
if (i==7) { // continue to second dialog screen
host.str=head.host; host.len=sizeof(head.host)-1;
max.value=&Max; max.low=1; max.high=254;
acode.value=&ACode; acode.low=0L; acode.high=99999L;
pword.str=PWord; *PWord=0;
if (uOpenDialog("EOE \xB8 1994 J A Templeman. Version 1.4")
|| uAddDialogItem(H_DIALOG_EDIT,"Wholesaler",&host)
|| uAddDialogItem(H_DIALOG_NUMBER,"Max Lines",&max)
|| uAddChoiceList("Backorders",&backord,"No","Yes",NULL)
|| uAddChoiceList("Cases only",&cases,"No","Yes",NULL)
|| uAddDialogItem(H_DIALOG_NUMBER,"Access Code",&acode)
|| uAddDialogItem(H_DIALOG_XINPUT,"Password",&pword)) return;
uRunDialog();
if (*PWord==(sizeof(head.pword)-1)) MovePw(head.pword,PWord);
}
head.max=(UINT)Max; head.acode=(UINT)ACode;
head.opts&=~(O_MASK_NoToFollow | O_MASK_CasesOnly);
mCard[2].nlines=2;
if (backord==1) {
head.opts|=O_MASK_NoToFollow; mCard[2].nlines=1;
}
if (cases==2) head.opts|=O_MASK_CasesOnly;
StowHead();
}
} //******************************** END Access
LOCAL_C VOID Void(VOID) {
INT i;
TEXT string[32];
H_DI_TEXT note1;
if (!head.lines) return;
*p_bcpy(string+10+p_itob(p_bcpy(string,
"Erase all ",10),head.lines)," lines?",7)=0;
note1.type=H_DTEXT_ALIGN_CENTRE | H_DTEXT_UNDERLINE;
note1.str="\x25(to erase one line, set its Qty to 0)";
if (uOpenDialog(string)
|| uAddDialogItem(H_DIALOG_TEXT,NULL,¬e1)
|| uAddButtonList("No",'n',"Yes",W_KEY_DELETE_LEFT,NULL)) return;
i=uRunDialog();
if ((i<=0) || (i!=W_KEY_DELETE_LEFT)) return;
head.undo=head.lines; head.lines=0; StowHead(); p_leave(1);
} //******************************** END Void
LOCAL_C VOID ChooseFile(INT mode) {
TEXT dsname[P_FNAMESIZE+2];
H_DI_FSEL open;
H_DI_TEXT name;
open.fname=dsname;
f_fparse((mode=='V')? ".BAK": ".EOE",DatUsedPathNamePtr,dsname+1,NULL);
*dsname=p_slen(dsname+1);
if (key.keycode==W_KEY_MODE) {
if (!SwitchIf('M',dsname+1)) p_leave(1);
wInfoMsg("File not found"); return;
}
do {
if (mode=='C') {
if (uOpenDialog("Create new order file")) return;
if (*head.host) {
name.type=H_DTEXT_ALIGN_CENTRE | H_DTEXT_UNDERLINE;
name.str=head.host;
if (uAddDialogItem(H_DIALOG_TEXT,NULL,&name)) return;
}
open.flags=H_FILE_NEW_EDITOR |
H_FILE_NO_AUTOQUERY | H_FILE_SET_DEFEXT;
}
else {
if (uOpenDialog((mode=='V')?
"View wholesaler's reply": "Reopen existing order file")) return;
open.flags=H_FILE_PICK_SELECTOR |
H_FILE_RESTRICT_LIST | H_FILE_SET_DEFEXT;
}
if (uAddDialogItem(H_DIALOG_FSEL,"File:",&open)
|| uRunDialog()<=0) return;
dsname[1+*dsname]=0;
} while(SwitchIf(mode,dsname+1));
p_leave(1); // switch files
} //******************************** END ChooseFile
LOCAL_C VOID CRef(VOID) {
H_DI_EDIT ref;
ref.str=head.cref; ref.len=sizeof(head.cref)-1;
if (uOpenDialog(NULL)
|| uAddDialogItem(H_DIALOG_EDIT,"This order reference",&ref)
|| uRunDialog()<=0) return;
UpCase(head.cref); StowHead();
gPrintBoxText(&boxR,m.spot.ascent,G_TEXT_ALIGN_LEFT,0,head.cref+1,*head.cref);
} //******************************** END CRef
LOCAL_C VOID Send(VOID) {
HANDLE h;
INT outcome;
UWORD phone, signal;
H_DI_TEXT note1;
H_DI_FSEL spec;
union {
TEXT pName[E_MAX_NAME+2];
TEXT title[8+sizeof(head.host)];
TEXT oldname[P_FNAMESIZE+1];
} u1;
union {
TEXT spec[P_FNAMESIZE+2];
TEXT string[E_MAX_ERROR_TEXT_SIZE];
} u2;
if (*head.pword!=(sizeof(head.pword)-1)) {
wInfoMsg("Please complete setup"); Access(); return;
}
while (FlashFree()<6000L) {
note1.type=H_DTEXT_ALIGN_CENTRE | H_DTEXT_UNDERLINE;
note1.str="\35Close all other applications?";
if (uOpenDialog("Send needs more system memory.")
|| uAddDialogItem(H_DIALOG_TEXT,NULL,¬e1)
|| uAddButtonList("No",'n',"Yes",'y',NULL)
|| (uRunDialog()!='y')) return;
for (h=0; (h=p_pfind(h,"*",u1.pName))>=0;) {
if (p_bcmp(u1.pName,4,"SYS$",4) && p_bcmp(u1.pName,4,"TIME",4)
&& (h!=p_getpid())) {
p_atos(u2.string,"Closing %s",u1.pName);
wInfoMsg(u2.string);
if (!p_pterminate(h,0)) h=0; // reset to 1st process
}
}
}
note1.type=H_DTEXT_ALIGN_CENTRE | H_DTEXT_BOLD;
note1.str="\26Press Enter to connect";
phone=head.phone+1; signal=head.signal+1;
p_bcpy(u2.spec+1,dsname,*u2.spec=p_slen(dsname));
spec.fname=u2.spec;
spec.flags=H_FILE_NEW_EDITOR | H_FILE_SET_DEFEXT
| H_FILE_CAN_WILDCARD | H_FILE_NO_AUTOQUERY;
*p_bcpy(p_bcpy(u1.title,"Send to ",8),head.host+1,*head.host)=0;
if (uOpenDialog(u1.title)
|| uAddDialogItem(H_DIALOG_TEXT,NULL,¬e1)
|| uAddChoiceList("Dial",&phone,
"1st \5 line","2nd \5 line","3rd \5 line","no autodial",NULL)
|| uAddDialogItem(H_DIALOG_FSEL,"File(s):",&spec)
|| uAddChoiceList("Signal at end",&signal,"Ring","Chime","Mute",NULL)
|| (uRunDialog()<=0)) return;
u2.spec[1+*u2.spec]=0;
p_scpy(u1.oldname,dsname); // save active file name
head.phone=--phone; head.signal=--signal; StowHead();
p_free(m.pLine1); m.pLine1=NULL;
TileWindow(FALSE); // clear Full Window
m.boxB.br.y=Head+1; boxD.br.x=m.boxB.br.x;
gPrintBoxText(&m.boxB,m.spot.ascent,G_TEXT_ALIGN_CENTRE,0,
head.host+1,*head.host);
m.boxB.tl.y=YSend+1; m.boxB.br.y=YEsc-10;
gBorderRect(&m.boxB,W_BORD_SHADOW_S | W_BORD_SHADOW_ON);
gPrintText(XEsc,YEsc,"Press",5);
wDrawButton(&boxE,"Esc",FALSE); ShowDone("to cancel order");
outcome=p_enter2(Call,u2.spec+1);
if (com==NULL) p_leave(outcome); // (out of memory)
p_close(com->ccb); p_close(com->timer); wCancelBusyMsg();
AgeFile();
p_close(com->dir); p_free(com); com=NULL;
f_leave(SwitchIf('O',u1.oldname)); // restore original active file
if ((outcome==1) && !(m.state & A_MASK_Connected)) p_leave(1);
m.state&=~A_MASK_Connected;
if (outcome<0) p_errs(u2.string,outcome);
else p_scpy(u2.string,exit[outcome]);
gSetGC0(m.Bold); ShowDone(u2.string);
switch (outcome) {
case 1: // user escaped
case 2: // nothing to send
case E_FILE_LOCKED: // in use
case E_FILE_DEVICE: // not plugged in
break; // skip jingle
default:
Jingle(signal);
}
wFlush();
while(1) {
Wait();
if (soundstate!=E_FILE_PENDING) {p_close(scb); scb=NULL;}
}
} //******************************** END Send
LOCAL_C VOID SwitchNewTF(VOID) {
INT i;
H_DI_TEXT note1;
if (head.opts & O_MASK_NoToFollow) return;
note1.type=H_DTEXT_ALIGN_CENTRE | H_DTEXT_UNDERLINE;
note1.str="\x25if wholesaler has insufficient stock?";
if (uOpenDialog("Prefer new lines to follow automatically")
|| uAddDialogItem(H_DIALOG_TEXT,NULL,¬e1)
|| uAddButtonList("No",'n',"Yes",'y',NULL)) return;
i=uRunDialog(); if (i<=0) return; // escaped or failed
head.flags&=~L_MASK_ToFollow; pNext->flags&=~L_MASK_ToFollow;
if (i=='y') {
head.flags|=L_MASK_ToFollow; pNext->flags|=L_MASK_ToFollow;
}
StowHead(); ShowTF(Foot+1,pNext); InfoTF(pNext);
} //******************************** END SwitchNewTF
LOCAL_C VOID UnDo(VOID) {
if (head.undo) {
head.lines=head.undo; head.undo=0;
StowHead(); p_leave(1);
}
if (head.unsend) {
head.state=head.unsend; head.unsend=0;
StowHead(); p_leave(1);
}
} //******************************** END UnDo
LOCAL_C VOID UnSend(VOID) {
H_DI_TEXT note1;
note1.type=H_DTEXT_ALIGN_CENTRE | H_DTEXT_UNDERLINE;
note1.str="\40for retransmission to wholesaler";
if (uOpenDialog("\"Undo send\" restores this order")
|| uAddDialogItem(H_DIALOG_TEXT,NULL,¬e1)
|| uAddButtonList("STOP",'n',"Undo Send",'y',NULL)
|| (uRunDialog()!='y')) return;
head.unsend=head.state; head.state=0; StowHead(); p_leave(1);
} //******************************** END UnSend
LOCAL_C VOID ZLeadIn(VOID) {
LONG zlead;
H_DI_NUMBER lead;
zlead=head.zlead; lead.value=&zlead; lead.low=0L; lead.high=4L;
if (uOpenDialog(NULL)
|| uAddDialogItem(H_DIALOG_NUMBER,"How many PIP Code 0's preset?",&lead)
|| uRunDialog()<=0) return;
head.zlead=(unsigned int)zlead; StowHead(); p_leave(1);
} //******************************** END ZLeadIn
GLDEF_C VOID Char(VOID) {
while(1) {
wTextCursor(m.MainW,&m.spot); // Cursor ON
DatLocked--; Wait(); DatLocked++;
wEraseTextCursor(); // Cursor OFF
if (key.keycode & W_EVENT_KEY) { // Not a keypress
if (key.keycode==CONS_EVENT_COMMAND) ExecSysCmd();
else if ((key.keycode==CONS_EVENT_FOREGROUND)
|| (key.keycode==CONS_EVENT_ON_OFF))
ShowHost();
}
else if (key.keycode & W_SPECIAL_KEY)
m.HotKey(key.keycode & (~W_SPECIAL_KEY));
else {
switch (key.keycode) {
case W_KEY_MODE:
m.HotKey(key.keycode); break;
case W_KEY_MENU:
if (key.modifiers & W_CTRL_MODIFIER) // switch Status Window
if ((m.state^=A_MASK_HideSWin) & A_MASK_HideSWin) wsDisable();
else wsEnable();
else {
mList[9]=(head.undo)? "uUndo delete":
(head.unsend)? "uUndo \"undo send\"": "u(can't Undo)";
m.HotKey(uPresentMenus());
}
break;
default: return;
}
}
}
} //******************************** END Char
GLDEF_C VOID Wait(VOID) {
while(1) {
if (keybusy) wFlush();
else {keybusy=TRUE; uGetKeyA(&keystate,&key);} // start keyboard
p_iowait();
if (keystate!=E_FILE_PENDING) { // keystroke
keybusy=FALSE;
if (!DatLocked) return; // process keystroke
if (key.keycode==W_KEY_ESCAPE) break;
}
else if (DatLocked) return; // process event
}
if (scb!=NULL) {p_close(scb); scb=NULL;} // abort jingle
p_sound(pip); gSetGC0(m.Bold); ButtonDance(&boxE,"Esc");
p_leave(1); // Esc pressed
} //******************************** END Wait
LOCAL_C VOID ButtonDance(P_RECT *box, TEXT *name) {
wDrawButton(box,name,TRUE);
wFlush(); p_sleep(1);
wDrawButton(box,name,FALSE);
} //******************************** END ButtonDance
LOCAL_C VOID User1(VOID) {
if (uKeyPressOutstanding()) return;
switch (key.keycode) {
case W_KEY_UP:
base--; this--; break;
case W_KEY_DOWN:
base++; this++; break;
case W_KEY_HOME:
this=0; break;
case W_KEY_END:
this=next; break;
case W_KEY_PAGE_UP:
base-=vMax; this-=vMax; break;
case W_KEY_PAGE_DOWN:
base+=vMax; this+=vMax; break;
case W_KEY_HELP:
Help(); return;
default:
if ((key.keycode=='*') && !(head.opts & O_MASK_NoToFollow)) {
pNext->flags^=L_MASK_ToFollow;
InfoTF(pNext); ShowTF(Foot+1,pNext); break;
}
if (key.keycode<W_KEY_MODE) p_sound(beep);
return; // reject keystroke
}
View();
} //******************************** END User1
LOCAL_C INT User2(VOID) {
if (uKeyPressOutstanding()) return FALSE;
cmd1=this; cmd2=0;
switch (key.keycode) {
case W_KEY_UP:
if (key.modifiers & W_SHIFT_MODIFIER) cmd2=-1; // Scroll Lock
cmd1--; break;
case W_KEY_DOWN:
if (key.modifiers & W_SHIFT_MODIFIER) cmd2=1; // Scroll Lock
cmd1++; break;
case W_KEY_HOME:
cmd1=0; break;
case W_KEY_END:
cmd1=next; break;
case W_KEY_PAGE_UP:
cmd1-=vMax; cmd2=-vMax; break;
case W_KEY_PAGE_DOWN:
cmd1+=vMax; cmd2=vMax; break;
case 'c': // switch Case flag
case 'C':
if (!(head.opts & O_MASK_CasesOnly)) pThis->flags^=L_MASK_Cases;
enable=TRUE; break;
case W_KEY_HELP:
Help(); return FALSE;
case W_KEY_TAB: // update
return TRUE;
case W_KEY_RETURN: // update
if (enable) return TRUE;
default:
if ((key.keycode=='*') && !(head.opts & O_MASK_NoToFollow)) {
pThis->flags^=L_MASK_ToFollow;
InfoTF(pThis); enable=TRUE; break;
}
if (key.keycode<W_KEY_MODE) {
if (!enable) wInfoMsg("Use +, -, Delete, \30, \31, Tab or Esc");
p_sound(beep);
}
return FALSE; // reject keystroke
}
m.state|=A_MASK_Edit; return TRUE;
} //******************************** END User2
GLDEF_C VOID ShowDone(TEXT *msg) {
gPrintBoxText(&boxD,m.spot.ascent,G_TEXT_ALIGN_LEFT,0,msg,p_slen(msg));
} //******************************** END ShowDone
GLDEF_C VOID ShowState(TEXT *msg) {
gPrintBoxText(&m.boxS,m.spot.ascent,G_TEXT_ALIGN_CENTRE,0,msg,p_slen(msg));
} //******************************** END ShowState
LOCAL_C VOID Help(VOID) {
INT choice;
choice=uDialogMenu("\30 \31 for help on:",
"Keyboard",
"Item Code",
"Quantity",
"Dialog boxes",
"Sounds",
"Sending",
NULL);
switch (choice) {
case 2:
uDisplayText("[Delete] backs cursor one space.",
"[Esc] clears or cancels current action.",
"[Tab] jumps cursor between new/alter line.",
"[Menu] then \30 \31 \32 \33 select tools and show",
"tool \"Hot Keys\" (eg: [ \2 ]+[X] to exit).",
"\30 \31 PgUp PgDn Home End scroll order view.",
NULL);
break;
case 3:
uDisplayText("Item code is PIP Code (7 digits)",
"or Wholesaler Code (upto 5 digits+letter).",
"Enter the code on the bottom line: if it's",
"already ordered its line is shown and",
"may be amended or removed (see Qty help).",
"[*] alters action preferred if wholesaler",
"has insufficient stock.",
NULL);
break;
case 4:
uDisplayText("To set qty in new lines: after Item Code",
"enter UNITS required and press [Enter],",
"or enter CASES required and press [C].",
"To alter qty: Tab \30 \31 cursor onto line,",
"press Delete, reenter, Tab or \30 \31 again.",
"Line is erased by setting its qty to 0.",
"[C] alters CASE/UNITS, [*] alters t/f",
NULL);
break;
case 5:
uDisplayText("Dialog boxes \"pop up\" from menu selection",
"or (more directly) from a \"hot key\". Edit",
"box contents using \30 \31 \32 \33 to move cursor.",
"Don't press [Enter] until all changes done!",
"[Esc] undoes all changes in the box.",
"\21value\20 without cursor is a \"spin box\":",
"press [Tab] to reveal all its values.",
NULL);
break;
case 6:
uDisplayText("[System][Menu]\"S\" sets all sound on/off.",
"A \"pip\" confirms your action accepted.",
"A \"beep\" means key pressed was discarded.",
"A \"rasp\" (during Send) means delay due to",
"phone line (e.g. an extension in use).",
NULL);
break;
case 7:
uDisplayText("Use mains adaptor to send, if possible.",
"After successful send file is cleared, then",
"[Menu]\"View\" or [Pgm button] shows reply.",
"Cancelling reply never cancels order.",
NULL);
break;
}
} //******************************** END Help
LOCAL_C VOID ExecSysCmd(VOID) {
TEXT command[P_FNAMESIZE+2];
wGetCommand(command);
if (*command=='X') p_leave(0); // shutdown
if (!SwitchIf(*command,command+1)) p_leave(1); // switch files
} //******************************** END ExecSysCmd
LOCAL_C VOID StowThis(VOID) {
m.SeekTo=head.oLine1+(this-1)*sizeof(LINE);
f_seek(m.fcb,P_FABS,&m.SeekTo);
f_write(m.fcb,m.pLine1+(this-1),sizeof(LINE));
p_sound(pip); head.undo=head.unsend=0; StowHead();
} //******************************** END StowThis
LOCAL_C VOID StowHead(VOID) {
m.SeekTo=0; f_seek(m.fcb,P_FABS,&m.SeekTo);
f_write(m.fcb,&head,sizeof(HEADER));
} //******************************** END StowHead
GLDEF_C VOID StowAll(VOID) {
if (m.fcb!=NULL) {
StowHead();
if (m.pLine1!=NULL) f_write(m.fcb,m.pLine1,head.lines*sizeof(LINE));
}
} //******************************** END StowAll
LOCAL_C VOID UpCase(TEXT *source) {
UINT i=1;
for (;i<=*source;i++) *(source+i)=p_toupper(*(source+i));
} //******************************** END UpCase
LOCAL_C VOID Jingle(UWORD tune) {
if ((tune<2) && (!p_open(&scb,"SND:",-1)))
p_ioc4(scb,E_FALARM,&soundstate,&tune);
} //******************************** END Jingle
GLDEF_C VOID TileWindow(INT tile) {
W_WINDATA wd = {0,0};
if (tile) wsScreenExt(&wd.extent); // exclude Status Window
else {
wd.extent.width=wserv_channel->conn.info.pixels.x;
wd.extent.height=wserv_channel->conn.info.pixels.y;
}
wSetWindow(m.MainW,W_WIN_EXTENT,&wd);
if (!(m.state & A_MASK_HideSWin)) wsEnable(); // show Status Window
m.boxB.tl=wd.extent.tl;
m.boxB.br.x=wd.extent.width; m.boxB.br.y=wd.extent.height;
gClrRect(&m.boxB,G_TRMODE_CLR); // clear Main Window
} //******************************** END TileWindow
LOCAL_C ULONG FlashFree(VOID) {
TEXT string[40];
P_DINFO info;
if (!p_dinfo(dsname,&info)) {
p_atos(string,"%lu bytes free",info.free);
wInfoMsg(string);
return info.free;
}
return 0L;
} //******************************** END FlashFree
GLDEF_C VOID Flash(INT i) {
TEXT string[8];
*(string+p_itob(string,i))=0; wInfoMsg(string);
} //******************************** END Flash
LOCAL_C INT StartUp(VOID) {
//TEXT buf[64]; ///
G_GC gc;
G_FONT_INFO font;
DatLocked=1; uCommonInit();
m.MainW=uFindMainWid();
gc.textmode=G_TRMODE_REPL; // replace text
gc.font=WS_FONT_BASE; // S3 Normal font
m.Normal=f_leave(gCreateGC(m.MainW,
G_GC_MASK_TEXTMODE | G_GC_MASK_FONT,&gc));
gc.font=WS_FONT_BASE+1; // S3 Fast Bold font
m.Bold=f_leave(gCreateGC(m.MainW,
G_GC_MASK_TEXTMODE | G_GC_MASK_FONT,&gc));
//rcb=f_new(1,C_RSCFILE); ///
//f_send3(rcb,O_RS_INIT,DatCommandPtr); ///
//f_send4(rcb,O_RS_READ_BUF,buf,R_HOST); ///
//wInfoMsg(buf); ///
gFontInfo(gc.font,G_STY_NORMAL,&font);
m.spot.height=dY;
m.spot.ascent=font.ascent;
m.spot.width=font.numeric_width;
m.spot.flags=W_CURSOR_OBLOID;
wInformOn(); // enable CONS_EVENT_ON_OFF
uEscape(FALSE); //disable PSION[Esc]
f_leave(SwitchIf(hCrackCommandLine(),DatUsedPathNamePtr));
return 1;
} //******************************** END StartUp
C Module TCOM.C
#include "oe.h"
//#define uNUM 1 // SPD
//#define uNUM 21 // MU
//#define uNUM 31 // PH
//#define uNUM 41 // SA
#ifdef uNUM
#define uVER 122
#define uTYPE 1 // Generic
//#define uTYPE 2 // Exclusive
#define uTAG (uNUM+uVER*256)
#else
#define uTYPE 0 // Restricted until:
#define uYY 97
#define uMM 7
#define uDD 1
#define uTAG (uYY*512+uMM*32+uDD-47712U)
// GT=81 (17 May 93)
// JAT=31416 (24 Aug 54)
#endif
#define ASCII_EOT 4
#define rMax 5 // max lines in Reply Window
#define tMax 8 // max consecutive retries during Send
// Static variables local to this module
LOCAL_D INT rowR; // rows displayed in Reply Window
LOCAL_D P_RECT boxR; // Reply Border
LOCAL_D USER user = {"P1",1,uTYPE,uTAG};
LOCAL_D UBYTE bps[3] = {P_BAUD_300,P_BAUD_1200,P_BAUD_2400};
LOCAL_D P_CRC crc, ack[4] = {15708U, 49507U, 26277U, 26277U};
// Global Definitions
// Procedure Prototypes local to this module
LOCAL_C INT Rx(VOID); // receive frame
LOCAL_C INT GetFrame(ULONG timeout); // wait for Rx string
LOCAL_C INT Tx(UINT len); // send frame
LOCAL_C INT Reply(ULONG timeout); // wait for Red, Green or White
LOCAL_C VOID Put(VOID *, UINT); // Tx frame
LOCAL_C VOID Get(VOID); // Rx line
LOCAL_C VOID ShowLine(TEXT *); //line into Reply Window
LOCAL_C VOID Check(INT); // display any error text
//****************************************************************
GLDEF_C INT Call(TEXT *spec) {
UINT i, line, len;
HEADER *pHost;
LINE *pLine;
TxLINE *pOut;
TEXT string[80];
com=f_alloc(sizeof(ASYNC));
com->ccb=com->timer=com->dir=NULL;
com->state=0; // enable Tx, Ack even
com->host=head;
wFlush(); gSetGC0(m.Normal); rowR=0;
boxR.tl.x=m.boxB.tl.x+2; boxR.tl.y=m.boxB.tl.y+3+dY;
boxR.br.x=m.boxB.br.x-3; boxR.br.y=m.boxB.tl.y+3+rMax*dY;
while(!SwitchIf('S',spec)) { // send next order
SwitchFile(-1);
m.SeekTo=sizeof(HEADER)+head.lines*sizeof(LINE);
f_seek(m.fcb,P_FABS,&m.SeekTo);
head.oblk=0;
f_write(m.fcb,com->host.host,head.iblk=(*com->host.host)+1);
len=(*head.host<*com->host.host)? *head.host: *com->host.host;
pHost=(p_bcmp(head.host+1,len,com->host.host+1,len))? &com->host: &head;
com->frame.head.user=user;
com->frame.head.acode=pHost->acode;
p_bcpy(com->frame.head.pword,pHost->pword+1,5);
len=p_bcpy(com->frame.head.cref,head.cref,(*head.cref)+1)
-com->frame.data;
if (Tx(len)) while((len=Rx())>0) { // accept RVI msg
f_write(m.fcb,com->frame.data,++len); head.iblk+=len;
ShowLine(com->frame.data); // RVI
}
pLine=m.pLine1; line=0;
while(line<head.lines) { // pack, block & send lines
p_atos(string,"Sending line %u",line+1); ShowState(string);
for (i=LinesPerBlock, pOut=com->frame.line, len=0; i; i--) {
pLine->rblk=0;
PackLn(pOut++,pLine++); len+=sizeof(TxLINE);
if (++line==head.lines) break;
}
Tx(len);
}
head.state=1; head.stamp=p_date(); ShowState("Awaiting reply");
while((len=Rx())>0) { // process reply
if (head.state==1) { // now Sent OK
p_sound(pip);
gSetGC0(m.Bold); ShowDone("to cancel reply"); gSetGC0(m.Normal);
}
if (com->frame.tail.flag==ASCII_EOT) { // trailer
f_write(m.fcb,&com->frame.tail,len);
head.oblk=len;
ShowLine(com->frame.tail.outcome);
ShowState("Sent OK, reply OK");
continue;
}
p_atos(string,"Sent OK %u checked",(UINT) com->frame.progress.line);
ShowState(string); head.state=2+com->frame.progress.line;
if ((com->frame.progress.flag!=' ')
&& (com->frame.progress.line<=head.lines)
&& (len-=sizeof(UWORD))) { // report shortage
pLine=m.pLine1-1+com->frame.progress.line;
f_write(m.fcb,&com->frame.progress.flag,len); pLine->rblk=len;
p_atos(string+FormItm(string,pLine),
(len==1)? " (%u)Not on file": " (%u%c)%s",
(len==1)? pLine->qty: com->frame.progress.qshort,
com->frame.progress.flag,
com->frame.progress.description);
ShowLine(string);
}
}
AgeFile();
}
if (m.state & A_MASK_Connected) return 0;
else return 2; // found nothing to send
} //******************************** END Call
LOCAL_C INT Rx(VOID) {
WORD len, one=1, try=tMax;
p_iow2(com->ccb,P_FFLUSH); // flush LDD input buffer
while(1) { // wait for EOF or good CRC
p_ioc5(com->ccb,P_FREAD,&com->rxstate,com->frame.data,&one); // start Rx
do { // send Red or White every 2 secs until string received
if (!try--) p_leave(E_FILE_RETRAN); // too many tries
Put(&ack[com->state & 3],sizeof(P_CRC));
} while(!(len=GetFrame(20)));
if (len>sizeof(P_CRC)) {
CRC16(&crc.uw,com->frame.data,len); // compute CRC
if (!crc.uw) { // good CRC
com->state&=~(C_MASK_StopTx | C_MASK_RVI); // enable Tx, cancel RVI
com->state^=C_MASK_AckOdd; // switch Ack
len-=sizeof(P_CRC); *(com->frame.data+len)=0;
break;
}
}
if (com->state & C_MASK_StopTx) continue;
if ((len==sizeof(P_CRC))
&& (ack[com->state & 1].uw==com->frame.crc.uw)) { // end of file
len=(com->state & C_MASK_RVI)? -1: 0;
com->state|=C_MASK_StopTx; // stop next Tx
com->state&=~C_MASK_RVI; // cancel any RVI
break;
}
p_sound(rasp); // error
}
return len;
} //******************************** END Rx
LOCAL_C INT GetFrame(ULONG timeout) {
WORD tstate, last, this=0;
p_ioc4(com->timer,P_FRELATIVE,&tstate,&timeout); // start Timer
while(1) {
Wait();
if (com->rxstate!=E_FILE_PENDING) break; // 1st byte received
if (tstate!=E_FILE_PENDING) return 0; // timeout
}
p_iow2(com->timer,P_FCANCEL); p_waitstat(&tstate); // stop Timer
Check(com->rxstate);
do {
p_sleept(5); last=this; p_iow3(com->ccb,P_FTEST,&this);
if (this>sizeof(com->frame)) p_leave(E_GEN_OVER);
} while(last!=this);
if (this) Check(p_read(com->ccb,com->frame.data+1,this));
return this+1; // done
} //******************************** END GetFrame
LOCAL_C INT Tx(UINT len) {
WORD outcome, rtry, try=tMax;
CRC16(&crc.uw,com->frame.data,len); // compute CRC
*(com->frame.data+len++)=crc.hilo.hi; *(com->frame.data+len++)=crc.hilo.lo;
while(1) { // send frame & wait for Green ack
if (!try--) p_leave(E_FILE_RETRAN); // too many tries
Put(com->frame.data,len);
for (rtry=tMax; (outcome=Reply(20))<0; ) {
if (!--rtry) p_leave(E_FILE_INACT); // inactivity timeout
}
if (outcome==2) break; // RVI received
outcome^=~com->state; outcome&=C_MASK_AckOdd;
if (!outcome) break; // ack is Green
p_sound(rasp); // error
}
com->state^=C_MASK_AckOdd; // switch Ack
return outcome;
} //******************************** END Tx
LOCAL_C INT Reply(ULONG timeout) {
INT i;
WORD tstate, two=sizeof(P_CRC);
P_CRC crc;
p_iow2(com->ccb,P_FFLUSH); // flush LDD input buffer
p_ioc5(com->ccb,P_FREAD,&com->rxstate,&crc,&two); // start Rx
p_ioc4(com->timer,P_FRELATIVE,&tstate,&timeout); // start Timer
while(1) {
Wait();
if (com->rxstate!=E_FILE_PENDING) break; // 1st byte received
if (tstate==E_FILE_PENDING) continue;
p_iow2(com->ccb,P_FCANCEL); p_waitstat(&com->rxstate); // stop Rx
return -1; // timeout
}
p_iow2(com->timer,P_FCANCEL); p_waitstat(&tstate); // stop Timer
Check(com->rxstate);
for (i=0; i<=2; i++) {if (ack[i].uw==crc.uw) return i;} // reply known
return -1; // reply garbled
} //******************************** END Reply
GLDEF_C VOID Connect(VOID) {
P_SRCHAR config;
TEXT string[32];
TEXT *pout;
wSetBusyMsg("S3 disc bays closed?",
W_CORNER_BOTTOM_RIGHT | 1);
f_open(&com->timer,"TIM:",-1); // Timer
f_open(&com->ccb,"TTY:A",-1); // Serial Port
wCancelBusyMsg();
if (com->host.modem==2) { // manual modem
ShowState("Press modem DATA on hearing far tone");
if (com->host.phone < 3) {
*p_bcpy(string,com->host.dial[com->host.phone]+1,
*com->host.dial[com->host.phone])=0;
hDTMFString(string);
}
}
else ShowState("Waiting for local modem");
p_iow3(com->ccb,P_FSENSE,&config);
config.tbaud=config.rbaud=bps[com->host.bps];
config.tmask=0x2400; // B13, B10
if (com->host.modem>1) config.hand=P_OBEY_DSR; // Manual or VX543
if (com->host.modem==3) { // configure VX543
config.tbaud=config.rbaud=P_BAUD_1200;
config.frame=P_DATA_7 | P_PARITY; config.parity=P_PAR_EVEN;
f_leave(p_iow3(com->ccb,P_FSET,&config)); // set port parameters
Put("\33F 8N10\15",8); // Format 8 data, No parity, 1 stop, V21
p_sleep(5L); // half second
config.tbaud=config.rbaud=P_BAUD_300;
config.frame=P_DATA_8;
}
f_leave(p_iow3(com->ccb,P_FSET,&config)); // set port parameters
Put(&crc,0); // null Tx (wait for CTS and maybe DSR)
p_sleep(15L); // 1.5 sec
config.hand|=P_FAIL_DSR; // ignored unless P_OBEY_DSR is set
f_leave(p_iow3(com->ccb,P_FSET,&config)); // set port parameters
ShowState("Trying to connect to wholesaler");
if (com->host.modem<2) { // AT modem
pout=p_scpy(com->frame.data,"ATE1V1Q0X1D"); // echo cmds, long replies
if (com->host.phone < 3) {
*(pout-2)='4';
*(pout++)=(com->host.modem)? 'P': 'T';
pout=p_bcpy(pout,com->host.dial[com->host.phone]+1,
*com->host.dial[com->host.phone]);
}
*(pout++)=0x0D; *pout=0;
Put(com->frame.data,p_slen(com->frame.data)); Get();
if (p_bcmp(com->frame.data,7,"CONNECT",7)) p_leave(0); // no connection
if (*(com->frame.data+7)==0) config.tbaud=config.rbaud=P_BAUD_300;
else if (!p_bcmp(com->frame.data+8,4,"1200",4))
config.tbaud=config.rbaud=P_BAUD_1200;
else if (!p_bcmp(com->frame.data+8,4,"2400",4))
config.tbaud=config.rbaud=P_BAUD_2400;
}
else if (com->host.modem==3) { // VX543 modem
pout=p_scpy(com->frame.data,"\33O");
if (com->host.phone < 3) {
*(pout-1)='D'; *(pout++)=' ';
pout=p_bcpy(pout,com->host.dial[com->host.phone]+1,
*com->host.dial[com->host.phone]);
}
*(pout++)=0x0D; *pout=0;
Put(com->frame.data,p_slen(com->frame.data)); Get();
}
config.tmask=0;
f_leave(p_iow3(com->ccb,P_FSET,&config)); // set port parameters
p_sleep(10L); // one second
while(Rx()>0) {} // Tx Bid
m.state|=A_MASK_Connected;
} //******************************** END Connect
LOCAL_C VOID Put(VOID *string, UINT len) {
p_ioc5(com->ccb,P_FWRITE,&com->txstate,string,&len); // start Tx
while(1) {
Wait();
if (com->txstate!=E_FILE_PENDING) break; // Tx done
}
Check(com->txstate);
} //******************************** END Put
LOCAL_C VOID Get(VOID) {
UWORD len;
while(1) {
len=sizeof(com->frame.data);
p_ioc5(com->ccb,P_FREAD,&com->rxstate,com->frame.data,&len); // start Rx
while(1) {
Wait();
if (com->rxstate!=E_FILE_PENDING) break;
}
Check(com->rxstate);
if (com->host.modem==3) return; // VX543
if (!(--len)) continue;
*(com->frame.data+len)=0; ShowLine(com->frame.data);
if (p_bcmp(com->frame.data,2,"AT",2)) return; // not an echo
}
} //******************************** END Get
LOCAL_C VOID ShowLine(TEXT *string) {
TEXT line[80];
P_RECT box;
P_POINT up = {0,-dY};
if (rowR++==rMax) { // scroll window
rowR=rMax;
wScrollRect(m.MainW,&boxR,&up);
}
box.tl.x=boxR.tl.x; box.br.x=boxR.br.x;
box.br.y=boxR.tl.y+(rowR-1)*dY; box.tl.y=box.br.y-dY;
gPrintBoxText(&box,m.spot.ascent,G_TEXT_ALIGN_LEFT,0,
line,FormTxt(line,string));
} //******************************** END ShowLine
LOCAL_C VOID Check(INT outcome) {
TEXT string[E_MAX_ERROR_TEXT_SIZE];
if (outcome<0) {
if (outcome==E_FILE_LINE) p_leave(outcome);
p_errs(string,outcome); wInfoMsg(string);
}
} //******************************** END Check
C Module REPLY.C
#include "oe.h"
// S3 Screen Layout pixel coords
#define Head 8 // y for Header row
#define Foot 79 // y for Footer row
#define XBar 90 // x for Status window split
// Static variables local to this module
TEXT *reason[]= {
"B(to follow on back order)",
"Ttemporarily.",
"M - manuf. cannot supply.",
NULL
};
// Procedure Prototypes local to this module
LOCAL_C VOID ShowRow(TEXT *,TEXT *,INT); // show Reply Row
LOCAL_C TEXT *Clock(TEXT *, ULONG); // Time Stamp -> ASCII
//****************************************************************
GLDEF_C VOID ShowReply(VOID) {
INT base, i, new;
RxLINE line;
TEXT left[40], right[80];
LINE *pLine, *pNew;
RxTAIL *pTail;
p_atos(right,"File %s sent ",DatStatusNamePtr);
*Clock(right+p_slen(right),head.stamp)=0;
m.boxS.br.y=Head; ShowRow(NULL,right,FALSE);
pTail=(RxTAIL *)(m.pHost+head.iblk); pTail->shorts=0;
if (head.oblk) {
m.SeekTo=head.oLine1+head.lines*sizeof(LINE)+head.iblk;
for (pLine=m.pLine1;(TEXT *)pLine!=m.pHost;pLine++)
m.SeekTo+=pLine->rblk;
f_seek(m.fcb,P_FABS,&m.SeekTo); f_read(m.fcb,pTail,head.oblk);
*((TEXT *)pTail+head.oblk)=0;
FormTxt(right,pTail->outcome);
}
else if (head.state>1)
p_atos(right,"Reply cut off after line %u",head.state-2);
else p_scpy(right,"Outcome unknown");
ShowRow(NULL,right,TRUE);
gPrintText(158,Foot,"[Help] available",16);
if (*head.cref)
gPrintText(0,Foot,right,
p_bcpy(p_scpy(right,"Order ref:"),head.cref+1,*head.cref)-right);
m.spot.pos.y=Foot; m.spot.pos.x=m.boxB.br.x; // cursor off screen
m.SeekTo=sizeof(HEADER)+head.lines*sizeof(LINE)+head.iblk;
for (base=0, pLine=m.pLine1; base<head.lines; base++, pLine++) {
if (pLine->rblk) break; // 1st shortage
}
if (base==head.lines) {base=0; pLine=m.pLine1;} // 1st line
while(1) {
m.boxS.br.y=m.boxB.tl.y+dY+3;
p_atos(left,"Line %u of %u.",base+1,head.lines);
p_atos(right,(pTail->shorts)? "(%u lines report shortages)": "",
pTail->shorts-1);
ShowRow(left,right,FALSE); m.boxS.br.y+=3;
*(right+FormItm(right,pLine))=0;
ShowRow("Item Code:",right,TRUE);
p_atos(right,(pLine->flags & L_MASK_Cases)? "%u Case(s)": "%u",
pLine->qty);
ShowRow("Qty ordered:",right,FALSE);
if (pLine->rblk) {
f_seek(m.fcb,P_FABS,&m.SeekTo);
f_read(m.fcb,&line.flag,pLine->rblk);
if (line.flag=='N') {
ShowRow("Units short:","All - item is not on our file.",FALSE);
*right=0;
}
else {
*left=line.flag; *(left+1)=0;
for (i=0; reason[i]!=NULL; i++) {
if (*reason[i]==line.flag) {
p_scpy(left,reason[i]+1); break;
}
}
p_atos(right,"%u %s",line.qshort,left);
ShowRow("Units short:",right,FALSE);
*(&line.flag+pLine->rblk)=0;
FormTxt(right,line.description);
}
}
else {
p_scpy(right,((pTail->shorts) || (base+2<head.state))?
"(expect full delivery of this item)": "");
ShowRow(NULL,right,FALSE);
*right=0;
}
ShowRow(NULL,right,FALSE);
while(1) {
Char();
if (uKeyPressOutstanding()) continue;
new=base; pNew=pLine;
if (key.keycode==W_KEY_TAB)
key.keycode=(key.modifiers & W_SHIFT_MODIFIER)?
W_KEY_LEFT: W_KEY_RIGHT;
if ((key.keycode==W_KEY_DOWN) && (++new<head.lines)) { // next line
m.SeekTo+=(pNew++)->rblk; break;
}
if ((key.keycode==W_KEY_UP) && new--) { // previous line
m.SeekTo-=(--pNew)->rblk; break;
}
if (key.keycode==W_KEY_RIGHT) { // next shortage
while (++new<head.lines)
if ((++pNew)->rblk) {m.SeekTo+=pLine->rblk; break;}
if (new<head.lines) break;
}
if (key.keycode==W_KEY_LEFT) { // previous shortage
while (new--)
if ((--pNew)->rblk) {m.SeekTo-=pNew->rblk; break;}
if (new>=0) break;
}
if (key.keycode==W_KEY_HELP) {
uDisplayText("[Esc] or [Enter] removes this box, then:",
"\31 shows next, \30 shows previous line.",
"[Tab] or \32 shows next, [Shift]+[Tab] or \33",
"shows previous shortage.",
"[Menu] then \30 \31 \32 \33 select tools.",
"[Application button] switches files quickly.",
NULL);
}
else p_sound(beep);
}
base=new; pLine=pNew;
}
} //******************************** END ShowReply
LOCAL_C VOID ShowRow(TEXT *left,TEXT *right,INT bold) {
UINT align=G_TEXT_ALIGN_CENTRE;
m.boxS.tl.x=m.boxB.tl.x+2; m.boxS.tl.y=m.boxS.br.y-dY;
if (left!=NULL) {
m.boxS.br.x=XBar;
gPrintBoxText(&m.boxS,m.spot.ascent,
G_TEXT_ALIGN_RIGHT,dX+3,left,p_slen(left));
align=G_TEXT_ALIGN_LEFT;
m.boxS.tl.x=XBar;
}
m.boxS.br.x=m.boxB.br.x-3;
if (bold) gSetGC0(m.Bold);
gPrintBoxText(&m.boxS,m.spot.ascent,align,0,right,p_slen(right));
if (bold) gSetGC0(m.Normal);
m.boxS.br.y+=dY+1;
} //******************************** END ShowRow
LOCAL_C TEXT *Clock(TEXT *string, ULONG stamp) {
TEXT day[E_MAX_DAY_NAME], month[E_MAX_MONTH_NAME];
P_DAYSEC dstime;
P_DATE dt;
p_sttods(&stamp,&dstime); p_dstodt(&dstime,&dt);
p_nmday(day,p_wkday(dstime.day));
p_nmmon(month,dt.month);
p_atos(string,"%3s %u %3s %u %02u:%02u",
day,dt.day+1,month,dt.year+1900,dt.hour,dt.minute);
return string+p_slen(string);
} //******************************** END Clock
MASM Module MISC.ASM
.MODEL SMALL,C
OPTION NOKEYWORD:<ESC>
b0 = 01h
b1 = 02h
b2 = 04h
b3 = 08h
b4 = 10h
b5 = 20h
b6 = 40h
b7 = 80h
b8 = 0100h
b9 = 0200h
b10 = 0400h
b11 = 0800h
b12 = 1000h
b13 = 2000h
b14 = 4000h
b15 = 8000h
pp MACRO i,x
FOR y,<x>
i y
ENDM
ENDM
iMax = 8 ; max chars in Item Code
line STRUC
qty WORD ? ; Qty ordered
flags BYTE ? ; B0: Request To Follow if no stock
; B1: Qty is in cases
outcome BYTE ?
item BYTE iMax DUP(?) ; Item Code
line ENDS
TxLINE STRUC
qty WORD ? ; Qty ordered
bcd BYTE 4 DUP(?) ; Item Code (BCD 7 digits), Flags:
; B0: Back Order request
; B1: Qty ordered is in cases
; B3: Product Code (not PIP Code)
TxLINE ENDS
.CODE
; ****************************** CRC16 of CX bytes at DS:SI into DS:DI
CRC16 PROC PUBLIC USES cx dx si di
cld ; upwards
xor dx,dx
jcxz @F
.Repeat
push cx
mov cx,8
lodsb
.Repeat
mov ah,al
and ah,80h
xor dh,ah
shl dx,1
.If CARRY?
xor dx,B15+B2+B0 ; Generating Polynomial
.Endif
rol al,1
.Untilcxz
pop cx
.Untilcxz
@@: mov [di],dx
ret
CRC16 ENDP
; ****************************** Pack Order Line DS:BX into ES:DI
PackLn PROC PUBLIC USES cx si di
cld ; upwards
mov cl,4
mov ax,[bx].line.qty
stosw
lea si,[bx].line.item
call pack
call pack
call pack
lodsb
shl al,cl
mov ah,[bx].line.flags
and ah,B0+B1
.If BYTE PTR[si]>'9'
or ah,B3 ; B3: Product Code
.EndIf
or al,ah
stosb
ret
PackLn ENDP
pack PROC PRIVATE
lodsw
shl al,cl
and ah,0fh
or al,ah
stosb
ret
pack ENDP
; ****************************** Move BCS Password DS:SI into ES:DI
MovePw PROC PUBLIC USES cx si di
cld ; upwards
lodsb
stosb
mov cl,al
xor ch,ch
.Repeat
lodsb
.If (al>='a') && (al<='z')
sub al,20h ; Upper Case
.EndIf
sub al,1bh
add al,cl
rol al,cl
stosb
.Untilcxz
ret
MovePw ENDP
; ****************************** Compressed ZTS DS:SI into ZTS ES:DI
FormTxt PROC PUBLIC USES cx si di
cld ; upwards
xor cx,cx
.While 1
lodsb
.If al < ' '
.Break .If !al
.Continue ; discard
.EndIf
.If al & B7
mov al,' '
.EndIf
.If al == '#'
mov al,'œ'
.EndIf
inc cx
stosb
.Endw
stosb
mov ax,cx
ret
FormTxt ENDP
; ****************************** Item Code of Line DS:SI into ES:DI
FormItm PROC PUBLIC USES cx si di
cld ; upwards
lea si,[si].line.item+1
.If BYTE PTR[si+iMax-2] <= '9' ; PIP Code
movsw
movsb
mov al,'-'
stosb
movsw
movsw
mov ax,8
.Else ; Product Code
mov cx,iMax-1
mov al,'0'
xchg si,di
repe scasb
xchg si,di
inc cx
dec si
mov ax,cx
rep movsb
.Endif
ret
FormItm ENDP
END