This is a basic command shell whose input is provided by adsPen.
It only interprets one command 'exit' which closes the shell.
Show PVShell
PVShell.h
/*
PVShell was developed to show the usage of "adsPen"
According to that, it has not been extensively tested.
*/
#ifndef __PVSHELL__
#define __PVSHELL__
#include <stdrom.h>
#include "define.h"
#include "libc.h"
#define SHELL_STATE_VISIBLE 0x01
#define SHELL_STATE_SCROLL 0x02
#define SHELL_STATE_INTERACTIVE 0x04
#define SHELL_STATE_SCRLCRSR 0x08
#define SHELL_BUF_SIZE 1024
typedef struct
{
int x, y, w, h;
int c, r;
int FirstLine;
int State;
int Size;
char Buffer[SHELL_BUF_SIZE];
} PVShell;
void PVShell_Init(PVShell *trm, int x, int y, int w, int h);
void PVShell_SetInteractive(PVShell *trm, bool flag);
void PVShell_Draw(PVShell *trm);
void PVShell_Hide(PVShell *trm);
void PVShell_ScrollUp(PVShell *trm);
void PVShell_ScrollDown(PVShell *trm);
void PVShell_Append_Str(PVShell *trm, char *Str);
void PVShell_Append_Chr(PVShell *trm, char Chr);
void PVShell_Bksp(PVShell *trm);
#endif
PVShell.c
#include <stdrom.h>
#include "define.h"
#include "libc.h"
#include "PVShell.h"
#define FONT_W 6
#define FONT_H 8
typedef struct
{
int rw, cl;
char *pBuf;
PVShell *pPVShell;
bool bNewLine;
} BCB;
void Iter_Init(BCB *pBCB, PVShell *pSh)
{
pBCB->rw = pBCB->cl = 0;
pBCB->pPVShell = pSh;
pBCB->pBuf = pSh->Buffer;
pBCB->bNewLine = FALSE;
}
int Iter_Next(BCB *pBCB)
{
int ch;
pBCB->bNewLine = FALSE;
ch = *pBCB->pBuf;
if (ch == '\r' || pBCB->cl == pBCB->pPVShell->c)
{
pBCB->cl = 1; if (ch == '\r') pBCB->cl = 0;
pBCB->rw++;
pBCB->bNewLine = TRUE;
}
else
pBCB->cl++;
if (ch == 0)
return 0;
pBCB->pBuf++;
return ch;
}
int PVShell_CountLines(PVShell *trm)
{
BCB bcb;
Iter_Init(&bcb, trm);
while (Iter_Next(&bcb));
return bcb.rw+1;
}
void PVShell_Init(PVShell *trm, int x, int y, int w, int h)
{
trm->x = x; trm->y = y; trm->w = w; trm->h = h;
trm->r = (h - 4) / FONT_H;
trm->c = (w - 4) / FONT_W;
trm->State = SHELL_STATE_VISIBLE;
trm->FirstLine = 0;
trm->Buffer[0] = 0;
}
void PVShell_SetInteractive(PVShell *trm, bool flag)
{
if (flag)
trm->State |= SHELL_STATE_INTERACTIVE;
else
trm->State &= ~SHELL_STATE_INTERACTIVE;
}
void PVShell_Draw(PVShell *trm)
{
BCB bcb;
char ch = 0;
int x, y;
LibClrBox(trm->x, trm->y, trm->w, trm->h);
LibBox(trm->x, trm->y, trm->w, trm->h, 1);
x = trm->x + 2;
y = trm->y + 2;
Iter_Init(&bcb, trm);
do
if (bcb.rw == trm->FirstLine) break;
while (ch = Iter_Next(&bcb));
bcb.bNewLine = FALSE;
while (TRUE)
{
ch = Iter_Next(&bcb);
if (bcb.bNewLine)
{
x = trm->x + 2;
y += FONT_H;
if (bcb.rw - trm->FirstLine == trm->r)
{
trm->State |= SHELL_STATE_SCROLL;
break;
}
}
if (ch >= ' ')
{
LibPutProFont(IB_CG57FONT, ch, x, y);
x += FONT_W;
}
if (trm->State & SHELL_STATE_INTERACTIVE)
{
if (ch == 0)
{
LibBox(x, y, FONT_W, FONT_H, 1);
break;
}
}
}
LibPutDisp();
}
void PVShell_Bksp(PVShell *trm)
{
char *p;
p = strchr(trm->Buffer, 0);
if (p == trm->Buffer)
return;
p--;
if (*p != '\r')
*p = 0;
}
void PVShell_Append_Chr(PVShell *trm, char Chr)
{
char Str[2] = "";
Str[0] = Chr; PVShell_Append_Str(trm, Str);
}
void PVShell_Append_Str(PVShell *trm, char *Str)
{
int space;
char *p;
if (strlen(trm->Buffer) + strlen(Str) + 1 >
SHELL_BUF_SIZE)
{
space = strlen(trm->Buffer) +
strlen(Str) + 1 - SHELL_BUF_SIZE;
p = trm->Buffer + space;
do
{
if (*p == '\r' || *p == 0)
break;
p++;
} while (TRUE);
if (*p == '\r') p++;
memcpy(trm->Buffer, p,
trm->Buffer + strlen(trm->Buffer) - p + 1);
}
strcat(trm->Buffer, Str);
if (PVShell_CountLines(trm) >= trm->r)
trm->FirstLine = PVShell_CountLines(trm) - trm->r;
if (trm->State & SHELL_STATE_SCROLL)
PVShell_ScrollUp(trm);
}
void PVShell_ScrollUp(PVShell *trm)
{
if (PVShell_CountLines(trm) > trm->FirstLine + trm->r)
trm->FirstLine++;
}
void PVShell_ScrollDown(PVShell *trm)
{
if (trm->FirstLine > 0)
trm->FirstLine--;
}
Show Main
#include <stdrom.h>
#include "define.h"
#include "libc.h"
#include "adsPen.h"
#include "PVShell.h"
#define MAINLOOP main
#define SHELL_X 10
#define SHELL_Y 10
#define SHELL_W 140
#define SHELL_H 54
/**********************************************
Special Keys
**********************************************/
#define VK_UP 0x11
#define VK_DOWN 0x12
#define VK_LEFT 0x13
#define VK_RIGHT 0x14
#define VK_END 0x06
#define VK_HOME 0x07
#define VK_BACK 0x08
#define VK_DELETE 0x7F
#define CMDBUF_SIZE 32
PVShell Shell;
char CmdBuffer[CMDBUF_SIZE];
char *pCBuf = CmdBuffer;
bool bRunning = TRUE;
void PollEvents(TCHSTS far *tsts, byte event_mask)
{
union REGS reg;
reg.x.ax = 0x0200 | event_mask;
reg.x.di = FP_OFF(tsts);
reg.x.es = FP_SEG(tsts);
int86(0x50, ®, ®);
}
/**********************************************
Draws a button
**********************************************/
void AddButton(int BX, int BY, int BW, int BH, char *BCAP)
{
int sz;
LibGdsBox(BX, BY, BX + BW, BY + BH);
sz = LibGetProStrSize(IB_PFONT2, BCAP);
LibPutProStr(IB_PFONT2,
BX + (BW - sz) / 2,
BY + (BH - 7) / 2, BCAP, sz);
LibPutDispBox(BX, BY, BW + 1, BH + 1);
}
/**********************************************
tests if (px, py) is contained in (x, y, w, h)
**********************************************/
bool IsInRect(int px, int py, int x, int y, int w, int h)
{
return (x < px && px < x + w) && (y < py && py < y + h);
}
/**********************************************
Drives the shell
**********************************************/
int CommandBufferManager(int Code)
{
if ((pCBuf == CmdBuffer + CMDBUF_SIZE - 1) &&
Code != VK_BACK && Code != '\r')
return 1;
if (Code == VK_BACK)
{
if (pCBuf != CmdBuffer)
PVShell_Bksp(&Shell);
}
else
PVShell_Append_Chr(&Shell, Code);
PVShell_Draw(&Shell);
if (Code == '\r')
{
if (!strcmp(CmdBuffer, "exit"))
{
bRunning = FALSE;
return 0;
}
else
{
PVShell_Append_Str(&Shell, "syntax error\r");
PVShell_Draw(&Shell);
}
pCBuf = CmdBuffer;
*pCBuf = 0;
PVShell_Append_Chr(&Shell, '>');
PVShell_Draw(&Shell);
}
else
{
if (Code != VK_BACK)
{
*pCBuf = Code; pCBuf++; *pCBuf = 0;
}
else
{
if (pCBuf > CmdBuffer)
{
pCBuf--; *pCBuf = 0;
}
}
}
return 1;
}
/**********************************************
Called by the recoginzer
**********************************************/
int InputEvent(int Reason, char Code, byte Mode)
{
if (Reason != ADSPEN_REASON_CODE) return ADSPEN_CMD_NEXT;
if (isprint(Code) || Code == '\r' || Code == VK_BACK)
{
if (CommandBufferManager(Code))
return ADSPEN_CMD_NEXT;
}
else
return ADSPEN_CMD_NEXT;
return ADSPEN_CMD_EXIT;
}
/**********************************************
See how it switches between touch and
character events
**********************************************/
void MAINLOOP()
{
TCHSTS tsts;
bool bPenUp;
LibClrDisp();
PVShell_Init(&Shell, SHELL_X, SHELL_Y, SHELL_W, SHELL_H);
PVShell_Append_Chr(&Shell, '>');
PVShell_Draw(&Shell);
AddButton(10, SHELL_Y + SHELL_H + 10, 65, 12, "down");
AddButton(90, SHELL_Y + SHELL_H + 10, 65, 12, "up");
bRunning = TRUE;
bPenUp = TRUE;
while (bRunning)
{
PollEvents(&tsts, 1);
if (tsts.y == -1 || tsts.x == -1) bPenUp = TRUE;
if (!bPenUp) continue;
if (tsts.y != -1 || tsts.x != -1)
{
if (IsInRect(tsts.x, tsts.y,
SHELL_X, SHELL_Y, SHELL_W, SHELL_H))
{
do
PollEvents(&tsts, 1);
while (tsts.y != -1 && tsts.x != -1);
PVShell_SetInteractive(&Shell, TRUE);
PVShell_Draw(&Shell);
adsPenInput(InputEvent);
PVShell_SetInteractive(&Shell, FALSE);
PVShell_Draw(&Shell);
bPenUp = FALSE;
}
if (IsInRect(tsts.x, tsts.y,
10,
SHELL_Y + SHELL_H + 10,
65, 12))
{
bPenUp = FALSE;
PVShell_ScrollDown(&Shell);
PVShell_Draw(&Shell);
}
if (IsInRect(tsts.x, tsts.y,
90, SHELL_Y + SHELL_H + 10,
65, 12))
{
bPenUp = FALSE;
PVShell_ScrollUp(&Shell);
PVShell_Draw(&Shell);
}
}
}
LibJumpMenu();
}
|