Page 1 of 1

Box Drawing Characters

Posted: Sun Nov 29, 2020 12:24 am
by JeJe
Code to draw simple boxes with box characters round non-proportional font text such as used in the IDE or in a plain text document.

Simple test creates a Writer document with some boxed text based on an array of strings. Put in a module and run test 1

Code: Select all

'     ╔══════════════════╗
'     ║This is an example║
'     ║  of box drawing. ║
'     ╚══════════════════╝

sub test1
	oDoc = Stardesktop.loadComponentFromURL("private:factory/swriter", "_blank", 0,Array())
	wait 200
	odoc.currentcontroller.componentwindow.setfocus
	'font needs to be non proportional and support then unicode box characters.
	'not "Courier New" is a Windows font
	oDoc.currentcontroller.viewcursor.charfontname ="Courier New" 
	sarray=array("This is an example","  of box drawing. ") 
	'boxchars = "┌─┐││└─┘"
	boxchars ="╔═╗║║╚═╝"
	'boxchars ="░░░░░░░░"
	'boxchars ="▓▓▓▓▓▓▓▓"
	'boxchars ="████████"
	'boxchars ="$$$$$$$$"
	'boxchars ="▓▓▓▓▓▓▓▓"
	'boxchars ="@@@@@@@@"
	boxRoundStringArray(odoc,sarray,boxchars ,"'     ")
end sub


sub  boxRoundStringArray(doc,sarray,boxchars ,prestring)
	for i = 0 to ubound(sarray)
		leni= len(sarray(i))
		if leni >mx then mx = leni
	next
	otext = doc.gettext
	tc = otext.createtextcursorbyrange(otext.getstart)

	tc.string =prestring & mid(boxchars,1,1) & string(mx,mid(boxchars,2,1)) & mid(boxchars,3,1)
	tc.collapsetoend
	oText.insertControlCharacter(tc, com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, False)

	for i = 0 to ubound(sarray)

		st =prestring & mid(boxchars,4,1) & sarray(i)
		v = mx-len(sarray(i))
		if v>0 then st = st & string(v," ")
		st =st & mid(boxchars,5,1)
		tc.string = st
		tc.collapsetoend
		oText.insertControlCharacter(tc, com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, False)

	next

	tc.string =prestring & mid(boxchars,6,1) & string(mx,mid(boxchars,7,1)) & mid(boxchars,8,1)

end sub



Test 2 uses a different approach - first create some paragraphs consisting of lines of space characters in a blank Writer document. Then make a selection using the block selection mode. The macro draws the boxes on by replacing space characters with the box characters.

Code: Select all





sub test2


	'┌───────────────────────────────────┐
	'│Call insertSpacedlines             │
	'│in a Writer document               │
	'│to add some lines full             │
	'│of spaces. Write something         │
	'│using overtype mode.               │
	'│Use BLK select mode to             │
	'│select round it. Then choose       │
	'│a pattern and call drawboxBlKSel.  │
	'│A non-proportional font will be    │
	'│needed.                            │
	'└───────────────────────────────────┘
	'
	boxchars = "┌─┐││└─┘"
	'boxchars ="╔═╗║║╚═╝"
	'boxchars ="░░░░░░░░"
	'boxchars ="▓▓▓▓▓▓▓▓"
	'boxchars ="████████"
	'boxchars ="$$$$$$$$"
	'boxchars ="▓▓▓▓▓▓▓▓"
	'boxchars ="@@@@@@@@"

	insertSpacedlines(20,40) 'CALL THIS FIRST IN A NEW WRITER DOCUMENT 
	'select a rectangle using BLK select mode
	'THEN COMMENT OUT that line and uncomment the below line and run 
	'
'	drawboxBlKSel boxchars
end sub

sub insertSpacedlines(no,width)
	st=string(width," ")
	otext=thiscomponent.text
	tc = otext.createtextcursorbyrange(otext.getend)
	for i= 1 to no

		tc.string =st
		tc.collapsetoend
		oText.insertControlCharacter(tc, com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, False)

	next
end sub

