[Solved] Request for comments: Change straight quotes to curly quotes (smart quotes)

Discuss the word processor
Post Reply
User avatar
MrProgrammer
Moderator
Posts: 5281
Joined: Fri Jun 04, 2010 7:57 pm
Location: Wisconsin, USA

[Solved] Request for comments: Change straight quotes to curly quotes (smart quotes)

Post by MrProgrammer »

I am planning to create a new tutorial and ask the forum volunteers for comments about this material.


Straight and curly.png
Straight and curly.png (93.52 KiB) Viewed 4746 times

OpenOffice will replace straight double quotes with curly quotes as you type them since features Format → AutoCorrect → While Typing and Format → AutoCorrect → AutoCorrect Options → Localized Options → Double Quotes → Replace are enabled by default. You could enable replacement of straight single quotes with curly quotes by enabling the corresponding option.

However sometimes the text was originally typed in a different word processor which did not replace straight quotes with curly quotes. When the document is opened with OpenOffice, the straight quotes remain. To convert the straight quotes to smart quotes:

• Ensure Format → AutoCorrect → AutoCorrect Options → Localized Options are set correctly. Set the Single Quotes → Replace and/or the Double Quotes → Replace options. The default Start and End characters are the curly quotes. If you've changed them, click the Default buttons.

• Ensure all other AutoCorrect options are disabled. This prevents any automatic changes except straight quote to curly quote conversions. In Localized Options, uncheck every box in the [M] column. Also, in Options, uncheck every box in the [M] column. Click OK.
Curly.gif
Curly.gif (46.27 KiB) Viewed 4746 times

• Using the Format → Styles and Formatting dialog, set the style of the paragraphs which you want to change to Default. Quotes in paragraphs which are set to a different style will not be altered.

• Select the paragraphs which contain the quotes you want to change, or select nothing to change every paragraph with the Default style.

• Use Format → AutoCorrect → Apply.

This will convert straight quotes to curly quotes. If you don't like the result, immediately use Edit → Undo. The conversion will change the style of the paragraphs from Default to Text Body. You can set a different paragraph style now if you like.
Last edited by Hagar Delest on Thu Feb 16, 2023 12:31 am, edited 1 time in total.
Reason: tagged solved.
Mr. Programmer
AOO 4.1.7 Build 9800, MacOS 13.7.6, iMac Intel.   The locale for any menus or Calc formulas in my posts is English (USA).
User avatar
Hagar Delest
Moderator
Posts: 33397
Joined: Sun Oct 07, 2007 9:07 pm
Location: France

Re: Request for comments: Change straight quotes to curly quotes (smart quotes)

Post by Hagar Delest »

I have 2 comments:
- The second screenshot should show the final options, meaning all the check marks unchecked but those needed. So that users can compare with the configuration that leads to the intended result.
- To make sure that the relevant text only is selected, you can add a step: use the Find & Replace dialog to search for the quotes to be replaced, Find All and close the dialog, then proceed with the style and autocorrect application.
LibreOffice 25.2 on Linux Mint Debian Edition (LMDE Faye) and 24.8 portable on Windows 11.
erbsenzahl
Volunteer
Posts: 258
Joined: Tue Apr 18, 2017 8:23 am
Location: Germany

Re: Request for comments: Change straight quotes to curly quotes (smart quotes)

Post by erbsenzahl »

However sometimes the text was originally typed in a different word processor which did not replace straight quotes with curly quotes.
Please add:
... in a different word processor or copied from the internet

@MrProgrammer: Thanks for starting this tutorial!
LibreOffice current versions 7.x & 24.x and OpenOffice 4.1.15
on LinuxMint 20 - 21 Mate, W10-64 pro
JeJe
Volunteer
Posts: 3068
Joined: Wed Mar 09, 2016 2:40 pm

Re: Request for comments: Change straight quotes to curly quotes (smart quotes)

Post by JeJe »

The other method of doing find and replaces should perhaps be mentioned... if a paragraph begins with a quote it must be an opening one... replace on that basis etc. I thought that was a good solution. Style changing can have unwanted effects depending on how simple the document is - so may not suit everyone.

The ideal solution would be a macro or extension where someone just has to run one command to easily fix the document whichever method - and which otherwise keeps or restores the document's original state.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
User avatar
Hagar Delest
Moderator
Posts: 33397
Joined: Sun Oct 07, 2007 9:07 pm
Location: France

Re: Request for comments: Change straight quotes to curly quotes (smart quotes)

Post by Hagar Delest »

I would even change "word processor" to "application", because the paste may come from something else than a word processor.

I agree with JeJe, the other methods will prevent any change of style.
The find and replace method is also a good one IMHO. Less complex than the macro, even if it requires 2 steps.

