#include #include #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); } } }