Sub DrawBoxBlKSel(boxchars as string)
	dim boo as boolean

	on error resume next
	w = thiscomponent.currentcontroller.frame.componentwindow.windows(0).accessiblecontext.getaccessiblechild(0).accessiblecontext.getaccessiblechild(0)
	for i = 0 to  w.accessiblecontext.getaccessiblechildcount -1
		a =w.accessiblecontext.getaccessiblechild(i)
		with a
			if .getselectionstart <> -1 then
				if not boo then
					boo = true
					startline =i
				end if
				.replacetext .getselectionstart ,.getselectionstart+1,mid(boxchars,4,1)
				.replacetext .getselectionend -1 ,.getselectionend,mid(boxchars,5,1)
				endline=i
			end if

		end with
	next

	a =w.accessiblecontext.getaccessiblechild(startline)
	with a
		.replacetext .getselectionstart ,.getselectionstart+1,mid(boxchars,1,1)
		.replacetext .getselectionend -1 ,.getselectionend,mid(boxchars,3,1)
		st = string(.getselectionend-.getselectionstart-2,mid(boxchars,2,1)
		.replacetext .getselectionstart+1,.getselectionend -1,st
	end with
	a =w.accessiblecontext.getaccessiblechild(endline)
	with a
		.replacetext .getselectionstart ,.getselectionstart+1,mid(boxchars,6,1)
		.replacetext .getselectionend -1 ,.getselectionend,mid(boxchars,8,1)
		st = string(.getselectionend-.getselectionstart-2,mid(boxchars,7,1))
		.replacetext .getselectionstart+1,.getselectionend -1,st
	end with

hr:
End Sub


Edit: removed some surplus code I didn't remove in the test2 listing.

Re: Box Drawing Characters

Posted: Fri Dec 04, 2020 3:47 pm
by JeJe
This code will convert a simple texttable in Writer to a box character based version for text files displaying non proportional fonts.
table.jpg

Code: Select all


	'┌─┬─┐
	'│ │ │
	'├─┼─┤
	'│ │ │
	'└─┴─┘
	'

	'put cursor in a simple single lines of text regular texttable
	'and it will be converted to a box character version and disposed
sub test
	ch = "┌┐└┘─│┬┴├┤┼"
	'ch = "░░░░░░░░░░░"
	converttable(ch)
end sub

sub converttable(ch)
	cc = thiscomponent.currentcontroller
	vc = thiscomponent.currentcontroller.viewcursor
	if isnull(vc.texttable)=false then
		t = vc.texttable
		st = gettablestring(t,ch)
		thiscomponent.currentcontroller.select(t.anchor.start)
		thiscomponent.text.removetextcontent(t)
		thiscomponent.currentcontroller.selection.getbyindex(0).string = st
	end if
end sub

Function GetTablestring(t,ch)
	if ch ="" then ch=  "┌┐└┘─│┬┴├┤┼"


	cols = t.columns.count
	rows = t.rows.count

	dim colwidths(cols -1)

	for x = 0 to cols -1
		for y = 0 to rows - 1
			ll= len(t.getcellbyposition(y,x).string)
			if ll>colwidths(y) then colwidths(y) = ll
		next
	next

	tot =-1
	for x = 0 to cols -1
		tot =tot + colwidths(x) +1
	next

	blankrow= mid(ch,9,1) & string(tot,mid(ch,5,1)) & mid(ch,10,1) & chr(13)
	firstblankrow = blankrow
	lastblankrow = blankrow
	n = 1
	for x = 0 to cols -1
		n= n+colwidths(x) +1
		mid(blankrow,n,1) = mid(ch,11,1)
		mid(firstblankrow,n,1) = mid(ch,7,1)
		mid(lastblankrow,n,1) = mid(ch,8,1)
	next

	mid(blankrow,len(blankrow)-1,1)=mid(ch,10,1)
	mid(firstblankrow,1,1)=mid(ch,1,1)
	mid(firstblankrow,len(firstblankrow)-1,1)=mid(ch,2,1)
	mid(lastblankrow,1,1)=mid(ch,3,1)
	mid(lastblankrow,len(lastblankrow) -1,1)=mid(ch,4,1)

	tst = firstblankrow

	for x = 0 to cols -1
		tst  =tst & mid(ch,6,1)
		for y = 0 to rows - 1
			st = t.getcellbyposition(y,x).string
			st = st &  string( colwidths(y) - len(st)," ")  & mid(ch,6,1)
			tst = tst & st
		next

		tst = tst  & chr(13)
		if x <> cols -1 then tst = tst & blankrow
	next

	tst = tst & lastblankrow
	gettablestring =tst

End function

Re: Box Drawing Characters

Posted: Sun Jan 24, 2021 11:23 pm
by JeJe
This code converts a texttable where the cells can have more than one line of text.
The test sub needs a document with a texttable and also a frame after it for the result.

Code: Select all



'Converts a table to a matching text only version
'with box characters for the borders
'needs a non-proportional font such as Courier New

private type stringarray
	sts() as string
end type

sub test 
'create a document with a single table 
'and add a text frame after it sized big enough for the result to be added to it

	'boxchars ="╔═╗║║╚═╝╣╠╬╦╩"
	boxchars = "┌─┐││└─┘┤├┼┬┴"
	'boxchars ="░░░░░░░░░░░░░░░"
	'boxchars ="▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓"
	'boxchars ="███████████████"
	'boxchars ="@@@@@@@@@@@@@@@"
	'boxchars ="             "
	'boxchars ="•••••••••••••"
	'boxchars ="............."


	doc = thiscomponent

	st = GetTableString(doc,doc.texttables.getbyindex(0),boxchars)

	with doc.textframes.getbyindex(0).text
	.string =""
	.createenumeration.nextelement.CharFontName = "Courier New" 'we need a non-proportional font
	.text.string= st
	end with
end sub


Function GetTableString(doc,t,boxchars)
	dim c as long

	ubc= t.columns.count -1

	ubr = t.rows.count-1

	dim ii(ubc,ubr) as stringarray
	dim maxlens(ubc)
	dim maxrows(ubr)

	for i = 0 to ubc
		c=0
		for j=0 to ubr

			ii(i,j)=new stringarray
			with ii(i,j)

				txt =t.getcellbyposition(i,j).text

				doc.currentcontroller.select(txt.getstart)
				vc = doc.currentcontroller.viewcursor
				mxr =0
				c=0
				do	
					tmp= ii(i,j).sts
					redim preserve tmp(c)
					vc.collapsetostart
					vc.gotoEndOfLine(true)
					tc = vc.text.createtextcursorbyrange(vc)
					tmp(c) = tc.string
					ii(i,j).sts = tmp
					lenvc= len(tc.string())
					if lenvc >= maxlens(i) then maxlens(i) =lenvc
					c=c+1

					vc.collapsetostart
					vc.godown(1,false)

					if equalunoobjects(vc.text,txt) = false then exit do
					vc.gotostartOfLine(false)
					mxr =mxr +1
				loop

				if mxr > maxrows(j) then maxrows(j) = mxr


			end with
		next

	next


	for i = 0 to ubc
		ll= maxlens(i)

		for j= 0 to ubr

			tmp=ii(i,j).sts

			redim preserve tmp(maxrows(j))

			for l = 0 to maxrows(j)
				st = tmp(l)
				if len(st) < ll then st = st & space(ll- len(st))
				tmp(l)=st
			next
			ii(i,j).sts =tmp
		next
	next

	st = ""
	tleftc= mid(boxchars,1,1)
	trightc= mid(boxchars,3,1)
	bleftc= mid(boxchars,6,1)
	trightc= mid(boxchars,8,1)
	vline = mid(boxchars,4,1)
	hline = mid(boxchars,2,1)

	crossline = mid(boxchars,10,1)
	firstline = mid(boxchars,1,1)
	endline = mid(boxchars,6,1)
	for i = 0 to ubc
		crossline = crossline & string(maxlens(i),hline)
		firstline = firstline & string(maxlens(i),hline)
		endline = endline & string(maxlens(i),hline)
		if i <> ubc then
			crossline = crossline & mid(boxchars,11,1)
			firstline = firstline & mid(boxchars,12,1)
			endline = endline & mid(boxchars,13,1)
		else
			crossline = crossline & mid(boxchars,9,1)
			firstline = firstline & mid(boxchars,3,1)
			endline = endline & mid(boxchars,8,1)
		end if
	next

	st =firstline & chr(13)
	for j = 0 to ubr
		for mx =0 to maxrows(j)
			st = st & vline
			for i = 0 to ubc
				st = st & ii(i,j).sts(mx)
				st = st & vline
			next
			st = st & chr(13)
		next
		if j<> ubr then	st = st  & crossline & chr(13)
	next
	st = st  & endline
	GetTableString=st
End function




Re: Box Drawing Characters

Posted: Fri Jan 29, 2021 10:46 pm
by JeJe
The table code has been improved a little and put in the attached extension.

Install extension. Run MyMacro JeText/AAA/ShowBoxCharacterDialog

Shows dialog to make non-proportional text documents from writer document
Including converting tables to aligned text and added spaces for the paragraph indent
Also tools to enter text upon a series of blank-space lines
Help is the tooltips

Usual caveats, use at own risk, work in progress, consider preliminary code etc.