unit GCHyper; {$N-} interface {NSRHyper text format:} {'\+xxx ' = start link (xxx = link id) } {'\-' = end link } {'\Fxxx ' = select font xxx} {'\Sxxx ' = select paragraphs style xxx} {'\Cxxx ' = select text color xxx} {'\Bxxx ' = select paragraph background color xxx} {'\Axxx ' = insert autocharacter (xxx = type id xsize yasc ydesc) [space separated] (if xsize=0 then call callback)} {'\Oxxx ' = insert frame object: xxx = type id style xoffset xsize ysize} { example: /O1 121 WO 0 5 5 } {'\P' = page break } {'\L' = line break } {'\H' = hard space } {Frame styles:} { C - Child window. A child window will be created and then properly resized, by calling the callback function} { T - Transparent. Ignored if child window. Text goes over or under the frame} { W - Wrap around. Text is wrapped around the frame} { X - X-expand. The frame is expanded to the right} { P - Callback: get object size & offset by calling the callback procedure. This proc may also alter style!} { O - Overlaying. Ignored if child window or not transparent. Overlays the text} { M - Position is relative to margins; otherwise, it is relative to window/document margins} { R - Right aligned (default is left aligned)} uses CDEError,CDETypes,CDETools, WinProcs,WinTypes,Win31,Strings, _CDEHyp,_CDEUsr,CDETask,CDEMem16, CDE_Usr; function NSRHyperCompileText(txt:Pointer;var nct:TNHCompiledText):integer;export; procedure NSRHyperSetInfo(h:hWnd;p:PNHyperInfo);export; procedure NSRHyperTextInit;export; procedure NSRHyperTextDone;export; function NSRHyperHotSpotHandler (i:longint;hWindow:hWnd;fnc:integer;var hi:TNHyperInfo):longint; export; function NSRHyperTextHandler (p:PChar;hWindow:hWnd;fnc:integer;dc:hDC;s,c,f,x,y:longint;var hi:TNHyperInfo;var li:TNHyperLineInfo):longint; export; function NSRHyperBrushHandler (hWindow:hWnd;dc:hDC;s,b:longint;var ir,orr,fr,tr:TRect;var hi:TNHyperInfo):integer; export; function NSRHyperLineHandler (hWindow:hWnd;fnc:integer;dc:hDC;s,lt:longint;var i,o,f,t:TRect;var hi:TNHyperInfo):integer; export; function NSRHyperAutoCharHandler (p:PNHAutoChar;hWindow:hWnd;fnc:integer;dc:hDC;p1,p2:longint;var tr:TRect;var hi:TNHyperInfo;var l:TNHyperLineInfo):longint; export; function NSRHyperFrameHandler (p:PNHFrame;hWindow:hWnd;fnc:integer;dc:hDC;p1,p2:longint;var tr:TRect;var hi:TNHyperInfo):longint; export; implementation function NSRHyperHotSpotHandler; begin case fnc of hthotspotfnc_GetCursor: NSRHyperHotSpotHandler:=-1; hthotspotfnc_GetFont: NSRHyperHotSpotHandler:=-1; hthotspotfnc_GetColor: NSRHyperHotSpotHandler:=1; end end; function NSRHyperFrameHandler; var ob:hBrush; op:hPen; s:array[0..40] of char; begin with p^ do case fnc of htframefnc_ResizeChild: begin with tr do if hfWindow<>0 then MoveWindow(hfWindow,left,top,right-left,bottom-top,true); end; htframefnc_CreateChild: begin hfWindow:=CreateWindow( 'EDIT', 'Test', ws_Child or ws_Visible or ws_Caption or ws_Border, 0,0,0,0, hWindow, 0, hInstance, Nil); end; htframefnc_Paint: begin ob:=SelectObject(dc,GetStockObject(white_brush)); op:=SelectObject(dc,GetStockObject(black_pen)); Str(hfIDData,s); with hfRect do Rectangle(dc,left+3,top+3,right-3,bottom-3); TextOut(dc,hfRect.left,hfRect.top,s,StrLen(s)); SelectObject(dc,ob); SelectObject(dc,op); end; htframefnc_DeleteChild: begin DestroyWindow(hfWindow); hfWindow:=0; end; end end; function NSRHyperTextHandler; var tm:TTextMetric; tp:TPoint; i:integer; b:hBrush; begin case fnc of httextfnc_TextOut: begin with hi.hiFonts^[f] do if hfCallbackData=hfcbd_SuperScript then begin GetTextMetrics(dc,tm); y:=li.hliLPTop+tm.tmAscent; end; if li.hliSelected then begin longint(tp):=GetTextExtent(dc,p,StrLen(p)); with li do begin b:=SelectObject(dc,CreateSolidBrush(hi.hiUserInfo[hiuserinfo_TextHandler])); PatBlt(dc,x,hliLPTop,tp.x,hliLPBottom-li.hliLPTop,PatCopy); DeleteObject(SelectObject(dc,b)); end; end; NSRHyperTextHandler:=longint(TextOut(dc,x,y,p,StrLen(p))); end; httextfnc_GetCharFromPos: begin for i:=0 to StrLen(p) do begin longint(tp):=GetTextExtent(dc,p,i); if tp.x>x then Break; end; if i>=StrLen(p) then NSRHyperTextHandler:=StrLen(p)-1 else NSRHyperTextHandler:=i-1; end; httextfnc_GetPosFromChar: begin if x=0 then NSRHyperTextHandler:=0 else begin longint(tp):=GetTextExtent(dc,p,x); NSRHyperTextHandler:=tp.x; end end; httextfnc_GetTextExtent: begin NSRHyperTextHandler:=GetTextExtent(dc,p,StrLen(p)); end; httextfnc_GetSpaceExtent: begin NSRHyperTextHandler:=GetTextExtent(dc,' ',1); end; httextfnc_GetTextMetrics: begin NSRHyperTextHandler:=longint(GetTextMetrics(dc,TTextMetric(Pointer(p)^))); end; httextfnc_SpaceOut,httextfnc_TabFill: begin if li.hliSelected then with li do begin b:=SelectObject(dc,CreateSolidBrush(hi.hiUserInfo[hiuserinfo_TextHandler])); PatBlt(dc,x,hliLPTop,LoWord(longint(p)),hliLPBottom-li.hliLPTop,PatCopy); DeleteObject(SelectObject(dc,b)); end; end; end; end; function NSRHyperBrushHandler; {when this handler is called; default background brush is already selected} {in the dc} var ob:hBrush; begin with orr do if (s=-1) then begin PatBlt(dc,fr.left,fr.top,fr.right-fr.left,fr.bottom-fr.top,PatCopy); end else begin PatBlt(dc,fr.left,fr.top,left-fr.left,fr.bottom,PatCopy); PatBlt(dc,right,fr.top,fr.right-right,fr.bottom,PatCopy); if hi.hiBrushes<>Nil then ob:=SelectObject(dc,CreateBrushIndirect(PLogBrush(FIncPtr(hi.hiBrushes,WLongMul(b,SizeOf(TLogBrush))))^)); PatBlt(dc,left,top,right-left,bottom-top,PatCopy); if hi.hiBrushes<>Nil then DeleteObject(SelectObject(dc,ob)); end; end; function NSRHyperLineHandler; var op:hPen; ys:integer; begin op:=SelectObject(dc,CreatePen(ps_Solid,0,RGB(0,0,0))); if fnc=htlinefnc_TopLine then ys:=(o.top+i.top) div 2 else ys:=(o.bottom+i.bottom) div 2; MoveTo(dc,i.left,ys); LineTo(dc,i.right,ys); DeleteObject(SelectObject(dc,op)); end; function NSRHyperAutoCharHandler; var ob:hBrush; x,y:integer; begin case fnc of htautocharfnc_Paint: with p^ do begin x:=p1; y:=p2; ob:=SelectObject(dc,GetStockObject(black_brush)); PatBlt(dc,x,y-hacYAsc,hacXSize,hacYAsc,PatCopy); SelectObject(dc,GetStockObject(white_brush)); PatBlt(dc,x,y,hacXSize,hacYDsc,PatCopy); SelectObject(dc,ob); end; end end; const MaxLineLength =32767; {Win32S: correct to MaxLongInt!} NHFontChar =#1; NHHiliteChar =#2; NHColorChar =#3; NHAutoChar =#4; NHFrameChar =#5; NHSpaceChar =' '; NHParaChar =#10; NHNLChar =#13; NHTabChar =#9; NHLineBreakChar =#8; NHHardSpaceChar =#7; NHWordEnd =[NHFrameChar,NHParaChar,NHTabChar,NHSpaceChar,NHNLChar,NHLineBreakChar]; NHLineFractionEnd =[NHNLChar,NHTabChar,NHLineBreakChar]; dopaint_Paint =0; dopaint_Print =1; dopaint_Calculate =2; dopaint_GetChar =3; type PNHHotSpot =^TNHHotSpot; TNHHotSpot = record hsIndex :longint; {size fits into 64K!} end; PANHHotSpot =^TANHHotSpot; TANHHotSpot =array[0..0] of TNHHotSpot; PNHHotRect =^TNHHotRect; TNHHotRect = record hrIndex :longint; hrRect :TRect; hrYPos :integer; {size fits into 64K!} hrReserved :integer; end; PANHHotRect =^TANHHotRect; TANHHotRect =array[0..0] of TNHHotRect; PNHLineInfo =^TNHLineInfo; TNHLineInfo = record liLeftPos :integer; liAddPoints :integer; liSpaces :integer; liBottomLine :integer; liTabulator :integer; {size fits into 64K!} liParagraph :integer; {MAXIMUM = 32767 PARAGRAPHS!!!!!!!!} liTopLine :integer; liBaseLine :integer; end; PANHLineInfo =^TANHLineInfo; TANHLineInfo =array[0..0] of TNHLineInfo; PNHData =^TNHData; TNHData = record ndInfo :TNHyperInfo; ndRects :Pointer; ndText :Pointer; ndIndexes :Pointer; ndFontTable :PByte; ndParaTable :PNHParagraph; ndColorTable :PByte; ndAutoCharTable :PNHAutoChar; ndFrameTable :PNHFrame; ndFontTableSize :longint; ndParaTableSize :longint; ndColorTableSize :longint; ndAutoCharTableSize :longint; ndFrameTableSize :longint; ndLineInfo :Pointer; ndLineNum :longint; ndYPos :integer; ndXPos :integer; ndYSize :integer; ndYStep :integer; ndYEnd :integer; ndXSize :integer; ndXStep :integer; ndXEnd :integer; ndFreeze :bool; ndWidth :integer; ndInSelection :bool; ndSelFirstLine :longint; ndSelLastLine :longint; ndSelFirstPos :longint; ndSelLastPos :longint; ndSelFirstChar :longint; ndSelLastChar :longint; ndSelRect :TRect; ndSelStartPoint :TPoint; ndSelPositive :bool; ndSelExtended :bool; ndSelMouseIn :bool; ndError :integer; ndVScroll :bool; {has scroll} ndHScroll :bool; {has scroll} end; PNHPaintParam =^TNHPaintParam; TNHPaintParam = record nhppCharacter :longint; nhppCharRect :TSRect; nhppCharLine :longint; nhppPoint :TSPoint; end; {========} procedure NHCountHiliteFontParaColorCharFrames(p:PChar;var len,hilite,fonts,para,color,achar,frame:longint); var c:longint; inslash:bool; begin hilite:=0; fonts:=0; inslash:=false; para:=0; color:=0; achar:=0; frame:=0; len:=0; while p[0]<>#0 do begin if p[0]='\' then inslash:=not inslash else if (p[0] in ['+','-']) and inslash then begin Inc(hilite); inslash:=false; end else if (p[0] in ['f','F']) and inslash then begin Inc(fonts); inslash:=false; end else if (p[0] in ['c','C']) and inslash then begin Inc(color); inslash:=false; end else if (p[0] in ['a','A']) and inslash then begin Inc(achar); inslash:=false end else if (p[0] in ['o','O']) and inslash then begin Inc(frame); inslash:=false; end else if (p[0] in ['p','P','b','B','s','S','l','L','\','h','H']) then begin inslash:=false; end else if p[0]=NHParaChar then Inc(para); p:=FIncPtr1(p); Inc(len); end; hilite:=hilite div 2; end; function NHCompile( p:PChar; s:longint; var snew:longint; spots:PNHHotSpot; fonttable,paratable,colortable,achartable,frametable:Pointer; paranum:integer):PChar; function NHGetFrameStyle(var p:PChar):longint; var result:longint; begin result:=0; while p[0]=NHSpaceChar do p:=FIncPtr1(p); while p[0]<>NHSpaceChar do begin case p[0] of 'C','c': result:=BSet(result,hfstyle_ChildWindow ,true); 'T','t': result:=BSet(result,hfstyle_Transparent ,true); 'W','w': result:=BSet(result,hfstyle_WrapAround ,true); 'X','x': result:=BSet(result,hfstyle_XExpand ,true); 'O','o': result:=BSet(result,hfstyle_Overlaying ,true); 'M','m': result:=BSet(result,hfstyle_RelativeToMargin ,true); 'P','p': result:=BSet(result,hfstyle_CallbackParameter,true); 'R','r': result:=BSet(result,hfstyle_RightAligned ,true); end; p:=FIncPtr1(p); end; NHGetFrameStyle:=result; end; function NHGetLongint(var p:PChar):longint; var c:integer; ch:char; res:longint; minus:bool; begin while p[0]=NHSpaceChar do p:=FIncPtr1(p); ch:=p[0]; res:=0; while ch in ['0'..'9'] do begin res:=res*10; res:=res+ord(ch)-ord('0'); p:=FIncPtr1(p); ch:=p[0]; end; NHGetLongint:=res end; procedure NHAdvance; begin while p[0]<>NHSpaceChar do p:=FIncPtr1(p); p:=FIncPtr1(p); end; var c2:longint; p2,p2org,porg:PChar; inslash:bool; inhilite:bool; curpara:integer; b:longint; ch:char; procedure Put(ch:char); begin p2[0]:=ch; p2:=FIncPtr1(p2); Inc(c2); end; begin p2:=NGAlloc(gmem_Moveable,s); p2org:=p2; porg:=p; if p2<>Nil then begin c2:=0; inslash:=false; inhilite:=false; curpara:=0; PNHParagraph(paratable)^.hpStyle:=0; PNHParagraph(paratable)^.hpBkBrush:=0; PNHParagraph(paratable)^.hpPageBreak:=false; repeat if inslash then begin inslash:=false; ch:=p[0]; p:=FIncPtr1(p); case ch of '\': begin Put('\'); end; 'f','F': begin PByte(fonttable)^:=NHGetLongint(p); Put(NHFontChar); fonttable:=FIncPtr1(fonttable); NHAdvance; end; 'c','C': begin PByte(colortable)^:=NHGetLongint(p); Put(NHColorChar); colortable:=FIncPtr1(colortable); NHAdvance; end; 'h','H': begin Put(NHHardSpaceChar); NHAdvance; end; 'l','L': begin Put(NHLineBreakChar); NHAdvance; end; '+','-': if inhilite then begin inhilite:=false; Put(NHHiliteChar); end else begin inhilite:=true; spots^.hsIndex:=NHGetLongint(p); spots:=FIncPtrWord(spots,SizeOf(spots^)); Put(NHHiliteChar); NHAdvance; end; 's','S': begin PNHParagraph(paratable)^.hpStyle:=NHGetLongint(p); NHAdvance; end; 'b','B': begin PNHParagraph(paratable)^.hpBkBrush:=NHGetLongint(p); NHAdvance; end; 'a','A': begin PNHAutoChar(achartable)^.hacType:=NHGetLongint(p); NHAdvance; PNHAutoChar(achartable)^.hacIDData:=NHGetLongint(p); NHAdvance; PNHAutoChar(achartable)^.hacXSize:=NHGetLongint(p); NHAdvance; PNHAutoChar(achartable)^.hacYAsc:=NHGetLongint(p); NHAdvance; PNHAutoChar(achartable)^.hacYDsc:=NHGetLongint(p); NHAdvance; achartable:=FIncPtrWord(achartable,SizeOf(TNHAutoChar)); Put(NHAutoChar); end; 'p','P': begin PNHParagraph(paratable)^.hpPageBreak:=true; end; 'o','O': begin PNHFrame(frametable)^.hfRect.left:=0; PNHFrame(frametable)^.hfRect.top:=0; PNHFrame(frametable)^.hfRect.right:=0; PNHFrame(frametable)^.hfRect.bottom:=0; PNHFrame(frametable)^.hfWindow:=0; PNHFrame(frametable)^.hfParagraph:=curpara; PNHFrame(frametable)^.hfType:=NHGetLongint(p); NHAdvance; PNHFrame(frametable)^.hfIDData:=NHGetLongint(p); NHAdvance; PNHFrame(frametable)^.hfStyle:=NHGetFrameStyle(p); NHAdvance; PNHFrame(frametable)^.hfOffset:=NHGetFrameStyle(p); NHAdvance; PNHFrame(frametable)^.hfXSize:=NHGetLongint(p); NHAdvance; PNHFrame(frametable)^.hfYSize:=NHGetLongint(p); NHAdvance; frametable:=FIncPtr(frametable,SizeOf(TNHFrame)); Put(NHFrameChar); end; end end else begin case p[0] of '\': begin inslash:=true; end; NHNLChar:; NHParaChar: begin Put(NHParaChar); paratable:=FIncPtrWord(paratable,SizeOf(TNHParagraph)); Dec(paranum); Inc(curpara); if paranum>0 then begin PNHParagraph(paratable)^.hpStyle:=0; PNHParagraph(paratable)^.hpBkBrush:=0; PNHParagraph(paratable)^.hpPageBreak:=false; end end else Put(p[0]); end; p:=FIncPtr1(p); end until HPtrsDis(porg,p)>=s; Put(NHSpaceChar); Put(#0); end else begin NHCompile:=Nil; Exit; end; NGReAlloc(Pointer(p2org),c2,gmem_Moveable); NHCompile:=p2org; snew:=c2; end; function NHDeleteHotRect(p:Pointer):Pointer; begin NHDeleteHotRect:=Nil; NGFree(p); end; function NHCreateHotRect(p:Pointer):Pointer; begin NHDeleteHotRect(p); p:=NGAlloc(gmem_Moveable,SizeOf(longint)); PLongint(p)^:=0; NHCreateHotRect:=p; end; function NHAddHotRect(p:Pointer;tr:TRect;ndx:longint;var err:bool):Pointer; var ns:longint; hnd2:THandle; begin err:=false; ns:=(PLongint(p)^+1)*SizeOf(TNHHotRect)+SizeOf(longint); GlobalUnlock(HiWord(longint(p))); hnd2:=GlobalRealloc(HiWord(longint(p)),ns,gmem_Moveable); if hnd2=0 then begin err:=true; p:=GlobalLock(HiWord(longint(p))); end else begin p:=GlobalLock(hnd2); ns:=PLongint(p)^; Inc(PLongint(p)^); with PNHHotRect(FIncPtr(p,4+ns*SizeOf(TNHHotRect)))^ do begin hrRect:=tr; hrIndex:=ndx; end; end; NHAddHotRect:=p; end; function NHFindHotRect(p:Pointer;tp:TPoint):longint; var pr:PNHHotRect; num,c:longint; begin if p<>Nil then begin num:=PLongint(p)^; pr:=FIncPtr4(p); for c:=0 to num-1 do begin with pr^ do if PtInRect(hrRect,tp) then begin NHFindHotRect:=hrIndex; Exit end; pr:=FIncPtrWord(pr,SizeOf(TNHHotRect)) end end; NHFindHotRect:=-1; end; procedure NHPrepareText(p:PChar); begin while p[0]<>#0 do begin if p[0]=NHNLChar then p[0]:=NHSpaceChar; p:=FIncPtr1(p); end; end; procedure NHGetAllData(w:hWnd;data:PNHData); {Get addittional callback data (like frame style P)} var c:longint; frametable:PNHFrame; autochartable:PNHAutoChar; dummy:TRect; dummyli:TNHyperLineInfo; begin with data^ do begin frametable:=ndFrameTable; autochartable:=ndAutoCharTable; for c:=1 to ndAutoCharTableSize do begin with autochartable^ do if hacXSize=0 then HTAutoCharHandler(ndInfo.hiAutoCharFnc)(autochartable,w,htautocharfnc_GetSize,0,0,0,dummy,ndInfo,dummyli); autochartable:=FIncPtrWord(autochartable,SizeOf(autochartable^)); end; for c:=1 to ndFrameTableSize do begin with frametable^ do begin if BGet(hfStyle,hfstyle_CallbackParameter) then HTFrameHandler(ndInfo.hiFrameFnc)(frametable,w,htframefnc_GetSizeOffset,0,0,0,dummy,ndInfo); if BGet(hfStyle,hfstyle_ChildWindow) then HTFrameHandler(ndInfo.hiFrameFnc)(frametable,w,htframefnc_CreateChild,0,0,0,dummy,ndInfo); end; frametable:=FIncPtrWord(frametable,SizeOf(frametable^)); end; end; end; procedure NHReleaseAllWindows(w:hWnd;data:PNHData); var c:longint; frametable:PNHFrame; dummy:TRect; begin with data^ do begin frametable:=ndFrameTable; for c:=1 to ndFrameTableSize do begin with frametable^ do begin if BGet(hfStyle,hfstyle_ChildWindow) then HTFrameHandler(ndInfo.hiFrameFnc)(frametable,w,htframefnc_DeleteChild,0,0,0,dummy,ndInfo); end; frametable:=FIncPtrWord(frametable,SizeOf(frametable^)); end; end; end; procedure NHInitFonts(data:PNHData); var c:integer; begin with data^.ndInfo do for c:=0 to hiNumFonts-1 do with hiFonts^[c] do hfHandle:=0; end; procedure NHDoneFonts(data:PNHData); var c:integer; begin with data^.ndInfo do for c:=0 to hiNumFonts-1 do with hiFonts^[c] do begin if hfHandle<>0 then DeleteObject(hfHandle); hfHandle:=0; end end; procedure NHGetStyle(style_no:integer;var style:TNHStyle;data:PNHData); begin with data^ do HUCopy( FIncPtrWord( ndInfo.hiStyles, WLongMul( SizeOf(style), style_no)), @style, SizeOf(style)); end; procedure NHCutText(hWindow:hWnd;dc:hDC;width:integer;var ypos,lines,xlen:integer;data:PNHData); var fonttable,oldfonttable:PByte; para:longint; autochartable,oldautochartable:PNHAutoChar; p,oldp,buffer:PChar; bufferlen:integer; font,oldfont:byte; maxysize:integer; maxyasc:integer; marginleft,marginright,cmarginleft,cmarginright:integer; style:TNHStyle; indent,tabnumber,newindent,oldindent,tabcount:integer; line,lastline:longint; frame,advframe:longint; wordnumber:integer; inframe,rightframe,intab:bool; frameto:integer; yasc,ydsc,xsize,ya,yd,xs,ys,nextspace:integer; tmet:TTextMetric; tp:TPoint; indexes,oldindexes:PNHHotSpot; inhilite,oldinhilite:bool; hilitefont,oldhilitefont:integer; firstparaline,firstlineline:bool; li:TNHyperLineInfo; procedure NHSelectFont; var f:byte; begin begin if inhilite then if hilitefont>=0 then f:=hilitefont else f:=font else f:=font end; with data^ do with ndInfo do with hiFonts^[f] do begin if hfHandle=0 then hfHandle:=CreateFontIndirect(hfFont); SelectObject(dc,hfHandle); HTTextHandler(hiTextFnc)( PChar(Pointer(@tmet)), hWindow, httextfnc_GetTextMetrics, dc, para, 0, font, 0, 0, ndInfo, li); end; end; function NHGetNextWord(var xsize,ysize,yasc,ydsc:integer):bool; var wordstart:PChar; partstart:PChar; wordend:PChar; len:integer; tp:TPoint; tr:TRect; charnum:longint; begin {store everything in case the word does not fit. In such case, we break the line} {and try again with the same word and all} oldfont:=font; oldfonttable:=fonttable; oldautochartable:=autochartable; oldindexes:=indexes; oldp:=p; oldinhilite:=inhilite; oldhilitefont:=hilitefont; {find start and end of the word} wordstart:=p; while not (p[0] in NHWordEnd) do p:=FIncPtr1(p); wordend :=p; p :=wordstart; {for now, the yAsc and xAsc are taken from the current font; also, the size of the word} {is still zero} xsize:=0; yasc :=tmet.tmAscent; ydsc :=tmet.tmDescent; NHGetNextWord:=false; with data^ do repeat partstart:=p; {part=the characters with the same font&hilite-status&color within the word} while not ((p[0] in [NHHiliteChar,NHFontChar,NHAutoChar,NHColorChar]) or (longint(p)>=longint(wordend))) do p:=FIncPtr1(p); {the number of characters in the part=} len:=HPtrsDis(partstart,p); if len>=32767 then ndError:=nderror_WordTooLong else if len>0 then begin {we'll copy the characters in the buffer in case they break the segment limit} if len>bufferlen then begin if not NGRealloc(Pointer(buffer),len+1,gmem_Moveable) then begin ndError:=nderror_OutOfMem; Exit end; bufferlen:=len; end; HUCopy(partstart,buffer,len); PChar(FIncPtrWord(buffer,len))[0]:=#0; longint(tp):= HTTextHandler(ndInfo.hiTextFnc) (buffer,hWindow,httextfnc_GetTextExtent,dc,para,0,font,0,0,data^.ndInfo,li); Inc(xsize,tp.x); {extend the descent & ascent} if ydsc<tmet.tmDescent then ydsc:=tmet.tmDescent; if yasc<tmet.tmAscent then yasc:=tmet.tmAscent; end; while p[0]=NHFontChar do begin p:=FIncPtr1(p); font:=PByte(fonttable)^; fonttable:=FIncPtr1(fonttable); NHSelectFont; end; while p[0]=NHAutoChar do begin p:=FIncPtr1(p); with autochartable^ do begin Inc(xsize,hacXSize); if yasc<hacYAsc then yasc:=hacYAsc; if ydsc<hacYDsc then ydsc:=hacYDsc; end; autochartable:=FIncPtrWord(autochartable,SizeOf(autochartable^)); end; while p[0]=NHHiliteChar do begin p:=FIncPtr1(p); if inhilite then begin inhilite:=false; indexes:=FIncPtr(indexes,SizeOf(indexes^)); NHSelectFont; end else begin inhilite:=true; hilitefont:= HTHotSpotHandler(ndInfo.hiHotSpotFnc)( indexes^.hsIndex, hWindow, hthotspotfnc_GetFont, ndInfo); NHSelectFont end; end; while p[0] in [NHColorChar] do p:=FIncPtr1(p); until longint(p)>=longint(wordend); ysize:=yasc+ydsc; p:=wordend; NHGetNextWord:=true; end; procedure NHReturnState; begin {restore old fonts etc} font:=oldfont; fonttable:=oldfonttable; autochartable:=oldautochartable; p:=oldp; inhilite:=oldinhilite; hilitefont:=oldhilitefont; indexes:=oldindexes; NHSelectFont; end; function NFrame(i:longint):PNHFrame; begin NFrame:=FIncPtr(data^.ndFrameTable,i*SizeOf(TNHFrame)) end; function NLineInfo(i:longint):PNHLineInfo; begin NLineInfo:=FIncPtr(data^.ndLineInfo,i*SizeOf(TNHLineInfo)) end; function NPara(i:longint):PNHParagraph; begin NPara:=FIncPtr(data^.ndParaTable,i*SizeOf(TNHParagraph)) end; {tukaj naprej se komentiraj!} procedure NHAddFrame; procedure NAlignFrame; var style:TNHStyle; marginright,marginleft:integer; begin with NFrame(frame)^ do with hfRect do begin top:=ypos; NHGetStyle(NPara(hfParagraph)^.hpStyle,style,data); with style do begin marginleft:=hsLeftSpace; marginright:=width-hsRightSpace; end; if BGet(hfStyle,hfStyle_RightAligned) then begin if BGet(hfStyle,hfStyle_RelativeToMargin) then right:=marginright-hfOffset else right:=width-hfOffset; if BGet(hfStyle,hfStyle_XExpand) then if BGet(hfStyle,hfStyle_RelativeToMargin) then left:=marginleft else left:=0 else left:=right-hfXSize; rightframe:=true; end else begin if BGet(hfStyle,hfStyle_RelativeToMargin) then left:=marginleft+hfOffset else left:=hfOffset; if BGet(hfStyle,hfStyle_XExpand) then if BGet(hfStyle,hfStyle_RelativeToMargin) then right:=marginright else right:=width else right:=left+hfXSize; rightframe:=false; end; bottom:=top+hfYSize; frameto:=bottom; end end; begin with NFrame(frame)^ do begin if BGet(hfStyle,hfstyle_Transparent) and (not BGet(hfStyle,hfstyle_ChildWindow)) then begin NAlignFrame; inframe:=true; end else begin NAlignFrame; if BGet(hfStyle,hfstyle_XExpand) or (not BGet(hfStyle,hfstyle_WrapAround)) then begin ypos:=frameto; inframe:=false; end else begin inframe:=true; if BGet(hfStyle,hfstyle_RightAligned) then begin if cmarginright>hfRect.left then cmarginright:=hfRect.left end else begin if cmarginleft<hfRect.right then cmarginleft:=hfRect.right; end end; end end; Inc(frame); end; procedure NHCheckEndOfFrame; {repairs ypos to fit remaining frames on the 'stack'} begin if inframe then if ypos>=frameto then begin {only if the current paragraph 'swallowed' the current frame we can state} {that the frame has been 'put'} inframe:=false; {in that case, margins return to normal} cmarginleft:=marginleft; cmarginright:=marginright; end; {we have some frames in advance and we have already 'put' current frame; so let's} {advance to the next frame} while (advframe>0) and (not inframe) do begin NHAddFrame; Dec(advframe); end; end; procedure NHFeedLine(eol,eopara:bool); var c:longint; baseline,bottomline:longint; {add new line of text to the buffer.} begin with data^ do if not NGRealloc(ndLineInfo,(line+1)*SizeOf(TNHLineInfo),gmem_Moveable) then ndError:=nderror_OutOfMem else begin with NLineInfo(line)^ do begin {LeftPos=margin + indent} liLeftPos :=cmarginleft+indent; {number of spaces in the line is the same as wordnumber - 1} liSpaces :=wordnumber-1; liTopLine :=ypos; liBaseLine :=ypos+yasc; liBottomLine :=ydsc; liAddPoints :=0; liTabulator :=tabnumber; {the paragraph of the line} liParagraph :=para; {if the tabulating was caused by auto indent, mark it with - sign} if not intab then liTabulator:=-liTabulator; end; {do we have the new line (against: only a fraction of a line separated by a tabulator)} if eol then begin {increase the number of lines (meaning <real lines> of text, not NLineInfo lines} Inc(lines); {do the formatting of the line} with NLineInfo(line)^ do case style.hsParaFormat of hsparaformat_Right: begin liLeftPos :=cmarginright-xsize; {xsize=length of this line!} end; hsparaformat_Center: begin liLeftPos :=(liLeftPos+cmarginright-xsize) div 2; end; hsparaformat_Justify: begin {we dont' justify the last line in the paragraph} if not eopara then liAddPoints :=cmarginright-liLeftPos-xsize; end; hsparaformat_Continuous: begin if xlen<(xsize+liLeftPos) then xlen:=xsize+liLeftPos; end; end; {intab=false, so we'll be able to mark liTabulator with - sign if no AutoIndent} intab:=false; if not BGet(style.hsParaStyle,hsparastyle_AutoIndent) then begin {if no autoindent, reset tabulators and indent} tabnumber:=0; end; {if there is no autoindent [otherwise, keep offset]} {reset offset to +0 for next lines!} if (tabnumber=0) then if style.hsFirstIndent<0 then {if firstindent is negative, all other lines are moved to the right,} {not the first one to the left} indent:=abs(style.hsFirstIndent) else indent:=0; {lastline=the first fraction of this line. Because now we have all info for the} {whole real line, we can set the baselines to all fractions!} if lastline<=line then begin baseline:=0; bottomline:=0; {find the lowest baseline and bottomline} for c:=lastline to line do with NLineInfo(c)^ do begin if baseline<liBaseLine then baseline:=liBaseLine; if bottomline<liBottomLine then bottomline:=liBottomLine; end; bottomline:=baseline+bottomline; {it was not bottomline indeed; it was ydsc!!!} ypos:=bottomline; {new, corrected ypos} for c:=lastline to line do with NLineInfo(c)^ do begin liBaseLine:=baseline; {all fractions within same line have the same baseline!!!} liBottomLine:=bottomline; end; end; lastline:=line+1; {the NEXT line is the FIRST line of the next set!!!} Inc(ypos,style.hsLineSpace); {increase yposition for line space of the paragraph!} {check if the frame has already been 'swallowed'}; NHCheckEndOfFrame; end; yasc:=0; ydsc:=0; xsize:=0; wordnumber:=0; nextspace:=0; Inc(line); end; end; function NHNextParagraphBreak:bool; {is the next paragraph meant to be kept with current one?} var style:TNHStyle; begin with data^ do {not if it's the last paragraph} if para>=(ndParaTableSize-1) then NHNextParagraphBreak:=true else with NPara(para+1)^ do {not if there's a page break} if hpPageBreak then NHNextParagraphBreak:=true else begin {not if the next paragraph's style doesn't allow it!} NHGetStyle(hpStyle,style,data); NHNextParagraphBreak:=not BGet(style.hsParaStyle,hsparastyle_LinkToPrevious); end; end; procedure NHCloseParagraph; var c:longint; begin with NPara(para)^ do begin {place all frames on the 'stack'} NHCheckEndOfFrame; {if the paragraph is not kept with the next one, we have to 'put' all frames from the 'stack'} if NHNextParagraphBreak then begin if inframe then begin ypos:=frameto; inframe:=false; end; while advframe>0 do begin NHAddFrame; ypos:=frameto; inframe:=false; Dec(advframe); end end; Inc(ypos,style.hsBottomSpace); {place all frames on the 'stack'; remember: because of the bottom paragraph spacing,} {the paragraph might have 'swallowed' the frame, so we're testing again} NHCheckEndOfFrame; hpEndPosition:=ypos; tabnumber:=0; end; end; function NHNewParagraph:bool; begin if para=data^.ndParaTableSize then begin NHNewParagraph:=false; {no more paragraphs} Exit; end; NHNewParagraph:=true; with NPara(para)^ do begin NHGetStyle(hpStyle,style,data); {paragraph start position will be the same as current yposition} hpPosition:=ypos; {+ topspace} Inc(ypos,style.hsTopSpace); {place all frames on the 'stack'} NHCheckEndOfFrame; with style do begin if hsFirstIndent>0 then indent:=hsFirstIndent else indent:=0; {set original margins} marginleft:=hsLeftSpace; marginright:=width-hsRightSpace; {however, if the frame hasn't been 'put' yet, there is less space for text, so} {we keep c(urrent)margins on the frame's side of the paper} if inframe then if rightframe then begin cmarginleft:=marginleft; if marginright<cmarginright then cmarginright:=marginright; end else begin cmarginright:=marginright; if marginleft>cmarginleft then cmarginleft:=marginleft; end else begin {there is no frame, so current margins are same as paragraph (style) margins} cmarginleft:=marginleft; cmarginright:=marginright; end; {tabposition is zero} tabnumber:=0; end; end end; begin with data^ do with ndInfo do begin ndError:=nderror_Ok; if ndLineInfo<>Nil then NGFree(ndLineInfo); ndLineInfo:=NGAlloc(gmem_Moveable,0); if ndLineInfo=Nil then begin ndError:=nderror_OutOfMem; Exit; end; NHInitFonts(data); buffer:=NGAlloc(gmem_Moveable,1); bufferlen:=0; fonttable:=ndFontTable; oldfonttable:=Nil; autochartable:=ndAutoCharTable; oldautochartable:=Nil; indexes:=ndIndexes; oldindexes:=Nil; p:=ndText; oldp:=Nil; hilitefont:=0; oldhilitefont:=0; inhilite:=false; oldinhilite:=false; font:=0; oldfont:=0; lines:=0; xlen:=0; NHSelectFont; advframe:=0; {!!!!} frame:=0; para:=0; indent:=0; tabnumber:=0; line:=0; lastline:=0; wordnumber:=0; xsize:=0; ypos:=0; yasc:=0; ydsc:=0; nextspace:=0; inframe:=false; NHNewParagraph; repeat case p[0] of NHParaChar: begin {feed line and make it a real line, end of paragraph} NHFeedLine(true,true); NHCloseParagraph; Inc(para); if not NHNewParagraph then Break; if ndError<>nderror_Ok then Break; p:=FIncPtr1(p); Continue; end; NHFrameChar: begin if (wordnumber=0) and (not inframe) and (advframe=0) then begin advframe:=0; NHAddFrame; end else Inc(advframe); p:=FIncPtr1(p); end; NHLineBreakChar: begin NHFeedLine(true,false); if ndError<>nderror_Ok then Break; p:=FIncPtr1(p); Continue; end; NHTabChar: begin intab:=true; newindent:=indent; oldindent:=indent+xsize; NHFeedLine(false,false); if ndError<>nderror_Ok then Break; with style do while tabnumber<hsNumTabs do begin newindent:=hsTabs[tabnumber].htPosition; Inc(tabnumber); if newindent>=oldindent then Break; end; indent:=newindent; p:=FIncPtr1(p); Continue; end; NHSpaceChar: begin p:=FIncPtr1(p); Continue; end; end; if not NHGetNextWord(xs,ys,ya,yd) then Break; if (nextspace=0) or ((cmarginleft+indent+xsize+nextspace+xs)<cmarginright) or (BGet(style.hsParaFormat,hsparaformat_Continuous)) then begin if ya>yasc then yasc:=ya; if yd>ydsc then ydsc:=yd; Inc(wordnumber); Inc(xsize,nextspace); Inc(xsize,xs); longint(tp):= HTTextHandler(data^.ndInfo.hiTextFnc) (Nil,hWindow,httextfnc_GetSpaceExtent,dc,para,0,font,0,0,data^.ndInfo,li); if tp.x=0 then tp.x:=1; nextspace:=tp.x; end else begin NHReturnState; NHFeedLine(true,false); p:=FDecPtr1(p); if p[0]=NHSpaceChar then p[0]:=NHNLChar; p:=FIncPtr1(p); end; until false; SelectObject(dc,GetStockObject(System_Font)); NGFree(Pointer(buffer)); NHDoneFonts(data); end; end; procedure NHPaintText(hWindow:hWnd;dc:hDC;var tr:TRect;data:PNHData;doPaint:integer;var prm:TNHPaintParam); var fonttable:PByte; para:longint; colortable:PByte; autochartable:PNHAutoChar; p,buffer:PChar; bufferlen:integer; font:byte; line:PNHLineInfo; linenum:longint; nextspace:integer; currentword:integer; color:byte; inhilite:bool; inhilitefont:integer; inhilitecolor:integer; xpos:integer; hotrect:TRect; indexes:PNHHotSpot; err:bool; li:TNHyperLineInfo; charnum:longint; lchar,lline,llpos,lrpos:longint;{last possible char/line/left,right for GetCharacter; if clicked out of line} procedure NHSelectColor; var c:byte; begin {we only change color when painting. Isn't it so?} if doPaint in [dopaint_Paint,dopaint_Print] then begin if inhilite then if inhilitecolor>=0 then c:=inhilitecolor else c:=color else c:=color; with data^.ndInfo do SetTextColor(dc,hiColors^[c]); end end; procedure NHSelectFont; var f:byte; begin {we change font always: for calculating & for painting} if inhilite then if inhilitefont>=0 then f:=inhilitefont else f:=font else f:=font; with data^.ndInfo.hiFonts^[f] do begin if hfHandle=0 then hfHandle:=CreateFontIndirect(hfFont); SelectObject(dc,hfHandle); end; end; function NHGetSpaceSize:integer; {returns the size of the next space (justified!)} begin with line^ do if (liAddPoints>0) and (liSpaces>0) and (nextspace<>0) then begin NHGetSpaceSize:= nextspace + QuadMulDiv(liAddPoints,currentword+1,liSpaces) - QuadMulDiv(liAddPoints,currentword,liSpaces); end else NHGetSpaceSize:=nextspace; end; function NHCheckInSelection:bool; {fills the lineinfo structure with selection start and selection end parameters.} {it also sets hliSelected to true if the line is selected.} begin with li,data^ do begin hliSelected:=false; hliSelStart:=0; hliSelEnd:=MaxLineLength; if ndInSelection then if (linenum>=ndSelFirstLine) and (linenum<=ndSelLastLine) then begin hliSelected:=true; if linenum=ndSelFirstLine then hliSelStart:=ndSelFirstPos; if linenum=ndSelLastLine then hliSelEnd:=ndSelLastPos; end; end; end; function NHPaintNextWord:bool; {paints or calculates the next word} var wordstart:PChar; partstart:PChar; wordend:PChar; len:integer; tp:TPoint; tr:TRect; olddc:integer; rgn:hRgn; charnum:longint; begin wordstart:=p; while not (p[0] in NHWordEnd) do p:=FIncPtr1(p); wordend :=p; p :=wordstart; NHPaintNextWord:=false; with data^ do repeat partstart:=p; while not ((p[0] in [NHHiliteChar,NHFontChar,NHAutoChar,NHColorChar]) or (longint(p)>=longint(wordend))) do p:=FIncPtr1(p); len:=HPtrsDis(partstart,p); if len>=32767 then ndError:=nderror_WordTooLong else if len>0 then begin if len>bufferlen then begin if not NGRealloc(Pointer(buffer),len+1,gmem_Moveable) then begin ndError:=nderror_OutOfMem; Exit end; bufferlen:=len; end; HUCopy(partstart,buffer,len); PChar(FIncPtrWord(buffer,len))[0]:=#0; {get the index of the character} charnum:=HPtrsDis(ndText,partstart); longint(tp):= HTTextHandler(ndInfo.hiTextFnc) (buffer,hWindow,httextfnc_GetTextExtent,dc,line^.liParagraph,0,font,0,0,data^.ndInfo,li); {Paint} if dopaint in [dopaint_Paint,dopaint_Print] then with li do begin hliLPLeft:=line^.liLeftPos; hliLPTop:=line^.liTopLine; hliLPBottom:=line^.liBottomLine; olddc:=0; NHCheckInSelection; if hliSelected then if (hliSelStart<=(xpos+tp.x)) and (hliSelEnd>=xpos) then begin hliSelected:=true; olddc:=SaveDC(dc); ExcludeClipRect(dc,xpos,line^.liTopline,hliSelStart,line^.liBottomLine); ExcludeClipRect(dc,hliSelEnd,line^.liTopline,xpos+tp.x,line^.liBottomLine); HTTextHandler(ndInfo.hiTextFnc)( buffer, hWindow, httextfnc_TextOut, dc, line^.liParagraph, color, font, xpos, line^.liBaseline, data^.ndInfo, li); RestoreDC(dc,olddc); olddc:=SaveDC(dc); ExcludeClipRect(dc,hliSelStart,line^.liTopline,hliSelEnd,line^.liBottomLine); hliSelected:=false end else hliSelected:=(hliSelStart<=xpos) and (hliSelEnd>=(xpos+tp.x)); HTTextHandler(ndInfo.hiTextFnc)( buffer, hWindow, httextfnc_TextOut, dc, line^.liParagraph, color, font, xpos, line^.liBaseline, data^.ndInfo, li); if olddc<>0 then RestoreDC(dc,olddc); end {Calculate} else if dopaint in [dopaint_Calculate] then begin {calculating the selection} if ndInSelection then begin if (ndSelFirstChar<charnum) and (ndSelFirstPos=-1) then begin {safety: if the SelFirstChar is a formatting character} ndSelFirstLine:=linenum; ndSelFirstPos:=xpos; end else if (ndSelFirstChar>=charnum) and (ndSelFirstChar<(charnum+len)) then begin {otherwise, if the selcharacter is within the word, calculate the positions} ndSelFirstLine:=linenum; ndSelFirstPos:=xpos+HTTextHandler(ndInfo.hiTextFnc)( buffer, hWindow, httextfnc_GetPosFromChar, dc, para, 0, font, ndSelFirstChar-charnum, 0, data^.ndInfo, li); end; if (ndSelLastChar<charnum) and (ndSelLastPos=-1) then begin {safety: if the SelFirstChar is a formatting character} ndSelLastLine:=linenum; ndSelLastPos:=xpos; end else if (ndSelLastChar>=charnum) and (ndSelLastChar<(charnum+len)) then begin {otherwise, if the selcharacter is within the word, calculate the positions} ndSelLastLine:=linenum; ndSelLastPos:=xpos+HTTextHandler(ndInfo.hiTextFnc)( buffer, hWindow, httextfnc_GetPosFromChar, dc, para, 0, font, ndSelLastChar-charnum+1, {+1: selection is UP TO the next character} 0, data^.ndInfo, li); end; end; {calculating hotspots} if inhilite then begin SetRect(tr,xpos,line^.liTopLine,xpos+tp.x,line^.liBottomLine); UnionRect(hotrect,hotrect,tr); end; end {GetChar} else if dopaint in [dopaint_GetChar] then with prm do begin if (nhppPoint.x<xpos) and (nhppCharacter=-1) then begin nhppCharacter:=charnum; {safety:} nhppCharLine:=linenum; nhppCharRect.left:=xpos; nhppCharRect.right:=xpos+HTTextHandler(ndInfo.hiTextFnc)( buffer, hWindow, httextfnc_GetPosFromChar, dc, para, 0, font, 1, {end of the first character} 0, data^.ndInfo, li); end else if (nhppPoint.x>=xpos) and (nhppPoint.x<(xpos+tp.x)) then begin nhppCharLine:=linenum; nhppCharacter:=HTTextHandler(ndInfo.hiTextFnc)( buffer, hWindow, httextfnc_GetCharFromPos, dc, line^.liParagraph, 0, font, nhppPoint.x-xpos, 0, data^.ndInfo, li); nhppCharRect.left:=xpos+HTTextHandler(ndInfo.hiTextFnc)( buffer, hWindow, httextfnc_GetPosFromChar, dc, para, 0, font, nhppCharacter, 0, data^.ndInfo, li); nhppCharRect.right:=xpos+HTTextHandler(ndInfo.hiTextFnc)( buffer, hWindow, httextfnc_GetPosFromChar, dc, para, 0, font, nhppCharacter+1, 0, data^.ndInfo, li); nhppCharacter:=nhppCharacter+charnum end end; Inc(xpos,tp.x); end; while p[0]=NHFontChar do begin p:=FIncPtr1(p); font:=PByte(fonttable)^; fonttable:=FIncPtr1(fonttable); NHSelectFont; end; while p[0]=NHAutoChar do begin {get the index of the character} charnum:=HPtrsDis(ndText,p); p:=FIncPtr1(p); {Paint} if dopaint in [dopaint_Paint,dopaint_Print] then begin with li do begin hliLPLeft:=line^.liLeftPos; hliLPTop:=line^.liTopLine; hliLPBottom:=line^.liBottomLine; NHCheckInSelection; with li do if hliSelected then hliSelected:=(hliSelStart<=xpos) and (hliSelEnd>=(xpos+autochartable^.hacXSize)); end; HTAutoCharHandler(ndInfo.hiAutoCharFnc)( autochartable, hWindow, htautocharfnc_Paint, dc, xpos, line^.liBaseline, tr, ndInfo, li); end {Calculate} else if dopaint in [dopaint_Calculate] then begin if ndInSelection then begin if (ndSelFirstChar<charnum) and (ndSelFirstPos=-1) then begin {safety: formatting characters} ndSelFirstLine:=linenum; ndSelFirstPos:=xpos; end else if (ndSelFirstChar=charnum) then begin ndSelFirstLine:=linenum; ndSelFirstPos:=xpos; end; if (ndSelLastChar<charnum) and (ndSelFirstPos=-1) then begin {safety: formatting characters} ndSelLastLine:=linenum; ndSelLastPos:=xpos end else if (ndSelLastChar=charnum) then begin ndSelLastLine:=linenum; ndSelLastPos:=xpos+autochartable^.hacXSize; end; end; end else if dopaint in [dopaint_GetChar] then with prm do begin if (nhppPoint.x<xpos) and (nhppCharacter=-1) then begin nhppCharLine:=linenum; nhppCharacter:=charnum; {safety} nhppCharRect.left:=xpos; nhppCharRect.right:=xpos+autochartable^.hacXSize; end else if (prm.nhppPoint.x>=xpos) and (prm.nhppPoint.x<(xpos+autochartable^.hacXSize)) then begin nhppCharLine:=linenum; nhppCharacter:=charnum; {safety} nhppCharRect.left:=xpos; nhppCharRect.right:=xpos+autochartable^.hacXSize; end end; Inc(xpos,autochartable^.hacXSize); autochartable:=FIncPtrWord(autochartable,SizeOf(autochartable^)); end; while p[0] in [NHColorChar] do begin p:=FIncPtr1(p); color:=colortable^; colortable:=FIncPtr1(colortable); NHSelectColor; end; while p[0] in [NHHiliteChar] do begin p:=FIncPtr1(p); if inhilite then begin inhilite:=false; NHSelectColor; NHSelectFont; if dopaint in [dopaint_Calculate] then ndRects:=NHAddHotRect(ndRects,hotrect,indexes^.hsIndex,err); indexes:=FIncPtr(indexes,SizeOf(indexes^)); end else begin inhilite:=true; inhilitefont:=HTHotSpotHandler(ndInfo.hiHotSpotFnc)(indexes^.hsIndex,hWindow,hthotspotfnc_GetFont,ndInfo); inhilitecolor:=HTHotSpotHandler(ndInfo.hiHotSpotFnc)(indexes^.hsIndex,hWindow,hthotspotfnc_GetColor,ndInfo); NHSelectFont; NHSelectColor; if dopaint in [dopaint_Calculate] then SetRect(hotrect,32767,32767,-32767,-32767); end; end; until longint(p)>=longint(wordend); p:=wordend; NHPaintNextWord:=true; end; function NHFeedLine(charnum:longint):bool; begin with data^ do with line^,li do begin if liTabulator<0 then xpos:=0; {indented tabulator: 0 - liLeftPos} if liTabulator<>0 then {Paint} if dopaint in [dopaint_Print,dopaint_Paint] then begin li.hliLPLeft:=line^.liLeftPos; li.hliLPTop:=line^.liTopLine; li.hliLPBottom:=line^.liBottomLine; NHCheckInSelection; if hliSelected then hliSelected:=(hliSelStart<=xpos) and (hliSelEnd>=liLeftPos); HTTextHandler(ndInfo.hiTextFnc)( Pointer(MakeLong(liLeftPos-xpos,liTabulator)), hWindow, httextfnc_TabFill, dc, line^.liParagraph, color, font, xpos, line^.liBaseline, data^.ndInfo, li); end {Calculate} else if dopaint in [dopaint_Calculate] then begin if ((ndSelFirstChar<charnum) and (ndSelFirstPos=-1)) or (ndSelFirstChar=charnum) then begin {safety} ndSelFirstLine:=linenum; ndSelFirstPos:=xpos; end; if (ndSelLastChar<charnum) and (ndSelFirstPos=-1) then begin {safety} ndSelLastLine:=linenum; ndSelLastPos:=xpos; end else if (ndSelLastChar=charnum) then begin ndSelLastLine:=linenum; ndSelLastPos:=liLeftPos end end {GetChar} else if dopaint in [dopaint_GetChar] then with prm do begin if (nhppPoint.x<xpos) and (nhppCharacter=-1) then begin nhppCharLine:=linenum; nhppCharacter:=charnum; {safety} nhppCharRect.left:=xpos; nhppCharRect.right:=liLeftPos; end else if (prm.nhppPoint.x>=xpos) and (prm.nhppPoint.x<liLeftPos) then begin nhppCharLine:=linenum; nhppCharacter:=charnum; nhppCharRect.left:=xpos; nhppCharRect.right:=liLeftPos; end end; xpos:=liLeftPos; currentword:=0; nextspace:=0; NHFeedLine:=(liTopLine<tr.bottom) or (not (dopaint in [dopaint_Print,dopaint_Paint])); end; end; label Out; begin with data^ do with ndInfo do begin {Calc} if dopaint in [dopaint_Calculate] then begin ndRects:=NHCreateHotRect(ndRects); ndSelFirstPos:=-1; ndSelLastPos:=-1; end {GetChr} else if dopaint in [dopaint_GetChar] then with prm do begin nhppCharacter:=-1; end; inhilite:=false; xpos:=0; indexes:=ndIndexes; para:=0; NHInitFonts(data); ndError:=nderror_Ok; buffer:=NGAlloc(gmem_Moveable,1); bufferlen:=0; fonttable:=ndFontTable; colortable:=ndColorTable; autochartable:=ndAutoCharTable; p:=ndText; line:=ndLineInfo; linenum:=0; font :=0; color:=0; {first, we find the first displayed line!} if dopaint in [dopaint_Paint,dopaint_Print,dopaint_GetChar] then repeat if dopaint in [dopaint_Paint,dopaint_Print] then begin {Paint} if line^.liBottomLine>=tr.top then Break end {GetChar} else with prm do if (nhppPoint.y<=line^.liBottomLine) then begin nhppCharRect.top:=line^.liTopLine; nhppCharRect.bottom:=line^.liBottomLine; if nhppPoint.y<line^.liTopLine then goto Out; Break; end; repeat case p[0] of NHParaChar: begin Inc(para); line:=FIncPtr(line,SizeOf(line^)); Inc(linenum); p:=FIncPtr1(p); Break; end; NHLineBreakChar: begin line:=FIncPtr(line,SizeOf(line^)); Inc(linenum); p:=FIncPtr1(p); Break; end; NHNLChar: begin line:=FIncPtr(line,SizeOf(line^)); Inc(linenum); p:=FIncPtr1(p); Break; end; NHTabChar: begin line:=FIncPtr(line,SizeOf(line^)); Inc(linenum); end; NHFontChar: begin font:=fonttable^; fonttable:=FIncPtr(fonttable,SizeOf(fonttable^)); end; NHColorChar: begin color:=colortable^; colortable:=FIncPtr(colortable,SizeOf(colortable^)); end; NHHiliteChar: begin inhilite:=not inhilite; if inhilite=false then indexes:=FIncPtr(indexes,SizeOf(indexes^)) else begin inhilitefont:=HTHotSpotHandler(ndInfo.hiHotSpotFnc) (indexes^.hsIndex,hWindow,hthotspotfnc_GetFont,ndInfo); inhilitecolor:=HTHotSpotHandler(ndInfo.hiHotSpotFnc) (indexes^.hsIndex,hWindow,hthotspotfnc_GetColor,ndInfo); end end; NHAutoChar: begin autochartable:=FIncPtr(autochartable,SizeOf(autochartable^)); end; end; p:=FIncPtr1(p); until false; until para=ndParaTableSize; {now, we paint it!} if para<ndParaTableSize then begin charnum:=HPtrsDis(ndText,p); NHSelectFont; NHSelectColor; NHFeedLine(charnum); SetBkMode(dc,Transparent); SetTextAlign(dc,ta_Left or ta_BaseLine); repeat case p[0] of NHParaChar: begin llpos:=xpos; lrpos:=xpos; lchar:=HPtrsDis(ndText,p); lline:=linenum; {in case: if clicked right of the end of the line} if (dopaint in [dopaint_Calculate]) and inhilite then begin ndRects:=NHAddHotRect(ndRects,hotrect,indexes^.hsIndex,err); SetRect(hotrect,32767,32767,-32767,-32767); end; Inc(para); if para=ndParaTableSize then Break; line:=FIncPtr(line,SizeOf(line^)); Inc(linenum); if not NHFeedLine(lchar) then Break; p:=FIncPtr1(p); Continue; end; NHTabChar,NHNLChar,NHLineBreakChar: begin llpos:=xpos; lrpos:=xpos; lchar:=HPtrsDis(ndText,p); lline:=linenum; {in case: if clicked right of the end of the line} if (dopaint in [dopaint_Calculate]) and inhilite then begin ndRects:=NHAddHotRect(ndRects,hotrect,indexes^.hsIndex,err); SetRect(hotrect,32767,32767,-32767,-32767); end; line:=FIncPtr(line,SizeOf(line^)); Inc(linenum); if not NHFeedLine(lchar) then Break; p:=FIncPtr1(p); Continue; end; NHFrameChar: begin p:=FIncPtr1(p); Continue; end; NHSpaceChar: begin charnum:=HPtrsDis(ndText,p); {last space} p:=FIncPtr1(p); Continue; end; end; nextspace:=NHGetSpaceSize; {nextspace correction} if nextspace>0 then {Paint} if dopaint in [dopaint_Paint,dopaint_Print] then begin li.hliLPLeft:=line^.liLeftPos; li.hliLPTop:=line^.liTopLine; li.hliLPBottom:=line^.liBottomLine; NHCheckInSelection; with li do if hliSelected then hliSelected:=(hliSelStart<=xpos) and (hliSelEnd>=(xpos+nextspace)); HTTextHandler(data^.ndInfo.hiTextFnc)( Pointer(MakeLong(nextspace,0)), hWindow, httextfnc_SpaceOut, dc, line^.liParagraph, color, font, xpos, line^.liBaseline, data^.ndInfo, li); end {Calculate} else if dopaint in [dopaint_Calculate] then begin if ((ndSelFirstChar<charnum) and (ndSelFirstPos=-1)) or (ndSelFirstChar=charnum) then begin {safety} ndSelFirstLine:=linenum; ndSelFirstPos:=xpos; end; if (ndSelLastChar<charnum) and (ndSelFirstPos=-1) then begin {safety} ndSelLastLine:=linenum; ndSelLastPos:=xpos; end else if (ndSelLastChar=charnum) then begin ndSelLastLine:=linenum; ndSelLastPos:=xpos+nextspace end end {GetChar} else if dopaint in [dopaint_GetChar] then with prm do begin if (nhppPoint.x<xpos) and (nhppCharacter=-1) then begin nhppCharLine:=linenum; nhppCharacter:=charnum; {safety} nhppCharRect.left:=xpos; nhppCharRect.right:=xpos+nextspace; end else if (nhppPoint.x>=xpos) and (nhppPoint.x<(xpos+nextspace)) then begin nhppCharLine:=linenum; nhppCharacter:=charnum; nhppCharRect.left:=xpos; nhppCharRect.right:=xpos+nextspace; end end; xpos:=xpos+nextspace; if not NHPaintNextWord then Break; nextspace:= HTTextHandler(data^.ndInfo.hiTextFnc)( Nil, hWindow, httextfnc_GetSpaceExtent, dc, line^.liParagraph, 0, font, 0, 0, data^.ndInfo, li); Inc(currentword); if dopaint in [dopaint_GetChar] then begin if prm.nhppCharacter<>-1 then Break else if prm.nhppPoint.y<line^.liTopLine then with prm do begin nhppCharacter:=lchar; nhppCharLine:=lline; nhppCharRect.left:=llpos; nhppCharRect.right:=lrpos; Break end end; until false; end; Out: if dopaint in [dopaint_Calculate] then begin {have we calculated the positions correctly?} if (ndSelFirstPos=-1) or (ndSelLastPos=-1) then ndInSelection:=false; end; end; SelectObject(dc,GetStockObject(System_Font)); NGFree(Pointer(buffer)); NHDoneFonts(data); end; procedure NHPaint(hWindow:hWnd;dc:hDC;var ps:TPaintStruct;data:PNHData); var ob,b:hBrush; c:longint; tr:TRect; paratable:PNHParagraph; frametable:PNHFrame; para:longint; style:TNHStyle; irect,orect,frame,fr,cr:TRect; mdc,olddc:hDC; oldbitmap:hBitmap; xoff,yoff:integer; prm:TNHPaintParam; begin with data^ do begin GetClientRect(hWindow,cr); b:=CreateSolidBrush(ndInfo.hiBgrndColor); tr:=ps.rcPaint; olddc:=dc; mdc:=CreateCompatibleDCRect(dc,ps.rcPaint,oldbitmap); if mdc<>0 then begin dc:=mdc; xoff:=-tr.left; yoff:=-tr.top; end else begin xoff:=0; yoff:=0; end; ExtSetViewportOrg(olddc,0,-ndYPos); DPToLP(olddc,tr,2); ExtSetViewportOrg(dc,xoff,yoff-ndYPos); paratable:=ndParaTable; for para:=0 to ndParaTableSize-1 do begin with paratable^ do if (hpPosition<=tr.bottom) and (hpEndPosition>=tr.top) then begin UnrealizeObject(b); ob:=SelectObject(dc,b); NHGetStyle(hpStyle,style,data); frame.left:=-ndXPos; frame.right:=ndWidth; frame.top:=hpPosition; frame.bottom:=hpEndPosition; orect:=frame; if style.hsParaFormat<>hsparaformat_Continuous then orect.right:=orect.left+ndWidth; Inc(orect.left,ndInfo.hiLeftSpace); if style.hsParaFormat<>hsparaformat_Continuous then Dec(orect.right,ndInfo.hiRightSpace); irect:=orect; Inc(irect.left,style.hsLeftSpace); Inc(irect.top,style.hsTopSpace); Dec(irect.bottom,style.hsBottomSpace); if style.hsParaFormat<>hsparaformat_Continuous then Dec(irect.right,style.hsRightSpace); HTBrushHandler(ndInfo.hiBrushFnc)( hWindow, dc, para, hpBkBrush, irect, orect, frame, tr, ndInfo); SelectObject(dc,ob); if BGet(style.hsParaStyle,hsparastyle_TopLine) then HTLineHandler(ndInfo.hiLineFnc)( hWindow, htlinefnc_TopLine, dc, para, style.hsTopLine, irect, orect, frame, tr, ndInfo); if BGet(style.hsParaStyle,hsparastyle_BottomLine) then HTLineHandler(ndInfo.hiLineFnc)( hWindow, htlinefnc_BottomLine, dc, para, style.hsBottomLine, irect, orect, frame, tr, ndInfo); end; paratable:=FIncPtr(paratable,SizeOf(paratable^)); end; if ndYSize<tr.Bottom then begin UnrealizeObject(b); ob:=SelectObject(dc,b); DPToLP(olddc,cr,2); frame.left:=-ndXPos; frame.right:=ndWidth; frame.top:=ndYSize; frame.bottom:=cr.bottom; HTBrushHandler(ndInfo.hiBrushFnc)( hWindow, dc, -1, -1, frame, frame, frame, tr, ndInfo); SelectObject(dc,ob); end; tr:=ps.rcPaint; ExtSetViewportOrg(olddc,-ndXPos+ndInfo.hiLeftSpace,-ndYPos); DPToLP(olddc,tr,2); ExtSetViewportOrg(dc,xoff-ndXPos+ndInfo.hiLeftSpace,yoff-ndYPos); frametable:=ndFrameTable; for c:=0 to ndFrameTableSize-1 do begin with frametable^ do if not BGet(hfStyle,hfstyle_ChildWindow) then if not BGet(hfStyle,hfstyle_Overlaying) then begin HTFrameHandler(ndInfo.hiFrameFnc)( frametable, hWindow, htframefnc_Paint, dc, 0, 0, tr, ndInfo); end; frametable:=FIncPtr(frametable,SizeOf(frametable^)); end; NHPaintText(hWindow,dc,tr,data,dopaint_Paint,prm); frametable:=ndFrameTable; for c:=0 to ndFrameTableSize-1 do begin with frametable^ do if not BGet(hfStyle,hfstyle_ChildWindow) then if BGet(hfStyle,hfstyle_Overlaying) then begin HTFrameHandler(ndInfo.hiFrameFnc)( frametable, hWindow, htframefnc_Paint, dc, 0, 0, tr, ndInfo); end; frametable:=FIncPtr(frametable,SizeOf(frametable^)); end; DeleteObject(b); if mdc<>0 then begin SetViewportOrg(mdc,0,0); SetViewportOrg(olddc,0,0); with ps.rcPaint do BitBlt(olddc,left,top,right-left,bottom-top,mdc,0,0,SrcCopy); DeleteObject(SelectObject(mdc,oldbitmap)); DeleteDC(mdc); end; end; end; function NHCreateSelRegion(data:PNHData;sfline,sfpos,slline,slpos:longint;wid:longint):hRgn; var rgn1,rgn2:hRgn; line:PNHLineInfo; top1,bottom1,top2,bottom2,base1,base2:longint; begin with data^ do begin line:=FIncPtr(ndLineInfo,sfline*SizeOf(line^)); if sfline=slline then begin rgn1:=CreateRectRgn(sfpos,line^.liTopLine,slpos,line^.liBottomLine) end else begin top1:=line^.liTopLine; bottom1:=line^.liBottomLine; base1:=line^.liBaseLine; line:=FIncPtr(ndLineInfo,slline*SizeOf(line^)); top2:=line^.liTopLine; bottom2:=line^.liBottomLine; base2:=line^.liBaseLine; if (base2=base1) then {fractions of the same text line} rgn1:=CreateRectRgn(sfpos,top1,slpos,bottom2) else begin rgn1:=CreateRectRgn(sfpos,top1,wid,bottom1); rgn2:=CreateRectRgn(0,bottom1,wid,top2); CombineRgn(rgn1,rgn1,rgn2,rgn_Or); SetRectRgn(rgn2,0,top2,slpos,bottom2); CombineRgn(rgn1,rgn1,rgn2,rgn_Or); DeleteObject(rgn2); end end; end; NHCreateSelRegion:=rgn1; end; function NHUpdateSelection(data:PNHData;sfline,sfpos,slline,slpos:longint;wid:longint;insel:bool):hRGN; var rgn1,rgn2:hRgn; begin rgn1:=0; with data^ do if ndInSelection then begin rgn1:=NHCreateSelRegion( data, ndSelFirstLine, ndSelFirstPos, ndSelLastLine, ndSelLastPos, wid); if insel then begin rgn2:=NHCreateSelRegion( data, sfline, sfpos, slline, slpos, wid); CombineRgn(rgn1,rgn1,rgn2,rgn_XOr); DeleteObject(rgn2); end; OffsetRgn(rgn1,-ndXPos+ndInfo.hiLeftSpace,-ndYPos); end else if insel then begin rgn1:=NHCreateSelRegion( data, sfline, sfpos, slline, slpos, wid); OffsetRgn(rgn1,-ndXPos+ndInfo.hiLeftSpace,-ndYPos); end; NHUpdateSelection:=rgn1; end; function NHyperWindowProc(hWindow:hWnd;msg:word;wParam:word;lParam:longint):longint;export; var result:longint; p:PNHData; b:hBrush; ps:TPaintStruct; dc:hDC; tr:TRect; fonts,hilite:longint; oldpos:integer; crsr:bool; index:longint; tp:TPoint; nct:TNHCompiledText; dummy:TRect; is:bool; hotcursor:longint; prr:PANHHotRect; rgn:hRgn; function DoIt:bool; begin DoIt:= (p<>Nil) and (p^.ndInfo.hiFonts<>Nil) and (p^.ndInfo.hiColors<>Nil) and (p^.ndInfo.hiStyles<>Nil) and (p^.ndText<>Nil) and (p^.ndParaTable<>Nil) and (p^.ndError=nderror_Ok) end; function GetCharacter(tp:TPoint;var lne:longint;var tr:TSRect):longint; var dummy:TRect; dc:hDC; prm:TNHPaintParam; begin dc:=GetDC(0); with prm do begin nhppPoint.x:=tp.x; nhppPoint.y:=tp.y; end; NHPaintText( hWindow, dc, dummy, p, dopaint_GetChar, prm); ReleaseDC(0,dc); lne :=prm.nhppCharLine; tr :=prm.nhppCharRect; GetCharacter:=prm.nhppCharacter; end; procedure CutText(w,h:integer); var dc:hDC; oldsize:integer; ypos,lines,xsize:integer; mip,map:integer; frametable:PNHFrame; c:longint; tr,dummy:TRect; prm:TNHPaintParam; begin if p^.ndInfo.hiVScrollerFnc=Nil then begin GetScrollRange(hWindow,sb_Vert,mip,map); if (mip=map) and (mip=0) then Dec(w,GetSystemMetrics(sm_CXVScroll)+1); end; if p^.ndInfo.hiHScrollerFnc=Nil then begin GetScrollRange(hWindow,sb_Horz,mip,map); if (mip=map) and (mip=0) then Dec(h,GetSystemMetrics(sm_CYVScroll)+1); end; dc:=GetDC(0); with p^ do begin ndWidth:=w; w:=w-p^.ndInfo.hiRightSpace-p^.ndInfo.hiLeftSpace; oldsize:=ndYSize; NHPrepareText(ndText); if w<=0 then w:=1; NHCutText( hWindow, dc, w, ypos, lines, xsize, p); NHPaintText( hWindow, dc, dummy, p, dopaint_Calculate, prm); ndYSize:=ypos; if lines=0 then ndYStep:=1 else ndYStep:=ypos div lines; if oldsize=0 then ndYPos:=0 else ndYPos:=QuadMulDiv(ndYPos,ndYSize,oldsize); end; ReleaseDC(0,dc); with p^ do if ndYSize<=h then begin if (ndInfo.hiVScrollerFnc=Nil) then begin SetScrollRange(hWindow,sb_Vert,0,0,false); SetScrollPos(hWindow,sb_Vert,0,true); Inc(ndWidth,GetSystemMetrics(sm_CXVScroll)+1) end else begin HTScrollerHandler(ndInfo.hiVScrollerFnc)(hWindow,htscrollfnc_SetScrollRange,0,0,ndInfo); HTScrollerHandler(ndInfo.hiVScrollerFnc)(hWindow,htscrollfnc_SetScrollPos,0,0,ndInfo); end; ndYPos:=0; ndYEnd:=ndYSize; ndVScroll:=false; end else begin ndYEnd:=ndYSize-(h div 2); if (ndInfo.hiVScrollerFnc=Nil) then begin SetScrollRange(hWindow,sb_Vert,0,ndYEnd,false); SetScrollPos(hWindow,sb_Vert,ndYPos,true); end else begin HTScrollerHandler(ndInfo.hiVScrollerFnc)(hWindow,htscrollfnc_SetScrollRange,ndYEnd,0,ndInfo); HTScrollerHandler(ndInfo.hiVScrollerFnc)(hWindow,htscrollfnc_SetScrollPos,ndYPos,0,ndInfo); end; ndVScroll:=true; end; p^.ndXSize:=xsize; xsize:=xsize-w; with p^ do if xsize>0 then begin ndXStep:=w div 10; if ndXStep=0 then ndXStep:=1; ndXEnd:=xsize; ndXPos:=0; if (ndInfo.hiHScrollerFnc=Nil) then begin SetScrollRange(hWindow,sb_Horz,0,ndXEnd,false); SetScrollPos(hWindow,sb_Horz,ndXPos,true); end else begin HTScrollerHandler(ndInfo.hiHScrollerFnc)(hWindow,htscrollfnc_SetScrollRange,ndXEnd,0,ndInfo); HTScrollerHandler(ndInfo.hiHScrollerFnc)(hWindow,htscrollfnc_SetScrollPos,ndXPos,0,ndInfo); end; ndHScroll:=true; end else begin ndXStep:=0; ndXEnd:=0; ndXPos:=0; if (ndInfo.hiHScrollerFnc=Nil) then begin SetScrollRange(hWindow,sb_Horz,0,0,false); SetScrollPos(hWindow,sb_Horz,0,true); end else begin HTScrollerHandler(ndInfo.hiHScrollerFnc)(hWindow,htscrollfnc_SetScrollRange,0,0,ndInfo); HTScrollerHandler(ndInfo.hiHScrollerFnc)(hWindow,htscrollfnc_SetScrollPos,0,0,ndInfo); end; ndHScroll:=false; end; with p^ do begin frametable:=ndFrameTable; for c:=0 to ndFrameTableSize-1 do begin with frametable^ do if BGet(hfStyle,hfstyle_ChildWindow) then begin tr:=hfRect; OffsetRect(tr,-ndXPos+ndInfo.hiLeftSpace,-ndYPos); HTFrameHandler(ndInfo.hiFrameFnc)( frametable, hWindow, htframefnc_ResizeChild, dc, 0, 0, tr, ndInfo); end; frametable:=FIncPtr(frametable,SizeOf(frametable^)); end; end; end; procedure ReleaseMem; begin with p^ do begin if ndRects<>Nil then NGFree(ndRects); if ndText<>Nil then NGFree(ndText); if ndFontTable<>Nil then NGFree(Pointer(ndFontTable)); if ndIndexes<>Nil then NGFree(Pointer(ndIndexes)); if ndLineInfo<>Nil then NGFree(Pointer(ndLineInfo)); if ndParaTable<>Nil then NGFree(Pointer(ndParaTable)); if ndAutoCharTable<>Nil then NGFree(Pointer(ndAutoCharTable)); if ndFrameTable<>Nil then begin NHReleaseAllWindows(hWindow,p); NGFree(Pointer(ndFrameTable)); end; if ndColorTable<>Nil then NGFree(Pointer(ndColorTable)); end end; procedure SelectPoint(tp:TPoint;extend:bool); var selchar:longint; selrect:TSRect; selline:longint; sfline,sfpos,slline,slpos,sfchar,slchar:longint; rgn:hRgn; begin selchar:=GetCharacter(tp,selline,selrect); if selchar<>-1 then with p^ do begin if extend then begin if ndSelPositive then if (selline<ndSelFirstLine) or ((selline=ndSelFirstLine) and (selrect.left<ndSelFirstPos)) then begin sfchar:=selchar; sfline:=selline; sfpos:=selrect.left; slchar:=ndSelFirstChar-1; slline:=ndSelFirstLine; slpos:=ndSelFirstPos; ndSelPositive:=false; end else begin sfchar:=ndSelFirstChar; sfline:=ndSelFirstLine; sfpos:=ndSelFirstPos; slchar:=selchar; slline:=selline; slpos:=selrect.right; end else if (selline>ndSelLastLine) or ((selline=ndSelLastLine) and (selrect.left>ndSelLastPos)) then begin sfchar:=ndSelLastChar+1; sfline:=ndSelLastLine; sfpos:=ndSelLastPos; slchar:=selchar; slline:=selline; slpos:=selrect.right; ndSelPositive:=true; end else begin sfchar:=selchar; sfline:=selline; sfpos:=selrect.left; slchar:=ndSelLastChar; slline:=ndSelLastLine; slpos:=ndSelLastPos; end; rgn:=NHUpdateSelection( p, sfline, sfpos, slline, slpos, MaxLineLength div 2, true); ndSelFirstChar :=sfchar; ndSelFirstLine :=sfline; ndSelFirstPos :=sfpos; ndSelLastChar :=slchar; ndSelLastLine :=slline; ndSelLastPos :=slpos; if rgn<>0 then begin InvalidateRgn(hWindow,rgn,false); DeleteObject(rgn); end; end else begin rgn:=NHUpdateSelection( p, selline, selrect.left, selline, selrect.right, MaxLineLength div 2, true); ndSelFirstChar:=selchar; ndSelFirstLine:=selline; ndSelFirstPos:=selrect.left; ndSelLastChar:=selchar; ndSelLastLine:=selline; ndSelLastPos:=selrect.right; ndInSelection:=true; if rgn<>0 then begin InvalidateRgn(hWindow,rgn,false); DeleteObject(rgn); end; end; SRectToRect(selrect,p^.ndSelRect); end end; procedure CorrectClientCursor(var tp:TPoint); begin with p^ do begin Inc(tp.y,p^.ndYPos); Inc(tp.x,p^.ndXPos-ndInfo.hiLeftSpace); end; end; procedure HGetCursorPos(var tp:TPoint); begin GetCursorPos(tp); ScreenToClient(hWindow,tp); CorrectClientCursor(tp); end; function GetSelection(pchr:PChar;mlen:longint):longint; var src:PChar; len:longint; pos:longint; od:array[0..1] of char; begin with p^ do if ndInSelection then begin pos:=0; len:=ndSelLastChar-ndSelFirstChar+1; src:=FIncPtr(ndText,ndSelFirstChar); while ((pchr=Nil) or ((pos<mlen) or (mlen=0))) and (len>0) do begin case src[0] of NHFontChar, NHHiliteChar, NHColorChar, NHAutoChar, NHFrameChar:; NHNLChar, NHLineBreakChar, NHSpaceChar, NHHardSpaceChar: begin if pchr<>Nil then begin pchr[0]:=' '; pchr:=FIncPtr1(pchr); end; Inc(pos) end; NHParaChar: begin if pchr<>Nil then begin pchr[0]:=#13; pchr:=FIncPtr1(pchr); pchr[0]:=#10; pchr:=FIncPtr1(pchr); end; Inc(pos,2) end; NHTabChar: begin if pchr<>Nil then begin pchr[0]:=#9; pchr:=FIncPtr1(pchr); end; Inc(pos); end; else begin if pchr<>Nil then begin pchr[0]:=src[0]; pchr:=FIncPtr1(pchr); end; Inc(pos); end end; Dec(len); src:=FIncPtr1(src); end; if pchr<>Nil then pchr[0]:=#0; GetSelection:=pos; end else GetSelection:=-1; end; begin result:=0; if msg<>wm_NCCreate then p:=NSRCtlMemoryLock(hWindow); case msg of wm_NCCreate: begin result:=NSRCtlDefWindowProc(hWindow,msg,wParam,lParam); NSRCtlInitWindow(hWindow,0,0,0); NSRCtlMemoryInit(hWindow,SizeOf(TNHData)); p:=NSRCtlMemoryLock(hWindow); with p^ do begin with ndInfo do begin hiBgrndColor:=RGB(255,255,255); hiFonts:=Nil; hiColors:=Nil; hiStyles:=Nil; hiNumFonts:=0; end; ndRects:=Nil; ndText:=Nil; ndFontTable:=Nil; ndColorTable:=Nil; ndAutoCharTable:=Nil; ndFrameTable:=Nil; ndParaTable:=Nil; ndIndexes:=Nil; ndLineInfo:=Nil; ndYPos:=0; ndXPos:=0; ndError:=nderror_Ok; ndFreeze:=false; ndInSelection:=false; ndSelFirstChar:=18; ndSelLastChar:=300; end; end; wm_NCDestroy: begin ReleaseMem; NSRCtlMemoryUnlock(hWindow); NSRCtlMemoryDone(hWindow); end; wm_Paint: if DoIt then with p^ do begin dc:=BeginPaint(hWindow,ps); GetClientRect(hWindow,tr); if ndLineInfo<>Nil then begin NHPaint( hWindow, dc, ps, p); end; EndPaint(hWindow,ps); end else begin BeginPaint(hWindow,ps); EndPaint(hWindow,ps); end; wm_Size: begin if DoIt and not p^.ndFreeze then begin p^.ndFreeze:=true; CutText(integer(LoWord(lParam)),integer(HiWord(lParam))); { InvalidateRect(hWindow,Nil,false); UpdateWindow(hWindow);} p^.ndFreeze:=false; end; end; wm_GetDlgCode: begin result:=dlgc_Static end; wm_SetText: begin if (p<>Nil) and (p^.ndInfo.hiFonts<>Nil) then begin p^.ndError:=NSRHyperCompileText(PChar(lParam),nct); if p^.ndError=nderror_Ok then SendMessage(hWindow,htm_SetCompiledText,0,longint(@nct)); end; result:=NSRCtlDefWindowProc(hWindow,msg,wParam,lParam); end; htm_SetCompiledText: begin if (p<>Nil) and (p^.ndInfo.hiFonts<>Nil) then with p^,PNHCompiledText(lparam)^ do begin ReleaseMem; ndError:=nderror_Ok; ndIndexes:=nctIndexesTable; ndFontTable:=nctFontTable; ndParaTable:=nctParaTable; ndColorTable:=nctColorTable; ndAutoCharTable:=nctAutoCharTable; ndFrameTable:=nctFrameTable; ndFontTableSize:=nctFontTableSize; ndParaTableSize:=nctParaTableSize; ndColorTableSize:=nctColorTableSize; ndAutoCharTableSize:=nctAutoCharTableSize; ndFrameTableSize:=nctFrameTableSize; ndText:=nctText; NHGetAllData(hWindow,p); ndYPos:=0; ndXPos:=0; if DoIt then begin GetClientRect(hWindow,tr); CutText(tr.right-tr.left,tr.bottom-tr.top); InvalidateRect(hWindow,Nil,false); end; end; result:=nderror_Ok; end; wm_LButtonDown: begin if DoIt then begin SetCapture(hWindow); HGetCursorPos(tp); if GWIsStyle(hWindow,hs_NoSelection) then p^.ndInSelection:=false else with p^ do begin ndSelPositive:=true; ndSelMouseIn:=true; ndSelExtended:=IsCurShift; if ndInSelection and (not ndSelExtended) then begin rgn:=NHUpdateSelection( p, 0, 0, 0, 0, MaxLineLength div 2, false); ndInSelection:=false; if rgn<>0 then begin InvalidateRgn(hWindow,rgn,false); DeleteObject(rgn); end; end; ndSelStartPoint:=tp; end; end; end; wm_Timer: begin if DoIt then with p^ do if (not ndSelMouseIn) and (GetCapture=hWindow) then begin GetCursorPos(tp); GetClientRect(hWindow,tr); ScreenToClient(hWindow,tp); {decide for direction - based upon the position of the cursor relative to the screen} with tr do begin if tp.x>right then begin SendMessage(hWindow,wm_HScroll,sb_linedown,0); tp.x:=tr.right-1 end else if tp.x<left then begin SendMessage(hWindow,wm_HScroll,sb_lineup,0); tp.x:=0; end; if tp.y>bottom then begin SendMessage(hWindow,wm_VScroll,sb_linedown,0); tp.y:=tr.bottom-1 end else if tp.y<top then begin SendMessage(hWindow,wm_VScroll,sb_lineup,0); tp.y:=0 end; if not GWIsStyle(hWindow,hs_NoSelection) then begin CorrectClientCursor(tp); SelectPoint(tp,true); end; end end; end; wm_MouseMove: begin if GetCapture=hWindow then if DoIt then with p^ do begin GetClientRect(hWindow,tr); GetCursorPos(tp); ScreenToClient(hWindow,tp); {if mouse went out of the screen, then init timer; if it came back, kill} {the timer. If the state remains the same, leave everything} if ndSelMouseIn then begin if PtInRect(tr,tp) then is:=true else begin ndSelMouseIn:=false; NSRCtrlInitTimer(hWindow); is:=false end end else begin if PtInRect(tr,tp) then begin is:=true; NSRCtrlKillTimer(hWindow); ndSelMouseIn:=true end else is:=false; end; if is then begin HGetCursorPos(tp); if not GWIsStyle(hWindow,hs_NoSelection) then if ndInSelection then begin if not PtInRect(ndSelRect,tp) then SelectPoint(tp,true); end else begin SelectPoint(ndSelStartPoint,ndSelExtended); if not ndInSelection then ndSelStartPoint:=tp; end end end end; wm_LButtonUp: begin if DoIt then begin ReleaseCapture; HGetCursorPos(tp); with p^ do if not ndInSelection then begin index:=NHFindHotRect(p^.ndRects,tp); if index<>-1 then PostMessage(p^.ndInfo.hiReceiver,wm_HyperLink,0,index) end end; if not crsr then SetCursor(LoadCursor(0,idc_Arrow)); end; wm_SetCursor: begin crsr:=false; if (LoWord(lParam)=htClient) and DoIt then with p^ do begin HGetCursorPos(tp); if ndInSelection then index:=-1 else index:=NHFindHotRect(ndRects,tp); if index<>-1 then begin crsr:=true; hotcursor:=HTHotSpotHandler(ndInfo.hiHotSpotFnc)( PNHHotSpot(FIncPtr(ndIndexes,index*SizeOf(TNHHotSpot)))^.hsIndex, hWindow, hthotspotfnc_GetCursor, ndInfo); if hotcursor=-1 then SetCursor(p^.ndInfo.hiCursorLink) else SetCursor(hotcursor) end else begin crsr:=true; SetCursor(p^.ndInfo.hiCursor) end end; if not crsr then SetCursor(LoadCursor(0,idc_Arrow)); end; wm_HScroll: if DoIt then with p^ do if ndHScroll then begin oldpos:=ndXPos; GetClientRect(hWindow,tr); case wParam of sb_Top: ndXPos:=0; sb_Bottom: ndXPos:=ndXEnd; sb_PageUp: Dec(ndXPos,tr.right); sb_PageDown: Inc(ndXPos,tr.right); sb_LineUp: Dec(ndXPos,ndXStep); sb_LineDown: Inc(ndXPos,ndXStep); sb_ThumbPosition: ndXPos:=integer(LoWord(lParam)); end; if ndXPos<0 then ndXPos:=0; if ndXPos>ndXEnd then ndXPos:=ndXEnd; if ndInfo.hiHScrollerFnc=Nil then SetScrollPos(hWindow,sb_Horz,ndXPos,true) else HTScrollerHandler(ndInfo.hiHScrollerFnc)(hWindow,htscrollfnc_SetScrollPos,ndXPos,0,ndInfo); ScrollWindow(hWindow,oldpos-ndXPos,0,Nil,Nil); end; wm_VScroll: if DoIt then with p^ do if ndVScroll then begin oldpos:=ndYPos; GetClientRect(hWindow,tr); case wParam of sb_Top: ndYPos:=0; sb_Bottom: ndYPos:=ndYEnd; sb_PageUp: Dec(ndYPos,tr.bottom); sb_PageDown: Inc(ndYPos,tr.bottom); sb_LineUp: Dec(ndYPos,ndYStep); sb_LineDown: Inc(ndYPos,ndYStep); sb_ThumbPosition: ndYPos:=integer(LoWord(lParam)); end; if ndYPos<0 then ndYPos:=0; if ndYPos>ndYEnd then ndYPos:=ndYEnd; if ndInfo.hiVScrollerFnc=Nil then SetScrollPos(hWindow,sb_Vert,ndYPos,true) else HTScrollerHandler(ndInfo.hiVScrollerFnc)(hWindow,htscrollfnc_SetScrollPos,ndYPos,0,ndInfo); ScrollWindow(hWindow,0,oldpos-ndYPos,Nil,Nil); end; wm_NCPaint: begin result:=DefWindowProc(hWindow,msg,wParam,lParam); end; wm_NCCalcSize: begin result:=DefWindowProc(hWindow,msg,wParam,lParam); end; htm_GetSelection: begin result:=GetSelection(Pointer(lParam),integer(wParam)); end; htm_SetParaPos: begin with p^ do with PNHParagraph(FIncPtr(ndParaTable,lParam*SizeOf(TNHParagraph)))^ do begin if ndInfo.hiVScrollerFnc=Nil then SetScrollPos(hWindow,sb_Vert,hpPosition,true) else HTScrollerHandler(ndInfo.hiVScrollerFnc)(hWindow,htscrollfnc_SetScrollPos,hpPosition,0,ndInfo); ScrollWindow(hWindow,0,ndYPos-hpPosition,Nil,Nil); end; end; else result:=NSRCtlDefWindowProc(hWindow,msg,wParam,lParam); end; if msg<>wm_NCDestroy then NSRCtlMemoryUnlock(hWindow); NHyperWindowProc:=result; end; procedure NSRHyperSetInfo(h:hWnd;p:PNHyperInfo); var inf:PNHData; begin inf:=NSRCtlMemoryLock(h); if inf<>Nil then inf^.ndInfo:=p^; NSRCtlMemoryUnlock(h); end; const RegCount:integer=0; procedure NSRHyperTextInit; begin if RegCount=0 then begin NSRCtlCreateClass( hInstance, NSRHyperTextClassName, cs_DblClks or cs_GlobalClass or cs_HRedraw or cs_VRedraw, 0, 0, LoadCursor(0,PChar(idc_arrow)), @NHyperWindowProc); end; Inc(RegCount); end; function NSRHyperCompileText; var ndError:integer; len:longint; begin with nct do begin FillChar(nct,SizeOf(nct),#0); ndError:=nderror_Ok; NHCountHiliteFontParaColorCharFrames( txt, len, nctIndexesTableSize, nctFontTableSize, nctParaTableSize, nctColorTableSize, nctAutoCharTableSize, nctFrameTableSize ); nctFontTableMSize:=nctFontTableSize*SizeOf(byte); nctParaTableMSize:=nctParaTableSize*SizeOf(TNHParagraph); nctColorTableMSize:=nctColorTableSize*SizeOf(byte); nctAutoCharTableMSize:=nctAutoCharTableSize*SizeOf(TNHAutoChar); nctFrameTableMSize:=nctFrameTableSize*SizeOf(TNHFrame); nctIndexesTableMSize:=nctIndexesTableSize*SizeOf(TNHHotSpot); if nctFontTableSize<>0 then begin nctFontTable:=NGAlloc(gmem_Moveable,nctFontTableMSize); if (nctFontTable=Nil) then ndError:=nderror_OutOfMem; end; if nctParaTableSize<>0 then begin nctParaTable:=NGAlloc(gmem_Moveable,nctParaTableMSize); if (nctParaTable=Nil) then ndError:=nderror_OutOfMem; end; if nctColorTableSize<>0 then begin nctColorTable:=NGAlloc(gmem_Moveable,nctColorTableMSize); if (nctColorTable=Nil) then ndError:=nderror_OutOfMem; end; if nctAutoCharTableSize<>0 then begin nctAutoCharTable:=NGAlloc(gmem_Moveable,nctAutoCharTableMSize); if (nctAutoCharTable=Nil) then ndError:=nderror_OutOfMem; end; if nctFrameTableSize<>0 then begin nctFrameTable:=NGAlloc(gmem_Moveable,nctFrameTableMSize); if (nctFrameTable=Nil) then ndError:=nderror_OutOfMem; end; if nctIndexesTableSize<>0 then begin nctIndexesTable:=NGAlloc(gmem_Moveable,nctIndexesTableMSize); if (nctIndexesTable=Nil) then ndError:=nderror_OutOfMem end; if (ndError=nderror_Ok) then begin nctText:=NHCompile( txt, len, nctTextMSize, nctIndexesTable, nctFontTable, nctParaTable, nctColorTable, nctAutoCharTable, nctFrameTable, nctParaTableSize); if nctText=Nil then ndError:=nderror_OutOfMem; end; if ndError<>nderror_Ok then begin if nctIndexesTable<>Nil then NGFree(Pointer(nctIndexesTable)); if nctFontTable<>Nil then NGFree(Pointer(nctFontTable)); if nctParaTable<>Nil then NGFree(Pointer(nctParaTable)); if nctColorTable<>Nil then NGFree(Pointer(nctColorTable)); if nctAutoCharTable<>Nil then NGFree(Pointer(nctAutoCharTable)); if nctFrameTable<>Nil then NGFree(Pointer(nctFrameTable)); end; NSRHyperCompileText:=ndError; end; end; procedure NSRHyperTextDone; begin if RegCount=1 then begin UnregisterClass(NSRHyperTextClassName,hInstance); end; Dec(RegCount) end; end.