XSharpPublic icon indicating copy to clipboard operation
XSharpPublic copied to clipboard

ReportPro - Tabs

Open ecosSystem opened this issue 2 months ago • 1 comments

If you print a memo-field with the following content (chr(9) between the blocks):

1234 5678 abcde 1234 5678 abcde

RP prints 5678 abcde too high:

Image

This happens with normal text and with RTF-text and worked fine in the VO-Version. This bug is caused by the function rpTabbedTextOut in Drawtext.prg Please replace the line MoveToEx(sDrawText:hDC,nX,sDrawText:nY-sDrawText:nDescent,NULL_PTR) with MoveToEx(sDrawText:hDC,nX,sDrawText:nY,NULL_PTR) This fixes the behaviour.

A second problem concerns only RTF-text. If the text after the first tab is marked as bold, RP goes completely nuts:

Image

I did not find a solution for this yet, this didn’t work in VO either. If you find a solution please let me know. I will also try to figure it out when I find some time.

ecosSystem avatar Oct 31 '25 07:10 ecosSystem

This should fix both problems:

STATIC FUNCTION rpTabbedTextOut(sDrawText AS rpDrawTextStruct,nLineStart AS LONGINT,nLineStop AS LONGINT) AS VOID
// this is a simple replacement for the API Tabbedtextout() since it doesn't work correctly...
// (there is a bug with mapping modes and tabs)
// this replacement doesn't do everything the API function does but, does solve our problems

// sDrawText	- DrawText structure
// nLineStart	- the starting character of this line (in the buffer)
// nLineStop	- the ending character of this line (in the buffer)

LOCAL nDefTabSize,nPrintChars,nX,nTab,nTabStop	AS LONGINT
LOCAL ptrText,ptrStart 									AS BYTE PTR
LOCAL nTextExt												AS DWORD

IF sDrawText:sParaProp:nTabs > 0					// default size is the width of the first tab
	nDefTabSize	:= sDrawText:aTabs[1]			// if tabs are sent in...
ELSE
	nDefTabSize	:= sDrawText:nAvgCharWid*8		// initialize the avg tab width
ENDIF
IF nDefTabSize = 0									// make sure we have a def size
	nDefTabSize	:= 48
ENDIF

ptrText		:= sDrawText:ptrText+nLineStart-1
ptrStart		:= ptrText
nPrintChars	:= 1
nX				:= sDrawText:nX

DO WHILE nLineStart <= nLineStop			// skip through the buffer
	IF DWORD(BYTE(ptrText)) = 9			// if this is a tab character
		IF nPrintChars > 1
			IF sDrawText:lClipText
				ExtTextOut(sDrawText:hDC,0,0,ETO_CLIPPED,(PTR)@sDrawText:nLeft,PSZ(_CAST,ptrStart),nPrintChars-1,NULL_PTR)
			ELSE
				ExtTextOut(sDrawText:hDC,0,0,0,NULL_PTR,PSZ(_CAST,ptrStart),nPrintChars-1,NULL_PTR)
			ENDIF
		ENDIF
		nTextExt		:= GetTabbedTextExtent(sDrawText:hPrinterDC,PSZ(_CAST,ptrStart),nPrintChars-1,0,NULL_PTR)
		nX				+= LONGINT(LoWord(nTextExt))
		
		ptrStart		:= ptrText+1				 	// setup pointers to the next char
		nPrintChars	:= 0
		
		IF sDrawText:sParaProp:nTabs < 2			// use the default tab size
			nTabStop := sDrawText:nLeft+nDefTabSize
			DO WHILE nTabStop <= nX
				nTabStop += nDefTabSize
			ENDDO
			nX := nTabStop
		ELSE										// variable position tabs
			FOR nTab := 1 UPTO sDrawText:sParaProp:nTabs
				nTabStop	:= sDrawText:aTabs[nTab]+sDrawText:nLeft
				IF nTabStop > nX
					nX := nTabStop
					EXIT
				ENDIF
			NEXT
		ENDIF
		
		// [KW---]
		// MoveToEx(sDrawText:hDC,nX,sDrawText:nY-sDrawText:nDescent,NULL_PTR)
		MoveToEx(sDrawText:hDC,nX,sDrawText:nY,NULL_PTR)
		// [---KW]
		
	ENDIF
	++ptrText							 			// setup pointers to the next char
	nPrintChars	+=1
	nLineStart	+=1
	
ENDDO

IF nPrintChars>1
	IF sDrawText:lClipText
		ExtTextOut(sDrawText:hDC,0,0,ETO_CLIPPED,(PTR)@sDrawText:nLeft,PSZ(_CAST,ptrStart),nPrintChars-1,NULL_PTR)
	ELSE
		ExtTextOut(sDrawText:hDC,0,0,0,NULL_PTR,PSZ(_CAST,ptrStart),nPrintChars-1,NULL_PTR)
	ENDIF
ENDIF

// [KW---]
sDrawText:NX := nX
// [---KW]

RETURN

ecosSystem avatar Oct 31 '25 10:10 ecosSystem