How to find in Writer if the cursor is in a Text Box

Creating a macro - Writing a Script - Using the API (OpenOffice Basic, Python, BeanShell, JavaScript)
Post Reply
roland65
Posts: 32
Joined: Tue Oct 18, 2011 6:41 pm

How to find in Writer if the cursor is in a Text Box

Post by roland65 »

Hi,

I did a search but couldn't find an answer to this simple question: in a Writer document, how can I find if the cursor is in a Text Box (the one you create with Insert / Text Box)?

Thanks for your help,
RB
LibreOffice 7.5.x on Ubuntu
User avatar
Villeroy
Volunteer
Posts: 31279
Joined: Mon Oct 08, 2007 1:35 am
Location: Germany

Re: How to find in Writer if the cursor is in a Text Box

Post by Villeroy »

Install [Tutorial] Introduction into object inspection with MRI, put the cursor into a text box and call menu:Tools>Extenstions>"MRI <--selection"
Please, edit this topic's initial post and add "[Solved]" to the subject line if your problem has been solved.
Ubuntu 18.04 with LibreOffice 6.0, latest OpenOffice and LibreOffice
roland65
Posts: 32
Joined: Tue Oct 18, 2011 6:41 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by roland65 »

OK, thanks, I'll investigate using the MRI tool...
LibreOffice 7.5.x on Ubuntu
roland65
Posts: 32
Joined: Tue Oct 18, 2011 6:41 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by roland65 »

Hi again,

perhaps I wasn't much clear: what I would like to do is to distinguish between the case 1) where a text box is selected (handles highlighted) and 2) the case where the visual cursor is *within* the text box and allows to enter some text. I'd like to achieve this in Writer or Impress.

I used the MRI tool or the new builtin dev tool in LibreOffice but I wasn't able to find some feature (supported service name, method, property) that allows to distinguish between both cases...

Do you think it's feasible?

Thanks a lot for any help...
RB
LibreOffice 7.5.x on Ubuntu
User avatar
Villeroy
Volunteer
Posts: 31279
Joined: Mon Oct 08, 2007 1:35 am
Location: Germany

Re: How to find in Writer if the cursor is in a Text Box

Post by Villeroy »

Code recorded by MRI

Code: Select all

Sub Snippet
  Dim oCurrentController As Variant
  Dim oObj1 As Boolean
  Dim oCurrentSelection As Variant
  Dim sImplementationName As String

  oCurrentController = ThisComponent.getCurrentController()
  oObj1 = oCurrentController.isFormDesignMode()
  oCurrentSelection = ThisComponent.getCurrentSelection()
  
  sImplementationName = oCurrentSelection.getImplementationName()
End Sub
Please, edit this topic's initial post and add "[Solved]" to the subject line if your problem has been solved.
Ubuntu 18.04 with LibreOffice 6.0, latest OpenOffice and LibreOffice
roland65
Posts: 32
Joined: Tue Oct 18, 2011 6:41 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by roland65 »

Hi Villeroy,

thanks for the code snippet. Yes, it allows to distinguish between normal text in Writer (where getImplementationName() returns 'SwXTextRange') and a text box (getImplementationName() returns 'com.sun.star.drawing.SvwShapeCollection').

But when we select the text box *or* when the view cursor is within the text box (two different situations), getImplementationName() returns 'com.sun.star.drawing.SvwShapeCollection' in both cases...

To reproduce:

1. Create a blank document in Writer

2. Insert a text box (Menu Insert/ Text Box) and write some text in it

3. With the cursor still within the text box, execute the Snippet macro => getImplementationName() returns 'com.sun.star.drawing.SvwShapeCollection'

4. Press Esc, then the text box is selected (or you can select it using the mouse). The cursor is not anymore within the text box. The text box handles are highlighted. Execute the Snippet macro => getImplementationName() returns 'com.sun.star.drawing.SvwShapeCollection'
LibreOffice 7.5.x on Ubuntu
User avatar
RoryOF
Moderator
Posts: 34611
Joined: Sat Jan 31, 2009 9:30 pm
Location: Ireland