Note that in French, I forgot to say in my previous post, the change is wrong for the opening double quote. French requires a nonbreaking space between the text and the quotes and it is placed before the quote in both cases with the autocorrect application (OK for closing but wrong for opening). Not a big deal because there is already an extension (Grammalecte) that does the job (and much more).
LibreOffice 25.2 on Linux Mint Debian Edition (LMDE Faye) and 24.8 portable on Windows 11.
User avatar
RoryOF
Moderator
Posts: 35064
Joined: Sat Jan 31, 2009 9:30 pm
Location: Ireland

Re: Request for comments: Change straight quotes to curly quotes (smart quotes)

Post by RoryOF »

I think there should be a warning near the top of the proposed Tutorial that this method is a general method, designed for the "normal" quotes of many languages, and that detailed editing for specific languages and corner cases may be necessary and remains the responsibility of the individual User.

I now act as Devil's Advocate and present some such corner cases for information - there may be others:

in representations of colloquial English there can be abbreviations such as don't, won't. How would these be handled?

Also, there can be elisions such as
Macbeth: If it were done when ’tis done, then ’twere well It were done quickly:

In extended speech, ranging over several paragraphs, in conventional typesetting it is not unusual that each paragraph starts with an opening quote character, but the closing quote is deferred until the end of the extended speech, so one can have unbalanced opening/closing quotes.

I think it will confuse the User(s) - who, as we know, can be easily confused - to list such exceptions, so I think the catch-all warning near the start of the tutorial would be sufficient.

Rory
Apache OpenOffice 4.1.15 on Xubuntu 22.04.5 LTS
esperantisto
Volunteer
Posts: 578
Joined: Mon Oct 08, 2007 1:31 am

Re: Request for comments: Change straight quotes to curly quotes (smart quotes)

Post by esperantisto »

JeJe wrote: Thu Jan 12, 2023 10:32 am
The ideal solution would be a macro or extension where someone just has to run one command to easily fix the document…
There is such a solution, namely, OOoFBTools (see Document text corrector in the menu). However, only for Russian or other languages that use «guillemets». Well, it is free software and one can hack the code :-)
AOO 4.2.0 (of 2015) / LO 7.x / Win 7 / openSUSE Linux Leap 15.4 (64-bit)
John_Ha
Volunteer
Posts: 9600
Joined: Fri Sep 18, 2009 5:51 pm
Location: UK

Re: Request for comments: Change straight quotes to curly quotes (smart quotes)

Post by John_Ha »

There are a number of macros available. I have used this one by bluegecko in the past where my changes are comments preceded by jh or jhq. It gives some idea of the complexity of the problem.

When OOo 3.4 changed the regular expressions engine I had to modify it - see comment.

I have used Sub FindReplaceQuotes (sFind,sReplace,sScope) to build a number of macros. I find it very useful as it makes a macro readable as any find/replace search is on just one line in the macro and it is easy to see what is happening.

Note the comment about AutoCorrect being buggy and restricted to text formatted in the default paragraph style. I don't know if it still applies.
Although OpenOffice has an apparently similar Autocorrect function, it's buggy in all but the simplest of cases. Autocorrect, if you want to apply it to an entire document, is unfortunately also restricted to text formatted in the default paragraph style, so useless if your document is already styled up.

Code: Select all

sub Quotes

'   By bluegecko, 13 January 2010. Public domain.

'jh Regular expressions changed in OOo 3.4 - search at start / end of word changed

'   This is a revised version of the smart quotes routine posted in June 2009 on this
'   same page (http://www.oooforum.org/forum/viewtopic.phtml?p=328916)
'   The macro switches apostrophes and quotation marks (single and double) from
'   their straight (or "dumb") variants to what are variously called "smart", "curly"
'   or "typographer's" quotes, and vice-versa.

'   Although OpenOffice has an apparently similar Autocorrect function, it's buggy
'   in all but the simplest of cases. Autocorrect, if you want to apply it to an entire
'   document, is unfortunately also restricted to text formatted in the default paragraph
'   style, so useless if your document is already styled up.

'   This macro provides a solution. It should work correctly in most instances, and should
'   also preserve any character formatting or styling. I've tested it in various contexts,
'   including contemporary quotation formatting (no space on one side of the quotation mark);
'   in older style formatting with spaces on either side of the quotation mark; and, also an
'   old style (Victorian and earlier), with double quotes without closures that were used to
'   mark long quotes split into several paragraphs, where the closing double quote only appears
'   at the end of the last paragraph. The macro should also correctly deal with apostrophes, and,
'   hopefully, any combination or multiple of single quotes and apostrophes.

'   The logic makes some assumptions:
'   1. single quotation marks within words are apostrophes
'   2. if there's an odd number of quotation marks (excluding apostrophes) in a paragraph, the
'   first one is considered to have no closure (as was the norm in the 19th century: quotations
'   spanning several paragraphs had an opening quotation mark at the start of each paragraph,
'   but a closing mark only at the end of the last paragraph)
'   3. stand-alone acute and grave accents are assumed to be single quotation marks, and will
'   be converted as such.

