Files
sibo-playground/code/SIBOSDK/demo/lined.c
2026-07-06 18:01:36 +01:00

397 lines
8.4 KiB
C

#include <p_std.h>
#include <wlib.h>
#include "lined.h"
GLREF_D UINT wMainWid;
LOCAL_C INT CreateGC(LINED *ed)
{
G_GC gc;
if (ed->gc)
return(FALSE);
gc.font=ed->i.font;
gc.style=ed->i.style;
gCreateTempGC(ed->i.winid,G_GC_MASK_FONT|G_GC_MASK_STYLE,&gc);
ed->gc=TRUE;
return(TRUE);
}
LOCAL_C VOID FreeGC(LINED *ed,INT gc)
{
if (!gc)
return;
ed->gc=FALSE;
gFreeTempGC();
}
LOCAL_C INT WidthTo(LINED *ed,INT blen)
{
return(gTextWidth(ed->i.font,ed->i.style,ed->pb,blen));
}
LOCAL_C VOID GetBox(LINED *ed,P_RECT *pbox)
{
pbox->tl.x=ed->i.xoff;
pbox->tl.y=ed->i.yoff;
pbox->br.x=pbox->tl.x+ed->i.width;
pbox->br.y=pbox->tl.y+ed->i.height;
}
LOCAL_C VOID DrawCursor(LINED *ed)
{
W_CURSOR flash;
flash.pos.x=ed->i.xoff+ed->marg+WidthTo(ed,ed->cur);
flash.pos.y=ed->i.yoff+ed->i.asc;
flash.height=ed->i.height;
flash.ascent=ed->i.asc;
flash.width=ed->cwidth;
flash.flags=0;
wTextCursor(ed->i.winid,&flash);
}
LOCAL_C VOID ToggleHighlight(LINED *ed)
{
P_RECT box;
INT gc;
if (ed->select)
{
gc=CreateGC(ed);
GetBox(ed,&box);
box.br.x=box.tl.x+ed->marg+WidthTo(ed,ed->blen);
gClrRect(&box,G_TRMODE_INV);
FreeGC(ed,gc);
}
}
LOCAL_C VOID DrawAll(LINED *ed)
{
P_RECT box;
INT gc;
GetBox(ed,&box);
gc=CreateGC(ed);
gPrintBoxText(&box,ed->i.asc,G_TEXT_ALIGN_LEFT,ed->marg,ed->pb,ed->blen);
if (ed->emph)
{
DrawCursor(ed);
ToggleHighlight(ed);
}
FreeGC(ed,gc);
}
GLDEF_C VOID le_destroy(LINED *ed)
{
p_free(ed->pb);
p_free(ed);
}
GLDEF_C LINED *le_init(IN_LINED *pin)
{
LINED *ed;
ed=p_alloc(sizeof(LINED));
if (!ed)
return(NULL);
p_bfil(ed,sizeof(LINED),0);
ed->cwidth=2;
ed->pb=p_alloc(pin->maxchars+1);
if (!ed->pb)
{
p_free(ed);
return(NULL);
}
ed->i=(*pin);
ed->lmarg=ed->i.width/4;
return(ed);
}
LOCAL_C VOID ScrollForCursor(LINED *ed,INT draw)
{
INT oldmarg;
INT curx;
INT exx;
INT exl;
INT exr;
oldmarg=ed->marg;
curx=WidthTo(ed,ed->cur);
exx=curx+ed->marg;
exl=exx-ed->lmarg;
exr=exx+ed->cwidth-ed->i.width;
if (exl<0 && ed->marg)
{
ed->marg-=exl-ed->scrollx;
if (ed->marg>0)
ed->marg=0;
}
else if (exr>0)
ed->marg-=exr+ed->scrollx;
if (ed->marg!=oldmarg && draw)
DrawAll(ed);
}
GLDEF_C VOID le_set_text(LINED *ed,INT blen,TEXT *pb)
{
*(p_bcpy(ed->pb,pb,blen))=0;
ed->blen=blen;
ed->marg=0;
ed->select=FALSE;
ed->cur=0;
if (ed->i.autoselect && blen)
{
ed->cur=blen;
ed->select=TRUE;
ScrollForCursor(ed,FALSE);
}
if (ed->visible)
DrawAll(ed);
}
LOCAL_C VOID DelSelRange(LINED *ed)
{
ed->select=FALSE;
ed->cur=0;
ed->marg=0;
ed->blen=0;
*ed->pb=0;
}
LOCAL_C VOID DoDelete(LINED *ed,INT modifier)
{
INT start;
INT finish;
if (ed->select)
DelSelRange(ed);
else
{
if (modifier&W_SHIFT_MODIFIER)
{
if (ed->cur==ed->blen)
return;
}
else if (!ed->cur)
return;
start=finish=ed->cur;
switch (modifier)
{
case W_SHIFT_MODIFIER:
finish++;
break;
case W_PSION_MODIFIER:
finish=ed->blen;
break;
default:
start--;
}
p_bcpy(ed->pb+start,ed->pb+finish,ed->blen+1-finish);
ed->blen-=finish-start;
ed->cur=start;
ScrollForCursor(ed,FALSE);
}
DrawAll(ed);
}
LOCAL_C VOID LoseHighlight(LINED *ed)
{
ToggleHighlight(ed);
ed->select=FALSE;
}
LOCAL_C VOID DisplayCursor(LINED *ed)
{
ScrollForCursor(ed,TRUE);
DrawCursor(ed);
}
GLDEF_C INT le_key(LINED *ed,INT keycode,INT modifier)
{
TEXT *pb;
if (keycode<0x100 && p_isprint(keycode))
{
if (ed->select)
DelSelRange(ed);
if (ed->blen==ed->i.maxchars)
{
p_sound(-5,320);
return(-1);
}
pb=ed->pb+ed->cur;
p_bcpy(pb+1,pb,ed->blen+1-ed->cur);
*pb=keycode;
(ed->blen)++;
(ed->cur)++;
ScrollForCursor(ed,FALSE);
DrawAll(ed);
return(0);
}
if (keycode==W_KEY_DELETE_LEFT || keycode==W_KEY_DELETE_RIGHT)
DoDelete(ed,modifier);
else
{
switch (keycode)
{
case W_KEY_LEFT:
if (ed->select)
{
LoseHighlight(ed);
ed->cur=0;
}
else if (!ed->cur)
return(0);
else
{
if (modifier&W_PSION_MODIFIER)
ed->cur=0;
else
(ed->cur)--;
}
DisplayCursor(ed);
break;
case W_KEY_RIGHT:
if (ed->select)
{
LoseHighlight(ed);
ed->cur=ed->blen;
}
else if (ed->cur==ed->blen)
return(0);
else
{
if (modifier&W_PSION_MODIFIER)
ed->cur=ed->blen;
else
(ed->cur)++;
}
DisplayCursor(ed);
}
}
return(0);
}
GLDEF_C VOID le_emphasise(LINED *ed,INT emph)
{
if (emph)
emph=TRUE;
if (ed->emph==emph)
return;
ed->emph=emph;
if (!ed->visible)
return;
DrawAll(ed);
if (!emph)
wEraseTextCursor();
}
GLDEF_C VOID le_set_cwidth(LINED *ed,INT cwidth)
{
ed->cwidth=cwidth;
if (ed->visible && ed->emph)
{
if (cwidth)
DrawCursor(ed);
else
wEraseTextCursor();
}
}
GLDEF_C VOID le_visible(LINED *ed,INT visible)
{
P_RECT box;
INT gc;
if (visible)
visible=TRUE;
if (ed->visible==visible)
return;
ed->visible=visible;
if (visible)
DrawAll(ed);
else
{
GetBox(ed,&box);
gc=CreateGC(ed);
gClrRect(&box,G_TRMODE_CLR);
FreeGC(ed,gc);
}
}
/************************** TEST CODE FOLLOWS ***********************/
LOCAL_C LINED *CreateLined(INT yoff,TEXT *msg,INT emph)
{
IN_LINED init;
LINED *ed;
init.maxchars=20;
init.winid=wMainWid;
init.xoff=10;
init.yoff=yoff;
init.width=80;
init.height=10;
init.asc=8;
init.font=WS_FONT_BASE+4;
init.style=0;
init.autoselect=TRUE;
ed=le_init(&init);
le_set_text(ed,p_slen(msg),msg);
le_emphasise(ed,emph);
le_visible(ed,TRUE);
return(ed);
}
GLDEF_C VOID main(VOID)
{
LINED *ed[3];
INT which;
WS_EV event;
INT keycode;
wStartup();
gBorder(W_BORD_CORNER_4);
ed[0]=CreateLined(10,"One",TRUE);
ed[1]=CreateLined(30,"Two",FALSE);
ed[2]=CreateLined(50,"Three",FALSE);
which=0;
FOREVER
{
do
{
wGetEventWait(&event);
} while (event.type!=WM_KEY);
keycode=event.p.key.keycode&(~W_SPECIAL_KEY);
switch (keycode)
{
case W_KEY_ESCAPE:
if (event.p.key.modifiers==W_PSION_MODIFIER)
p_exit(0);
case W_KEY_UP:
if (which)
{
le_emphasise(ed[which--],FALSE);
le_emphasise(ed[which],TRUE);
}
break;
case W_KEY_DOWN:
if (which<2)
{
le_emphasise(ed[which++],FALSE);
le_emphasise(ed[which],TRUE);
}
break;
default:
le_key(ed[which],keycode,event.p.key.modifiers);
}
}
}