Re: How to find in Writer if the cursor is in a Text Box

Post by RoryOF »

Check with Andrew Pitonyak's books on Open-/Libre-Office macro programming at
https://www.pitonyak.org/oo.php
Apache OpenOffice 4.1.15 on Xubuntu 22.04.4 LTS
RPG
Volunteer
Posts: 2250
Joined: Tue Apr 14, 2009 7:15 pm
Location: Netherlands

Re: How to find in Writer if the cursor is in a Text Box

Post by RPG »

It seems you want work with textsearch: TextSearch

Apache OpenOffice Community Forum - [Solved] Regular expressions for searching strings? - (View topic)In the link you can find an example.
LibreOffice 7.1.4.2 on openSUSE Leap 15.2
JeJe
Volunteer
Posts: 2779
Joined: Wed Mar 09, 2016 2:40 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by JeJe »

In both the selection and viewcursor the same object looks to be returned whether the border is selected or the text is.

Don't know what's possible in Ubuntu but in Windows a very roundabout way that might or might not work would be to measure the shape's position then simulate an arrow key press with Windows API calls and see if the position changed or not.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
JeJe
Volunteer
Posts: 2779
Joined: Wed Mar 09, 2016 2:40 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by JeJe »

Another indirect way would be to try pasting some text (record a macro to do that) - if the border is selected nothing looks to happen, if its the text then it will succeed and you can undo it.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
roland65
Posts: 32
Joined: Tue Oct 18, 2011 6:41 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by roland65 »

JeJe wrote: Sun Feb 26, 2023 10:42 pm Another indirect way would be to try pasting some text (record a macro to do that) - if the border is selected nothing looks to happen, if its the text then it will succeed and you can undo it.
Thanks for the idea, I'll try and post the code if I succeed...
LibreOffice 7.5.x on Ubuntu
JeJe
Volunteer
Posts: 2779
Joined: Wed Mar 09, 2016 2:40 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by JeJe »

There's Select all as well - using the dispatch helper selects everything in the textbox if its text that's selected and appears to have no effect if its the border - needs a way to tell if the selection has changed from code though.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
JeJe
Volunteer
Posts: 2779
Joined: Wed Mar 09, 2016 2:40 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by JeJe »

Seeing if the controller's transferable supports text seems to do it.

Code: Select all

dim df as new com.sun.star.datatransfer.DataFlavor
trans= thiscomponent.currentcontroller.gettransferable
df.mimetype = "text/plain;charset=utf-16"
if trans.isDataFlavorSupported(df) then msgbox "isintext"
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
roland65
Posts: 32
Joined: Tue Oct 18, 2011 6:41 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by roland65 »

JeJe wrote: Mon Feb 27, 2023 3:29 pm Seeing if the controller's transferable supports text seems to do it.
Wow, that's brilliant JeJe! It works like a charm in Writer...

However, it doesn't work in Impress... I've checked and found that getTransferable() can only be used in Writer and Calc.

So, at least in Writer I now have a solution, thanks a lot for that. Indeed, I need such a test in the TexMaths extension...

I have also tried your idea about using the dispatcher to check if some text can be inserted or not in the selected object. I ended up with the following macro, that works in Writer, Draw and Impress.

However, this macro has a problem: I don't know how to remove the inserted character. I tried different solutions (see at the of the the code) but with no luck. Any idea?

Code: Select all