'   The routine uses a subroutine to perform the search and replacements. It uses far more
'   steps than would have been necessary were OpenOffice's implementation of Regular Expressions
'   not so bloody awful (and were OpenOffice not in the habit of trashing character formatting
'   when performing Regular Expression search/replaces on parts of a string).

'   LIMITATIONS - GLOTTAL STOPS
'   The macro does not deal with single quotes used to indicate a glottal stops in some transliterations,
'   for instance Arabic (eg. ’Abdullah). In such transliterations, aleph glottal stops are often
'   written with a single right quotation mark, whilst the reverse form, the ‘ayn, is often written with
'   a left quotation mark.
'   I can't think of a method to reliably detect these without messing up the single quote detection, as
'   even if I used a word list, the opening quote might really be a quote, not a glottal stop.
'   If you do use glottal stops in your documents, I'd suggest you use the correct Unicode characters.
'   In properly encoded multilingual fonts such as Gentium, Linux Libertine and DejaVu (all of them
'   free), the aleph (left-pointing) is at code point 02BE, whilst ‘ayn (right-pointing) is at 02BF.
'   In OpenOffice's "Insert | Special character" dialog, they're under Spacing Modifier Letters.
'
'  Alternative method - do two passes with the following
'  The first pass handles all the close quotes; the second gets the remaining (open) quotes.
'  Search for: ([^ ])"       '   " = straight quotes
'  Replace with: $1”         '   ” = curly close quotes 
'  Options/Regular expression: ON
'  Click "Replace All"
'
'  Search for: "             '   " = straight quotes
'  Replace with: “           '   “ = curly open quotes
'  Click "Replace All"
'
'jh Remove the question and set the response = 6 so as to change straight to curly

'jh   a$ = "Use typographer’s quotes?" + Chr(10) + Chr(10) + _
'jh      "— Yes changes all quotation marks and apostrophes to curly ones;" + Chr(10) + _
'jh      "— No changes them all to straight ones;" + Chr(10) + _
'jh      "— Cancel leaves them as they are."
'jh   response = MsgBox(a$,512 + 32 + 3,"Typography - quotes")

'jh   If (response = 2) Then goto noChange                  ' 2 = cancel, so would do nothing

'jh set response to be 6 to change straight quotes to curly quotes

   response = 6        ' set by jh
   
   REM save cursor position
   oViewCursor = ThisComponent.getCurrentController().getViewCursor()
   oTextCursor = oViewCursor.Text.createTextCursorByRange(oViewCursor)

   REM disable screen update
   ThisComponent.lockControllers
   ThisComponent.CurrentController.Frame.ContainerWindow.Enable = False

   REM correct quotes made with acute or grave accents

   FindReplaceQuotes ("´","'","all")                     ' change acute to single quote
   FindReplaceQuotes ("`","'","all")                     ' change grave to single quote

   If (response = 6) Then                              ' APPLY SMART QUOTATION MARKS
   
   REM DOUBLE QUOTES
      DQ = Chr(34)                                 ' Chr(34) is the straight double quote
      FindReplaceQuotes (""+DQ+"[^"+DQ+"]+"+DQ+"","","all")   ' find "....."
      FindReplaceQuotes (""+DQ+"[^"+DQ+"]+","","selection")   ' find "..... within selections
      
'jh  I think that in the above two lines, the first line searches all.  
'jh  The second line searches only the selection 
 
      FindReplaceQuotes (""+DQ+"","“","selection")         ' change  to “
      FindReplaceQuotes ("“[^"+DQ+"“]+"+DQ+"","","all")      ' find “...."
      FindReplaceQuotes (""+DQ+"","”","selection")         ' change " to ”
      FindReplaceQuotes (""+DQ+"","“","all")               ' change remaining quotes to “

   REM SINGLE QUOTES
'jh  I think the following are correct.  I added them here in case they are needed - but they are not used below

      SQ   = Chr(39)    ' single quote - straight
      LQc  = Chr(8216)  ' single quote left - curly  
      RQc  = Chr(8217)  ' single quote right - curly
      LDQc = Chr(8220)  ' double quote left - curly
      RDQc = Chr(8221)  ' double quote right - curly
      
'jh   macro works differently if changes are enabled
        
      FindReplaceQuotes ("'","’","all")          ' change all single quotes to right

'jhq FindReplaceQuotes ("’\>","‘","all")   ' change rightquotes before words to leftquotes

'jhq the previous line should only replace "r-quotes before words". It replaces "r-quotes before and after words"
'jhq because??  \< no longer works for non-alpha chars (in macros?) after OOo 3.4.1. So ...

      FindReplaceQuotes ("’","‘","all")          ' change all rightquotes to leftquotes

'jhq Now change back only the "l-quotes after words"
'jhq ...look for (chars)(l-quote)(punctuation or sp). note \) rqd for )

      FindReplaceRegExp ("([a-z0-9])(‘)(\.|\?| |!|,|;|:|\))","$1’$3","all")      'l-quote at end of word changed to r-quote

