unit CodeCompletion;
interface
uses
//----------------------------------------------------------
//local
//----------------------------------------------------------
GenDefs,
//----------------------------------------------------------
//global
//----------------------------------------------------------
Windows,Forms,Classes,Messages,Sysutils,Controls,StdCtrls,ComCtrls,
RichEdit,StrUtils,Graphics,Math,ClipBrd;
//------------------------------------------------------------------
//reagiert auf messages!!!
//------------------------------------------------------------------
const
WMShowCodeCompletion=WM_USER+100;
WMHideCodeCompletion=WM_USER+101;
WMRemoveSpace=WM_USER+103;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
type
TCodeWindow= class(TForm)
VerbBox:TListBox;
procedure setInvisible();
procedure getCurrentWord();
procedure getPartialWord();
function getTextBetween(lpos,rpos:integer):JString;
procedure WriteSelectedWord;
procedure Msg_Show(var Msg:TMessage);message WMShowCodeCompletion;
procedure Msg_Hide(var Msg:TMessage);message WMHideCodeCompletion;
procedure Msg_Remove(var Msg:TMessage);message WMRemoveSpace;
procedure VerbBoxKeyDown(Sender:TObject;var Key:Word;Shift:TShiftState);
procedure VerbBoxMouseLeave(Sender:TObject);
private
//Private declarations
public
RE:TRichEdit;
Org_KeyUp:TKeyEvent;
Org_KeyDown:TKeyEvent;
Org_KeyPress:TKeyPressEvent;
KeysAssigned:boolean;
PosRect:TRect;
WordBeg:JString;
WordFull:JString;
WordStart,WordEnd:integer;
REModif:boolean;
Verbboxprefix:JString;
procedure On_KeyUp(Sender:TObject;var Key:Word;Shift:TShiftState);
procedure On_KeyDown(Sender:TObject;var Key:Word;Shift:TShiftState);
procedure On_KeyPress(Sender:TObject;var Key:char);
constructor Create(AOwner:TComponent);override;
destructor Destroy;override;
procedure setPosition();
procedure setCodeCompletionVerbs(Keys:PAnsiChar);
procedure setFont(FontName:JString;FontSize:integer);
procedure setSize(codewidth:integer;codeheight:integer);
procedure setColor(Col:TColor);
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
implementation
{$R *.dfm}
//------------------------------------------------------------------
//
//------------------------------------------------------------------
const
CH_Blank=' ';
CH_Return=chr(Key_Return);
CH_LineFeed=chr(Key_LineFeed);
CH_Tab=chr(Key_Tab);
unallowedchars:set of ansichar=[CH_Blank,CH_Return,CH_LineFeed,CH_Tab];
//------------------------------------------------------------------
//
//------------------------------------------------------------------
constructor TCodeWindow.Create(AOwner:TComponent);
begin
inherited Create(AOwner);
RE:=AOwner as TRichEdit;
width:=120;
Height:=80;
Org_KeyUp:=nil;
Org_KeyDown:=nil;
Org_KeyPress:=nil;
setFont(RE.Font.Name,RE.Font.Size);
setColor(RE.Color);
setInvisible();
KeysAssigned:=false;
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
destructor TCodeWindow.Destroy;
begin
if Visible then
setInvisible();
inherited Free;
end;
//------------------------------------------------------------------
//add words found in editor --
//--
//------------------------------------------------------------------
procedure TCodeWindow.setCodeCompletionVerbs(Keys:PAnsiChar);
var
i,j,ll:integer;
dup:boolean;
ActKey:AnsiString;
begin
if (Keys=nil)or(Keys='') then begin
VerbBox.Items.Clear;
end
else begin
if not KeysAssigned then begin //Already done
Org_KeyUp:=RE.OnKeyUp;
Org_KeyDown:=RE.OnKeyDown;
Org_KeyPress:=RE.OnKeyPress;
with RE do begin
OnKeyUp:=On_KeyUp;
OnKeyDown:=On_KeyDown;
OnKeyPress:=On_KeyPress;
end;
KeysAssigned:=true;
end;
VerbBox.Items.Clear;
i:=0;
ll:=Length(Keys);
while i<ll do begin
ActKey:='';
while (i<ll)and(Keys[i]<>';') do begin
ActKey:=ActKey+Keys[i];
i:=succ(i);
end;
if (i<ll) then
i:=succ(i);
if ActKey>'' then begin
dup:=false;
for j:=0 to pred(VerbBox.Items.Count) do
if LowerCase(VerbBox.Items.Strings[j])=LowerCase(ActKey) then
dup:=true;
if not dup then
VerbBox.Items.add(LowerCase(ActKey));
end;
end;
end;
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.setFont(FontName:JString;FontSize:integer);
begin
Font.Name:=FontName;
Font.Size:=FontSize
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.setSize(codewidth:integer;codeheight:integer);
begin
width:=codewidth;
Height:=codeheight
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.VerbBoxKeyDown(Sender:TObject;var Key:Word;
Shift:TShiftState);
var
i,llb,ll:integer;
next:JString; found:boolean;
begin
case Key of
vk_Escape:
Visible:=false;
vk_Down:begin
if VerbBox.ItemIndex<pred(VerbBox.Items.Count) then
VerbBox.ItemIndex:=(VerbBox.ItemIndex+1);
Key:=0;
end;
vk_Up:begin
if (VerbBox.ItemIndex>0) then
VerbBox.ItemIndex:=(VerbBox.ItemIndex-1);
Key:=0;
end;
VK_RIGHT:begin
llb:=Length(WordBeg);
ll:=Length(WordFull);
if llb<ll then begin
WordBeg:=MidStr(WordFull,1,llb+1);
getPartialWord();
end;
end;
VK_left:begin
llb:=Length(WordBeg);
if llb>1 then begin
WordBeg:=MidStr(WordFull,1,llb-1);
getPartialWord();
end;
end;
vk_Return:begin
Key:=0;
setInvisible();
WriteSelectedWord;
end;
vk_Prior:begin
Key:=0;
PostMessage(Handle,wm_VScroll,SB_PAGEUP,VerbBox.TopIndex);
with VerbBox do
i:=(ClientHeight div ItemHeight);
i:=max(0,VerbBox.ItemIndex-i);
if VerbBox.Items.Count=0 then
i:=-1;
VerbBox.ItemIndex:=i;
end;
vk_Next:begin
Key:=0;
PostMessage(Handle,wm_VScroll,SB_PAGEDOWN,VerbBox.ItemIndex);
with VerbBox do
i:=(ClientHeight div ItemHeight);
i:=VerbBox.ItemIndex+i;
if i>=VerbBox.Items.Count then
i:=pred(VerbBox.Items.Count);
VerbBox.ItemIndex:=i;
end;
else begin
if (VerbBox.SelCount=0) then begin
for i:=0 to VerbBox.Items.Count-1 do
if ord(MidStr(VerbBox.Items[i],1,1))=Key then begin
VerbBox.ItemIndex:=i;
Verbboxprefix:=chr(Key);
end;
end
else begin
Verbboxprefix:=Verbboxprefix+chr(Key);
i:=0; found:=false;
next:='';
while not found and(i<VerbBox.Items.Count-1) do begin
next:=VerbBox.Items[i+1];
if pos(LowerCase(Verbboxprefix),LowerCase(next))=1 then begin
found:=true;
VerbBox.ItemIndex:=i+1;
end;
i:=i+1
end;
if not found then
Verbboxprefix:=midstr(Verbboxprefix,1,length(Verbboxprefix)-1);
end;
end;
end;
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.VerbBoxMouseLeave(Sender:TObject);
begin
PostMessage(Handle,WMHideCodeCompletion,0,0);
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.setColor(Col:TColor);
begin
Color:=Col
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.setPosition();
var
tp:tpoint;
fh:integer;
begin
//determine popup location
SendMessage(RE.Handle,EM_POSFROMCHAR,integer(@tp),RE.SelStart);
tp:=RE.ClientToScreen(tp);
fh:=abs(RE.Font.Height);
//spacer
fh:=fh+4;
tp.y:=tp.y+fh;
if tp.y+Height>=Screen.DesktopHeight then
tp.y:=tp.y-Height-(fh*2);
if tp.x+width>=Screen.DesktopWidth then
tp.x:=tp.x-width-20;
with PosRect do begin
Left:=tp.x;
Top:=tp.y;
Right:=Left+width;
Bottom:=Top+Height;
end;
BoundsRect:=PosRect;
if VerbBox.Items.Count>0 then
VerbBox.ItemIndex:=0;
OnKeyDown:=On_KeyDown;
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.On_KeyDown(Sender:TObject;var Key:Word;Shift:TShiftState);
begin
if not Visible and(VerbBox.Items.Count>0) then begin
if (Key=vk_space)and(ssCtrl in Shift) then begin
Key:=0;
Shift:=[];
REModif:=RE.Modified;
PostMessage(Handle,WMRemoveSpace,(Sender as TRichEdit).SelStart,0);
PostMessage(Handle,WMShowCodeCompletion,0,0);
end
end
else
PostMessage(Handle,WMHideCodeCompletion,0,0);
if assigned(Org_KeyDown) then
Org_KeyDown(Sender,Key,Shift);
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.On_KeyUp(Sender:TObject;var Key:Word;Shift:TShiftState);
begin
if assigned(Org_KeyUp) then
Org_KeyUp(Sender,Key,Shift);
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.On_KeyPress(Sender:TObject;var Key:char);
begin
if assigned(Org_KeyPress) then
Org_KeyPress(Sender,Key);
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.getPartialWord();
var
j:integer;
found:boolean;
Partword:JString;
begin
Partword:=LowerCase(WordBeg);
VerbBox.ItemIndex:=0;
j:=0;
found:=false;
while not found and(j<VerbBox.Items.Count)and(VerbBox.ItemIndex=0) do begin
if MidStr(LowerCase(VerbBox.Items[j]),1,Length(Partword))=Partword then
VerbBox.ItemIndex:=j;
j:=j+1
end;
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
function TCodeWindow.getTextBetween(lpos,rpos:integer):JString;
var
tr:textrange;
Res:JString;
c:ansichar;
ll:integer;
begin
Res:='';
if rpos>=lpos then begin
tr.chrg.cpMin:=lpos;
tr.chrg.cpMax:=rpos;
ll:=(rpos-lpos)+4;
ll:=((ll div 4)+1)*4;
GetMem(tr.lpstrText,ll);
SendMessage(RE.Handle,EM_GETTEXTRANGE,0,integer(@tr));
Res:=tr.lpstrText;
c:=ansichar(Res[1]);
if (c in unallowedchars) then
Res:='';
end;
getTextBetween:=Res
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.getCurrentWord();
var
startpos,endpos,allendpos:integer;
begin
WordBeg:='';
WordStart:=RE.SelStart;
WordEnd:=RE.SelStart;
endpos:=RE.SelStart;
startpos:=SendMessage(RE.Handle,EM_FINDWORDBREAK,WB_MOVEWORDLEFT,endpos);
WordBeg:=getTextBetween(startpos,endpos);
if WordBeg>'' then begin
WordFull:=WordBeg;
WordStart:=startpos;
WordEnd:=endpos;
if WordBeg>'' then begin
allendpos:=SendMessage(RE.Handle,EM_FINDWORDBREAK,WB_MOVEWORDRIGHT,
startpos);
if allendpos>-1 then begin
WordFull:=getTextBetween(startpos,allendpos);
WordStart:=startpos;
WordEnd:=allendpos;
end;
end;
end;
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.setInvisible();
begin
//RE.WantReturns:=not Visible;
//RE.WantTabs:=Visible;
hide();
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.WriteSelectedWord;
var
NewWord:JString;
begin
if VerbBox.ItemIndex>-1 then begin
NewWord:=VerbBox.Items[VerbBox.ItemIndex];
if Length(WordBeg)>0 then begin
RE.SelStart:=WordStart;
RE.SelLength:=WordEnd-WordStart
end
else begin
RE.SelStart:=WordStart-1;
RE.SelLength:=0;
end;
RE.SelText:=NewWord;
RE.SetFocus;
end;
PostMessage(Handle,WMHideCodeCompletion,0,0);
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.Msg_Show(var Msg:TMessage);
begin
Visible:=true;
setPosition();
getCurrentWord();
getPartialWord();
Verbboxprefix:=WordBeg;
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.Msg_Hide(var Msg:TMessage);
begin
Visible:=false;
end;
//------------------------------------------------------------------
//
//------------------------------------------------------------------
procedure TCodeWindow.Msg_Remove(var Msg:TMessage);
begin
RE.SelStart:=RE.SelStart-1;
RE.SelLength:=1;
RE.CutToClipboard;
RE.Modified:=REModif;
end;
//------------------------------------------------------------------
//--
//Ende dieser Quelle --
//--
//------------------------------------------------------------------
end.
¤ Dauer der Verarbeitung: 0.24 Sekunden
(vorverarbeitet)
¤
|
Haftungshinweis
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.
|