' Draft macro to test if the visible cursor is in a text box or not
' Can be used in Writer, Draw or Impress
' But the inserted character used for testing cannot be removed?
Sub InTextBox

	' Current document and controller
 	Dim oDoc as Variant, oDocCtrl as Variant
	oDoc = ThisComponent
	oDocCtrl = oDoc.getCurrentController()

	' Selected object
	Dim oSelection as Variant
	oSelection = oDocCtrl.getSelection()
	If isEmpty(oSelection) Then
		msgbox "Nothing selected"
		Exit Sub
	End If
	
	' A text box is a shape collection
	Dim sImplementationName as String
	sImplementationName = oSelection.getImplementationName()
	If sImplementationName <> "com.sun.star.drawing.SvxShapeCollection" Then
		msgbox "Not in text box"
		Exit Sub
	End If
		
	' Shape and shape text
	Dim oShape as Variant, oShapeText as Variant
	oShape = oSelection.getByIndex(0)
	oShapeText = oShape.Text
	
	' Text cursor and text content
	Dim oTextCursor as Variant, sText as String
	oTextCursor = oShape.Text.createTextCursor()
	sText = oShapeText.String
	msgbox sText

	' Try to insert some character using the dispatcher
	Dim oDispatcher as Variant
	oDispatcher = createUnoService( "com.sun.star.frame.DispatchHelper" )

	' Works in Writer but not in Draw or Impress
	'dim args1(0) as new com.sun.star.beans.PropertyValue
    'args1(0).Name = "Text"        ' Insert a "z"
    'args1(0).Value = "z"
    'oDispatcher.executeDispatch(oDocCtrl.Frame, ".uno:InsertText", "", 0, args1())

	' Works in Writer, Draw and Impress
	dim args1(1) as new com.sun.star.beans.PropertyValue
	args1(0).Name = "Symbols"
	args1(0).Value = "z"        ' Insert a "z"
	args1(1).Name = "FontName"
	args1(1).Value = "Arial"	
	oDispatcher.executeDispatch(oDocCtrl.Frame, ".uno:InsertSymbol", "", 0, args1())

	' New text content
	Dim sNewText as String
	sNewText = oShapeText.String
	msgbox sNewText

	' If text contents are equal, no character was inserted => not in a text box
	' We could also test if Len(sNewText) > Len(sText)
	If sNewText = sText Then
		
		msgbox "Not in text box"
		
	' If text contents are different, a character was inserted => in a text box
	Else
		
		msgbox "In text box"
		
		' Now, we want to remove the inserted character
		
		' Doesn't work (does nothing)
		'oDispatcher.executeDispatch(oDocCtrl.Frame, ".uno:SwBackspace", "", 0, Array())

		' Doesn't work (insert an invisible character instead of backspace)
		'dim args2(0) as new com.sun.star.beans.PropertyValue
	    'args2(0).Name = "Text"
	    'args2(0).Value = chr(8) ' chr(8) is backspace
	    'oDispatcher.executeDispatch(oDocCtrl.Frame, ".uno:InsertText", "", 0, args2())

	End If
	
End Sub
LibreOffice 7.5.x on Ubuntu
JeJe
Volunteer
Posts: 2779
Joined: Wed Mar 09, 2016 2:40 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by JeJe »

.uno:Undo will undo it but I get the same length of string (testing in Writer) in both cases.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
JeJe
Volunteer
Posts: 2779
Joined: Wed Mar 09, 2016 2:40 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by JeJe »

In Impress you might be able to use this:

Provided some text is selected this will return the string.

Code: Select all

thiscomponent.currentcontroller.selection.string
There will be an error if the border is selected or there is no selection in the text.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
roland65
Posts: 32
Joined: Tue Oct 18, 2011 6:41 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by roland65 »

Once again thanks a lot! Your idea of undoing with .uno:Undo was very good. I had some difficulties because the behaviour is different in Writer, but now I have a macro that works in Writer, Calc, Draw and Impress (in Draw a text box is obtained when you double click on a shape).

So, many thanks to all the people who took time to answer to my question. And special thanks to JeJe...
RB

Code: Select all