'jhq ... and we have done it

'jhq Note that FindReplaceQuotes ("z\>","‘","all") works OK for z\> where z is a character.

      FindReplaceQuotes ("([:alnum:])‘([:alnum:])","","all")   ' find leftquotes within words
      FindReplaceQuotes ("‘","’","selection")                  ' change to rightquotes (apostrophes)
' deal with single quotes that have spaces around them
      FindReplaceQuotes (" ’","¨","all")                   ' temporarily change space+rightquote to dieresis (¨)
      FindReplaceQuotes ("¨[^¨]+¨","","all")               ' select all pairs
      FindReplaceQuotes ("¨[^¨]+","","selection")          ' trim selections to exclude closing space+rightquote
      FindReplaceQuotes ("¨"," ‘","selection")             ' replace with leftquote
      FindReplaceQuotes ("¨"," ’","all")                   ' change markers back to rightquotes
' deal with single quotes at start of line, paragraph, or following tabs or starting punctuation
      FindReplaceQuotes ("(\t|[“\[\(\{])’","","all")       ' select rightquotes following opening punctuation or tabs
      FindReplaceQuotes ("’","‘","selection")              ' change to leftquotes
      FindReplaceQuotes ("^’","‘","all")                   ' change rightquotes at new line to leftquotes
      FindReplaceQuotes ("“ ’","","all")                   ' change rightquotes after quotequote+space (2 steps)
      FindReplaceQuotes ("’","‘","selection")

'jh  simplest to leave this - it will never be executed as response was set to 6 above

   Else                                          ' APPLY STRAIGHT QUOTATION MARKS
      FindReplaceQuotes ("‘","'","all")
      FindReplaceQuotes ("’","'","all")
      FindReplaceQuotes ("“",Chr(34),"all")
      FindReplaceQuotes ("”",Chr(34),"all")
   EndIf

   REM restore cursor position
   oViewCursor = ThisComponent.getCurrentController().getViewCursor()
   oViewCursor.gotoRange(oTextCursor,false)
   
   REM reenable screen update
   ThisComponent.CurrentController.Frame.ContainerWindow.Enable = True
   ThisComponent.unlockControllers

   noChange:

'jh  Remove search backwards and regular expressions by running a dummy RESET search with them unticked
   FindReplaceReset ("abc","abc","all")                             ' change a abc to abc 

End Sub

'========================================================================

Sub FindReplaceQuotes (sFind,sReplace,sScope)

   REM sFind: regular expression     
   REM sReplace: if empty, function selects all occurrences of sFind
   REM sScope: set to "all" for entire document, or "selection" to restrict the scope.
   REM function searches backwards (necessary to correctly catch quotes)

   dim document   as object
   dim dispatcher as object
   document   = ThisComponent.CurrentController.Frame
   dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

   dim args1(18) as new com.sun.star.beans.PropertyValue
   args1(0).Name = "SearchItem.StyleFamily"
   args1(0).Value = 2
   args1(1).Name = "SearchItem.CellType"
   args1(1).Value = 0
   args1(2).Name = "SearchItem.RowDirection"
   args1(2).Value = true
   args1(3).Name = "SearchItem.AllTables"
   args1(3).Value = false
   args1(4).Name = "SearchItem.Backward"
   args1(4).Value = true                            ' backward is required for quotes
   args1(5).Name = "SearchItem.Pattern"
   args1(5).Value = false
   args1(6).Name = "SearchItem.Content"
   args1(6).Value = false
   args1(7).Name = "SearchItem.AsianOptions"
   args1(7).Value = false
   args1(8).Name = "SearchItem.AlgorithmType"
   args1(8).Value = 1                                ' search using Regular Expressions
   args1(9).Name = "SearchItem.SearchFlags"
   If sScope = "all" Then
      args1(9).Value = 65536   ' parse entire doc
   Else
      args1(9).Value = 71680   ' parse selection only
   End If
   args1(10).Name = "SearchItem.SearchString"
   args1(10).Value = sFind
   args1(11).Name = "SearchItem.ReplaceString"
   args1(11).Value = sReplace
   args1(12).Name = "SearchItem.Locale"
   args1(12).Value = 255
   args1(13).Name = "SearchItem.ChangedChars"
   args1(13).Value = 2
   args1(14).Name = "SearchItem.DeletedChars"
   args1(14).Value = 2
   args1(15).Name = "SearchItem.InsertedChars"
   args1(15).Value = 2
   args1(16).Name = "SearchItem.TransliterateFlags"
   args1(16).Value = 1280
   args1(17).Name = "SearchItem.Command"
   If sReplace = "" Then
      args1(17).Value = 1      ' find all
   Else
      args1(17).Value = 3      ' replace all
   End If
   args1(18).Name = "Quiet"
   args1(18).Value = true
   dispatcher.executeDispatch(document, ".uno:ExecuteSearch", "", 0, args1())