' Macro to test if the visible cursor is in a text box or not
' Can be used in Writer, Calc, Draw or Impress
' 27/02/2023
Sub InTextBox

	' Current document and controller
 	Dim oDoc as Variant, oDocCtrl as Variant
	oDoc = ThisComponent
	oDocCtrl = oDoc.getCurrentController()

	' Selected object
	Dim oSelection as Variant
	oSelection = oDocCtrl.getSelection()
	If isEmpty(oSelection) Then
		msgbox "Nothing selected"
		Exit Sub
	End If
	
	' A text box is a shape collection
	Dim sImplementationName as String
	sImplementationName = oSelection.getImplementationName()
	If sImplementationName <> "com.sun.star.drawing.SvxShapeCollection" Then
		msgbox "Not in text box"
		Exit Sub
	End If
		
	' Shape and shape text
	Dim oShape as Variant, oShapeText as Variant
	oShape = oSelection.getByIndex(0)
	oShapeText = oShape.Text
	
	' Text cursor and text content
	Dim oTextCursor as Variant, sText as String
	oTextCursor = oShape.Text.createTextCursor()
	sText = oShapeText.String
	'msgbox sText

	' Try to insert some character using the dispatcher
	Dim oDispatcher as Variant
	oDispatcher = createUnoService( "com.sun.star.frame.DispatchHelper" )

	' Writer document
	If oDoc.SupportsService("com.sun.star.text.TextDocument") Then

		Dim args1(0) as new com.sun.star.beans.PropertyValue
	    args1(0).Name = "Text"
	    args1(0).Value = ","   ' Insert a comma
	    oDispatcher.executeDispatch(oDocCtrl.Frame, ".uno:InsertText", "", 0, args1())
	 
	' Impress, Calc or Draw document   
	Else

		Dim args2(0) as new com.sun.star.beans.PropertyValue
	    args2(0).Name = "Symbols"
	    args2(0).Value = ","    ' Insert a comma
		oDispatcher.executeDispatch(oDocCtrl.Frame, ".uno:InsertSymbol", "", 0, args2())

	End If
	
	' New text content
	Dim sNewText as String
	sNewText = oShapeText.String
	'msgbox sNewText

	' If text contents are equal, no character was inserted => cursor is not in a text box
	' We could also test if Len(sNewText) > Len(sText)
	If sNewText = sText Then
		
		msgbox "Not in text box"
		
	' If text contents are different, a character was inserted => cursor is in a text box
	Else
		
		msgbox "In text box"
		
		' Undo to remove the inserted character
		oDispatcher.executeDispatch(oDocCtrl.Frame, ".uno:Undo", "", 0, Array())

	End If
	
End Sub
LibreOffice 7.5.x on Ubuntu
User avatar
Lupp
Volunteer
Posts: 3548
Joined: Sat May 31, 2014 7:05 pm
Location: München, Germany

Re: How to find in Writer if the cursor is in a Text Box

Post by Lupp »

Clever ideas!
However, the UndoManager may be disabled or not work reliably (overload?) in rare cases.
An alternative not needing Insert/Undo:

Code: Select all

Function textInsideShapeIsSelected() As Boolean
doc   = ThisComponent
cCtrl = doc.CurrentController
cSel  = cCtrl.Selection(0)
REM cSel may be a ShapeCollection.
REM Also a single selected shape is passed this way.
REM Even if the editing cursor is INSIDE of a shape, cSel passes the ShapeCollection.
isShape = cSel.supportsService("com.sun.star.drawing.ShapeCollection")
isInside = False
If isShape Then
REM Despite the fact that cSel may look like a shape,
REM cCtrl can see the transferable content.
REM If a text piece, one of the flavors has the .MimeType "text/rtf".
 trans = cCtrl.getTransferable()
 flavors = trans.TransferDataFlavors
 u = Ubound(flavors)
 For j = 0 To u
  isInside = flavors(j).MimeType = "text/rtf"
  If isInside Then Exit For
 Next j
EndIf
textInsideShapeIsSelected = isInside
End Function