End Sub

'========================================================================

Sub FindReplaceReset (sFind,sReplace,sScope)

'jh This sub FindReplaceReset is used merely to untick the Regular Expression and Backwards search boxes.

   REM sFind:     is not a regular expression
   REM sReplace:  if empty, function selects all occurrences of sFind
   REM sScope:    set to "all" for entire document, or "selection" to restrict the scope.
   REM function   searches forwards to untick the box

   dim document   as object
   dim dispatcher as object
   document   = ThisComponent.CurrentController.Frame
   dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

   dim args1(18) as new com.sun.star.beans.PropertyValue
   args1(0).Name = "SearchItem.StyleFamily"
   args1(0).Value = 2
   args1(1).Name = "SearchItem.CellType"
   args1(1).Value = 0
   args1(2).Name = "SearchItem.RowDirection"
   args1(2).Value = true
   args1(3).Name = "SearchItem.AllTables"
   args1(3).Value = false
   args1(4).Name = "SearchItem.Backward"
   args1(4).Value = false                      ' set to false to search forwards so as to untick the box
   args1(5).Name = "SearchItem.Pattern"
   args1(5).Value = false
   args1(6).Name = "SearchItem.Content"
   args1(6).Value = false
   args1(7).Name = "SearchItem.AsianOptions"
   args1(7).Value = false
   args1(8).Name = "SearchItem.AlgorithmType"
   args1(8).Value = 0                          ' set to 0 to untick regular expressions
   args1(9).Name = "SearchItem.SearchFlags"
   If sScope = "all" Then
      args1(9).Value = 65536   ' parse entire doc
   Else
      args1(9).Value = 71680   ' parse selection only
   End If
   args1(10).Name = "SearchItem.SearchString"
   args1(10).Value = sFind
   args1(11).Name = "SearchItem.ReplaceString"
   args1(11).Value = sReplace
   args1(12).Name = "SearchItem.Locale"
   args1(12).Value = 255
   args1(13).Name = "SearchItem.ChangedChars"
   args1(13).Value = 2
   args1(14).Name = "SearchItem.DeletedChars"
   args1(14).Value = 2
   args1(15).Name = "SearchItem.InsertedChars"
   args1(15).Value = 2
   args1(16).Name = "SearchItem.TransliterateFlags"
   args1(16).Value = 1280
   args1(17).Name = "SearchItem.Command"
   If sReplace = "" Then
      args1(17).Value = 1      ' find all
   Else
      args1(17).Value = 3      ' replace all
   End If
   args1(18).Name = "Quiet"
   args1(18).Value = true
   dispatcher.executeDispatch(document, ".uno:ExecuteSearch", "", 0, args1())

End Sub

 Edit: I missed this subroutine above

Code: Select all

Sub FindReplaceRegExp (sFind,sReplace,sScope)
   REM sFind: regular expression
   REM sReplace: if empty, function selects all occurrences of sFind
   REM sScope: set to "all" for entire document, or "selection" to restrict the scope.
   REM function searches backwards (necessary to correctly catch quotes)

   dim document   as object
   dim dispatcher as object
   document   = ThisComponent.CurrentController.Frame
   dispatcher = createUnoService("com.sun.star.frame.DispatchHelper")

   dim args1(18) as new com.sun.star.beans.PropertyValue
   args1(0).Name = "SearchItem.StyleFamily"
   args1(0).Value = 2
   args1(1).Name = "SearchItem.CellType"
   args1(1).Value = 0
   args1(2).Name = "SearchItem.RowDirection"
   args1(2).Value = true
   args1(3).Name = "SearchItem.AllTables"
   args1(3).Value = false
   args1(4).Name = "SearchItem.Backward"
   args1(4).Value = true
   args1(5).Name = "SearchItem.Pattern"
   args1(5).Value = false
   args1(6).Name = "SearchItem.Content"
   args1(6).Value = false
   args1(7).Name = "SearchItem.AsianOptions"
   args1(7).Value = false
   args1(8).Name = "SearchItem.AlgorithmType"
   args1(8).Value = 1
   args1(9).Name = "SearchItem.SearchFlags"
   If sScope = "all" Then
      args1(9).Value = 65536   ' parse entire doc
   Else
      args1(9).Value = 71680   ' parse selection only
   End If
   args1(10).Name = "SearchItem.SearchString"
   args1(10).Value = sFind
   args1(11).Name = "SearchItem.ReplaceString"
   args1(11).Value = sReplace
   args1(12).Name = "SearchItem.Locale"
   args1(12).Value = 255
   args1(13).Name = "SearchItem.ChangedChars"
   args1(13).Value = 2
   args1(14).Name = "SearchItem.DeletedChars"
   args1(14).Value = 2
   args1(15).Name = "SearchItem.InsertedChars"
   args1(15).Value = 2
   args1(16).Name = "SearchItem.TransliterateFlags"
   args1(16).Value = 1280
   args1(17).Name = "SearchItem.Command"
   If sReplace = "" Then
      args1(17).Value = 1      ' find all
   Else
      args1(17).Value = 3      ' replace all
   End If
   args1(18).Name = "Quiet"
   args1(18).Value = true
   dispatcher.executeDispatch(document, ".uno:ExecuteSearch", "", 0, args1())

End Sub
 
Last edited by John_Ha on Thu Jan 12, 2023 10:32 pm, edited 1 time in total.
LO 6.4.4.2, Windows 10 Home 64 bit

See the Writer Guide, the Writer FAQ, the Writer Tutorials and Writer for students.

Remember: Always save your Writer files as .odt files. - see here for the many reasons why.
JeJe
Volunteer
Posts: 3068
Joined: Wed Mar 09, 2016 2:40 pm

Re: Request for comments: Change straight quotes to curly quotes (smart quotes)

Post by JeJe »

John_Ha wrote: Thu Jan 12, 2023 2:00 pm this one by bluegecko
The other thread you posted this in is here (its got the missing FindReplaceRegExp sub):

https://forum.openoffice.org/en/forum/v ... 77#p306177

It gives a likely undesired opening quote at the end of this test.
"Same para"
"not same
para"
(Have never thought to disable the ContainerWindow along with locking controllers though - useful, possibly)
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
John_Ha
Volunteer
Posts: 9600
Joined: Fri Sep 18, 2009 5:51 pm
Location: UK

Re: Request for comments: Change straight quotes to curly quotes (smart quotes)

Post by John_Ha »

Thanks. I'm impressed - that post was 2014.

I have edited my post above to include the missing sub.
JeJe wrote: Thu Jan 12, 2023 7:57 pm It gives a likely undesired opening quote at the end of this test.
"Same para"
"not same
para"
I think any simple approach (ie not thousands of lines of code) is going to fail on some cases and the best you can hope for is a high percentage of correct changes. I'm afraid it's so long since I was working with the code I have forgotten how it works so I cannot comment on a simple fix to catch that case without messing up any other currently correct cases. It probably arises due to my modification when the regular expressions engine changed as it was how beginnings and ends of words were handled - it's certainly where I would start looking. :(
LO 6.4.4.2, Windows 10 Home 64 bit

See the Writer Guide, the Writer FAQ, the Writer Tutorials and Writer for students.

Remember: Always save your Writer files as .odt files. - see here for the many reasons why.
JeJe
Volunteer
Posts: 3068
Joined: Wed Mar 09, 2016 2:40 pm

Re: Request for comments: Change straight quotes to curly quotes (smart quotes)

Post by JeJe »

I think its by design that it doesn't catch that.

I looked here:

https://stackoverflow.com/questions/509 ... rly-quotes

And found this suggestion

If a double-quote is at the beginning of a line, guess that it is an opening quote.
If a double-quote is at the end of a line, guess a closing quote.
If a double-quote is preceded by a space, guess an opening quote.
If a double-quote is followed by a space, guess a closing quote.
If a double-quote doesn't fit into one of the above categories, guess that it is the “opposite” of the most recently used kind of double-quote.
I implemented that but modified with

if the last double quote was at the beginning of the line paragraph then it will be a close quote
if the next double quote is at the end of the line paragraph then it will be an open quote

Those given precedence over the preceding and following spaces rules.

There are likely some assumptions I haven't tested for such as one left in the textrange or one after is a character - not a picture or something.

I don't think I'll be spending any more time on this problem, but here that is:

Code: Select all

const openquote = "“"
const closequote = "”"
sub ChangeToCurlyQuotes

dim lastwasstartpara as boolean
  doc = ThisComponent
on error goto hr
   doc.undomanager.enterUndoContext("Change to curly quotes")
  
search = doc.createSearchDescriptor()
    With search
        .SearchString = chr(34)
        .SearchBackwards = false
    End With

    result = doc.findall(search)
    thiscomponent.currentcontroller.select(result)
    thiscomponent.currentcontroller.viewcursor.gotoRange(result(0).Start, True) 

for i = 0 to result.count -1
bc = result(i).text.createtextcursorbyrange(result(i))
ac = result(i).text.createtextcursorbyrange(result(i))

bc.collapsetostart
bc.goleft(1,true)
if bc.string<>"" then ascbc =  asc(bc.string) else ascbc = 0

ac.collapsetoend
ac.goright(1,true)
if ac.string<>"" then ascac =  asc(ac.string) else ascac = 0

nextisendpara = false
if i<result.count -1 then
tc= result(i+1).text.createtextcursorbyrange(result(i+1))
tc.collapsetoend
bc.goright(1,true)
if tc.string="" then
nextisendpara = true
else
if asc(tc.string) =13 then nextisendpara = true
end if
end if

if ascbc =13 or ascbc =0 then
lastquote=  openquote


elseif ascac= 13 or ascac = 0 then
lastquote =  closequote