Sub testIt()
MsgBox(IIf(textInsideShapeIsSelected(), "Text portion inside of a shape selected.", _
                                        "Not inside of a shape."))
End Sub
On Windows 10: LibreOffice 24.2 (new numbering) and older versions, PortableOpenOffice 4.1.7 and older, StarOffice 5.2
---
Lupp from München
roland65
Posts: 32
Joined: Tue Oct 18, 2011 6:41 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by roland65 »

Lupp wrote: Tue Feb 28, 2023 12:31 am Clever ideas!
However, the UndoManager may be disabled or not work reliably (overload?) in rare cases.
An alternative not needing Insert/Undo
Your function is like the macro proposed by JeJe. It works in Writer (and in Calc too, I guess) but not in Impress or Draw.
However, it's interesting. Thanks for sharing!
LibreOffice 7.5.x on Ubuntu
User avatar
Lupp
Volunteer
Posts: 3548
Joined: Sat May 31, 2014 7:05 pm
Location: München, Germany

Re: How to find in Writer if the cursor is in a Text Box

Post by Lupp »

roland65 wrote: Tue Feb 28, 2023 11:30 am
Lupp wrote: Tue Feb 28, 2023 12:31 am Clever ideas!
However, the UndoManager may be disabled or not work reliably (overload?) in rare cases.
An alternative not needing Insert/Undo
Your function is like the macro proposed by JeJe. It works in Writer (and in Calc too, I guess) but not in Impress or Draw.
However, it's interesting. Thanks for sharing!
Sorry! I came late to this topic and had obviously missed the post by @JeJe. Apologies!
In addition I had missed that the topic was explicitly extended to Draw and Impress.
Yes. CurrentController.getTransferable doesn't work in Draw. See https://bugs.documentfoundation.org/sho ... ?id=151713 .
(Next time I will read -hopefully- more thoroughly to avoid bloating threads.)
On Windows 10: LibreOffice 24.2 (new numbering) and older versions, PortableOpenOffice 4.1.7 and older, StarOffice 5.2
---
Lupp from München
JeJe
Volunteer
Posts: 2779
Joined: Wed Mar 09, 2016 2:40 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by JeJe »

Perhaps its a Windows vs Linux difference or an LO version one (I'm Windows 10 LO 7.4.0.3) but I get the same "Not in text box" result in both circumstances? The string returned remains the original one even after the input, though its changed in the document.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
JeJe
Volunteer
Posts: 2779
Joined: Wed Mar 09, 2016 2:40 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by JeJe »

Scrap that - it does work for me if run from the menu, I was running it from the IDE.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
roland65
Posts: 32
Joined: Tue Oct 18, 2011 6:41 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by roland65 »

Lupp wrote: Tue Feb 28, 2023 1:27 pm In addition I had missed that the topic was explicitly extended to Draw and Impress.
Yes, at the beginning I wanted this test only in Writer, but in the end I also need it in Impress and Draw...
LibreOffice 7.5.x on Ubuntu
roland65
Posts: 32
Joined: Tue Oct 18, 2011 6:41 pm

Re: How to find in Writer if the cursor is in a Text Box

Post by roland65 »

JeJe wrote: Tue Feb 28, 2023 1:41 pm Perhaps its a Windows vs Linux difference or an LO version one (I'm Windows 10 LO 7.4.0.3) but I get the same "Not in text box" result in both circumstances? The string returned remains the original one even after the input, though its changed in the document.
I did some tests in Linux, Windows 10 (in a VM) an MacOS X (in a VM) and I found that my proposed macro gives only reliable results on Linux. On Windows and Mac OS X, the results are random, but must often the macro doesn't work...

However, for Writer documents, your solution with Transferable works reliably on the three platforms. That's a good point.

I'm quite upset, but that's the strange world of the LibreOffice API...
LibreOffice 7.5.x on Ubuntu
Post Reply