elseif lastwasstartpara then
lastquote =  closequote


elseif nextisendpara then
lastquote=  openquote


elseif ascac=32 then
lastquote =  closequote

elseif ascbc=32  then
lastquote=  openquote
else
if lastquote = openquote then lastquote = closequote else lastquote = openquote
end if

if (ascbc =13 or ascbc =0) then 
lastwasstartpara = true 
else 
lastwasstartpara = false
end if

   result(i).string = lastquote
next

hr:
 doc.undomanager.leaveUndoContext()
End Sub
Edit: I was having issues with using .isEndOfParagraph for a textrange - don't know whether that's another of OO's many bugs - but I made it more complex than it would otherwise have been to get round that.
Windows 10, Openoffice 4.1.11, LibreOffice 7.4.0.3 (x64)
User avatar
MrProgrammer
Moderator
Posts: 5281
Joined: Fri Jun 04, 2010 7:57 pm
Location: Wisconsin, USA

Re: Request for comments: Change straight quotes to curly quotes (smart quotes)

Post by MrProgrammer »

Thank you for all of the thoughful comments. I'm sure they have improved the future tutorial.

Hagar Delest wrote: Thu Jan 12, 2023 9:08 am The second screenshot should show the final options, meaning all the check marks unchecked but those needed. So that users can compare with the configuration that leads to the intended result.
Agreed. I was showing the panels which appear using the default OpenOffice Settings, but I agree it will be better to show the end result rather than the starting settings.

Hagar Delest wrote: Thu Jan 12, 2023 9:08 am To make sure that the relevant text only is selected, you can add a step: use the Find & Replace dialog to search for the quotes to be replaced, Find All and close the dialog, then proceed with the style and autocorrect application.
Presumably the goal is usually to change all the single quotes or all the double quotes, or both, to curly quotes. But that's easily accomplished by selecting the corresponding Replace option, either Single or Double, on the Localized Options panel, which one needs to review anyway, and then not selecting any text. I don't see how Find and Replace helps. If it were my document and I had a paragraph which I didn't want changed, perhaps a Perl program, I'd set the style to Preformatted Text or other non-Default style.

erbsenzahl wrote: Thu Jan 12, 2023 9:52 am Please add:
... in a different word processor or copied from the internet
Hagar Delest wrote: Thu Jan 12, 2023 11:29 am I would even change "word processor" to "application", because the paste may come from something else than a word processor.
Sure. I'll add in a different word processor, text editor, other application, or copied from the internet. The last part is redundant since text copied from the internet is coming from a web browser application, but readers will find it easier to understand if I say or copied from the internet.

JeJe wrote: Thu Jan 12, 2023 10:32 am The other method of doing find and replaces should perhaps be mentioned. … Style changing can have unwanted effects depending on how simple the document is - so may not suit everyone.
Hagar Delest wrote: Thu Jan 12, 2023 11:29 am I agree with JeJe, the other methods will prevent any change of style.
I will update the tutorial's subject to clarify that it explains how to use AutoCorrect to convert straight quotes to curly quotes. I will not address any Find and Replace methods. Someone else can create that tutorial. If the text comes from another text editor or the internet I think it will usually have no styles other than Default, so style changing should not be a problem. Advice often found on the forum is, when beginning to work on a document which was created or copied from another application to first use Format → Default Formatting, then set all paragraphs to the Default style, and later apply other OpenOffice styles when the content is finalized.

RoryOF wrote: Thu Jan 12, 2023 1:01 pm I think there should be a warning near the top of the proposed Tutorial that this method is a general method, designed for the "normal" quotes of many languages, and that detailed editing for specific languages and corner cases may be necessary and remains the responsibility of the individual User.
Agreed.

RoryOF wrote: Thu Jan 12, 2023 1:01 pm in representations of colloquial English there can be abbreviations such as don't, won't. How would these be handled? Also, there can be elisions such as Macbeth: If it were done when ’tis done, then ’twere well It were done quickly:
Autocorrect seems to do a good job handling these cases. I think it will be difficult to construct a Find and Replace regular expression which handles the first of these examples properly. The last example shows that if a paragraph begins with a quote it must be an opening one is not always the case.
Autocorrect examples.png
Autocorrect examples.png (117.18 KiB) Viewed 4374 times

esperantisto wrote: Thu Jan 12, 2023 1:37 pm There is such a solution, namely, OOoFBTools
I will focus only on AutoCorrect in my tutorial. Others can create a tutorial for OOoFBTools or other extensions.

John_Ha wrote: Thu Jan 12, 2023 2:00 pm There are a number of macros available.
I will focus only on AutoCorrect in my tutorial. Others can create tutorials for macro solutions.

John_Ha wrote: Thu Jan 12, 2023 10:28 pm I think any simple approach (ie not thousands of lines of code) is going to fail on some cases and the best you can hope for is a high percentage of correct changes
The possibility of a few incorrect changes will be covered by the warning near the top that AutoCorrect is a general method, designed for the "normal" quotes of many languages.

Hagar Delest wrote: Thu Jan 12, 2023 11:29 am Note that in French, I forgot to say in my previous post, the change is wrong for the opening double quote. French requires a nonbreaking space between the text and the quotes and it is placed before the quote in both cases with the autocorrect application (OK for closing but wrong for opening). Not a big deal because there is already an extension (Grammalecte) that does the job (and much more).
I don't claim to understand the rules for French text but perhaps this AutoCorrect option helps. When [M] is selected the change can be made with Format → AutoCorrect → Apply.
French text.png
French text.png (98.1 KiB) Viewed 4366 times
Mr. Programmer
AOO 4.1.7 Build 9800, MacOS 13.7.6, iMac Intel.   The locale for any menus or Calc formulas in my posts is English (USA).
User avatar
Hagar Delest
Moderator
Posts: 33397
Joined: Sun Oct 07, 2007 9:07 pm
Location: France

Re: Request for comments: Change straight quotes to curly quotes (smart quotes)

Post by Hagar Delest »

MrProgrammer wrote: Sat Jan 14, 2023 5:12 am If it were my document and I had a paragraph which I didn't want changed, perhaps a Perl program, I'd set the style to Preformatted Text or other non-Default style.
But maybe there are paragraphs that have a dedicated style and include quotes to be changed. In this case, their style has to be changed to Default and then set back to their initial style. Thus, to limit the number of paragraphs to be managed, especially if you select all the text because you don't want to do that for each paragraph, then selecting only the paragraphs that include those straight quotes may help.
MrProgrammer wrote: Sat Jan 14, 2023 5:12 am I don't claim to understand the rules for French text but perhaps this AutoCorrect option helps. When [M] is selected the change can be made with Format → AutoCorrect → Apply.
Of course it is checked. The problem is that it works fine for closing quotes, not for opening ones:
AutoCorrect.png
AutoCorrect.png (11.9 KiB) Viewed 4313 times
LibreOffice 25.2 on Linux Mint Debian Edition (LMDE Faye) and 24.8 portable on Windows 11.
User avatar
MrProgrammer
Moderator
Posts: 5281
Joined: Fri Jun 04, 2010 7:57 pm
Location: Wisconsin, USA

Re: Request for comments: Change straight quotes to curly quotes (smart quotes)

Post by MrProgrammer »

I think it will be best to refer to this feature as custom quotes. At least the Help panel Index has an entry for custom quotes. The term curly is never used. The term smart is only used for smart tags. I will include the terms curly quotes and smart quotes in the tutorial in case people search for them. Amazingly the OOo 3.3 Writer Guide does not use the terms quote, quotes, curly, or smart at all! The term custom is used often, but never to refer to this AutoCorrect feature. The term autocorrect is used often, but not in reference to changing quotes. A picture shows that Localized Options used to be called Custom Quotes.

I find it odd that the quote replacment feature is in the Locaiized Options section. In my tests, the language which is specified for the paragraph makes no difference at all, whether it's set via direct formatting of the paragraph or via the Default style's language. Even when I set the language of the Default style to [None}, quotes are still changed as long as the paragraph has the Default style. Perhaps this is a reported issue, but I don't see that it is. I don't see a way to specify different custom quotes for different languages. In the dialog where one sets options for custom quotes, the box where one could specify a language is not selectable. Calling this feature a Localized Option does not make sense to me.

Hagar Delest wrote: Sat Jan 14, 2023 1:24 pm But maybe there are paragraphs that have a dedicated style and include quotes to be changed.
Not if the document was created on a text editor or if the document is based on text copied from the internet. Nonetheless I will mention using Find to mark paragraphs to be changed. I will note that the entire paragraph is altered by Format → AutoCorrect → Apply if any text in it is selected. This behavior is not discussed anywhere that I can find. I have no way to to explore what happens when Word documens are opened, so I won't mention that situation.

Hagar Delest wrote: Sat Jan 14, 2023 1:24 pm The problem is that it works fine for closing quotes, not for opening ones:
My mistake. Reading more about Add non breaking space before specific punctuation marks in French text, it seems this feature is not related to quotes at all, thus I won't mention it in the tutorial. There is no point in complicating the material.
  • Inserts a non breaking space before ";", "!", "?" and ":" when the character language is set to
    French (France, Belgium, Luxembourg, Monaco, or Switzerland) and
    before ":" only when the character language is set to French (Canada).
I looked for 20 minutes at the reported issues for AutoCorrect. There are more than 100, so my review was not thorough. I couldn't find any which related to problems with opening quotes in French text. The custom quotes replacement feature does not address the requirement to add non-breaking spaces since the replacement seems to be limited to a single character.
Mr. Programmer
AOO 4.1.7 Build 9800, MacOS 13.7.6, iMac Intel.   The locale for any menus or Calc formulas in my posts is English (USA).
Post Reply