├── .gitignore ├── AboutBox.frm ├── AboutBox.frx ├── AppEventHandler.cls ├── AppleScript └── IguanaTex.scpt ├── BatchEditForm.frm ├── BatchEditForm.frx ├── CopyToClipboard.bas ├── Defaults.bas ├── Dictionary.cls ├── ErrorForm.frm ├── ErrorForm.frx ├── ExportVBA.bas ├── ExternalEditorForm.frm ├── ExternalEditorForm.frx ├── IconvWrapper.bas ├── IguanaTexHelper ├── .swift-format ├── DEVELOP.md ├── Makefile ├── Package.resolved ├── Package.swift ├── README.md └── Sources │ └── IguanaTexHelper │ ├── Keyboard.swift │ ├── Resize.swift │ └── TextWindow.swift ├── LICENSE.txt ├── LatexForm.frm ├── LatexForm.frx ├── LoadVectorGraphicsForm.frm ├── LoadVectorGraphicsForm.frx ├── LogFileViewer.frm ├── LogFileViewer.frx ├── MacFileSystemObject.cls ├── MacUtils.bas ├── Macros.bas ├── MouseWheel.bas ├── README.md ├── RegenerateForm.frm ├── RegenerateForm.frx ├── RegistryAccess.bas ├── SetTempForm.frm ├── SetTempForm.frx ├── ShellWait.bas ├── TextWindow.cls ├── TextWindowFont.cls ├── Utils.bas └── change.log /.gitignore: -------------------------------------------------------------------------------- 1 | .build/ 2 | .swiftpm/ 3 | -------------------------------------------------------------------------------- /AboutBox.frm: -------------------------------------------------------------------------------- 1 | VERSION 5.00 2 | Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} AboutBox 3 | Caption = "IguanaTex" 4 | ClientHeight = 5436 5 | ClientLeft = 48 6 | ClientTop = 336 7 | ClientWidth = 8748.001 8 | OleObjectBlob = "AboutBox.frx":0000 9 | StartUpPosition = 1 'CenterOwner 10 | End 11 | Attribute VB_Name = "AboutBox" 12 | Attribute VB_GlobalNameSpace = False 13 | Attribute VB_Creatable = False 14 | Attribute VB_PredeclaredId = True 15 | Attribute VB_Exposed = False 16 | Option Explicit 17 | Public Sub CloseAboutButton_Click() 18 | Unload AboutBox 19 | End Sub 20 | 21 | 22 | Private Sub LabelURL_Click() 23 | OpenURL "https://www.jonathanleroux.org/software/iguanatex/" 24 | End Sub 25 | 26 | Private Sub LabelGithub_Click() 27 | OpenURL "https://github.com/Jonathan-LeRoux/IguanaTex" 28 | End Sub 29 | 30 | Private Sub UserForm_Initialize() 31 | Me.Top = Application.Top + 110 32 | Me.Left = Application.Left + 25 33 | Me.Height = 300 34 | Me.Width = 448 35 | Me.LabelAuthors.Caption = "by Jonathan Le Roux and Zvika Ben-Haim" & NEWLINE & NEWLINE & _ 36 | "Mac version by Tsung-Ju Chiang and Jonathan Le Roux" 37 | ShowAcceleratorTip Me.CloseAboutButton 38 | #If Mac Then 39 | ResizeUserForm Me 40 | #End If 41 | End Sub 42 | 43 | Private Sub UserForm_Activate() 44 | #If Mac Then 45 | MacEnableAccelerators Me 46 | #End If 47 | End Sub 48 | 49 | -------------------------------------------------------------------------------- /AboutBox.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jonathan-LeRoux/IguanaTex/bf549383004d3443fa5600e21330b521b34049e5/AboutBox.frx -------------------------------------------------------------------------------- /AppEventHandler.cls: -------------------------------------------------------------------------------- 1 | VERSION 1.0 CLASS 2 | BEGIN 3 | MultiUse = -1 'True 4 | END 5 | Attribute VB_Name = "AppEventHandler" 6 | Attribute VB_GlobalNameSpace = False 7 | Attribute VB_Creatable = False 8 | Attribute VB_PredeclaredId = False 9 | Attribute VB_Exposed = False 10 | Option Explicit 11 | '@MemberAttribute VB_VarHelpID, -1 12 | Public WithEvents App As Application 13 | Attribute App.VB_VarHelpID = -1 14 | 15 | Private Sub App_WindowBeforeDoubleClick(ByVal Sel As Selection, ByRef Cancel As Boolean) 16 | If (TryEditLatexEquation()) Then 17 | Cancel = True 18 | End If 19 | End Sub 20 | -------------------------------------------------------------------------------- /AppleScript/IguanaTex.scpt: -------------------------------------------------------------------------------- 1 | on ReadAllExternal(filename) 2 | return read filename as «class utf8» 3 | end ReadAllExternal 4 | 5 | on MacChooseFileOfType(typesStr) 6 | local typeList 7 | 8 | set backup to AppleScript's text item delimiters 9 | set AppleScript's text item delimiters to {","} 10 | set typeList to every text item of typesStr 11 | set AppleScript's text item delimiters to backup 12 | 13 | try 14 | return POSIX path of (choose file of type typeList) 15 | on error number -128 16 | # user cancelled 17 | return "" 18 | end try 19 | end MacChooseFileOfType 20 | 21 | on MacChooseFile(defaultValue) 22 | try 23 | try 24 | return POSIX path of (choose file default location defaultValue) 25 | on error number -1700 26 | # file not exist 27 | return POSIX path of (choose file) 28 | end try 29 | on error number -128 30 | # user cancelled 31 | return defaultValue 32 | end try 33 | end MacChooseFile 34 | 35 | on MacChooseApp(defaultValue) 36 | try 37 | return (choose application)'s id 38 | on error number -128 39 | # user cancelled 40 | return defaultValue 41 | end try 42 | end MacChooseApp 43 | 44 | on MacChooseFolder(defaultValue) 45 | try 46 | try 47 | return POSIX path of (choose folder default location defaultValue) 48 | on error number -1700 49 | # file not exist 50 | return POSIX path of (choose folder) 51 | end try 52 | on error number -128 53 | # user cancelled 54 | return defaultValue 55 | end try 56 | end MacChooseFolder 57 | 58 | on MacExecute(command) 59 | try 60 | do shell script command 61 | return 0 62 | on error number exitStatus 63 | return exitStatus 64 | end try 65 | end MacExecute 66 | 67 | on MacSetClipboard(str) 68 | set the clipboard to str 69 | end MacSetClipboard 70 | 71 | on MacGetClipboard() 72 | return the clipboard as string 73 | end MacGetClipboard 74 | -------------------------------------------------------------------------------- /BatchEditForm.frm: -------------------------------------------------------------------------------- 1 | VERSION 5.00 2 | Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} BatchEditForm 3 | Caption = "Batch edit" 4 | ClientHeight = 5880 5 | ClientLeft = 48 6 | ClientTop = 384 7 | ClientWidth = 4908 8 | OleObjectBlob = "BatchEditForm.frx":0000 9 | StartUpPosition = 1 'CenterOwner 10 | End 11 | Attribute VB_Name = "BatchEditForm" 12 | Attribute VB_GlobalNameSpace = False 13 | Attribute VB_Creatable = False 14 | Attribute VB_PredeclaredId = True 15 | Attribute VB_Exposed = False 16 | Option Explicit 17 | 18 | Private Sub UserForm_Initialize() 19 | LoadSettings 20 | Me.Top = Application.Top + 110 21 | Me.Left = Application.Left + 25 22 | Me.Height = 322 23 | Me.Width = 256 24 | TextBoxChooseColor.Top = checkboxTransp.Top 25 | LabelChooseColor.Left = checkboxTransp.Left 26 | TextBoxChooseColor.Left = LabelChooseColor.Left + LabelChooseColor.Width 27 | LabelChooseColor.Top = TextBoxChooseColor.Top + Round(TextBoxChooseColor.Height - LabelChooseColor.Height) / 2 28 | ShowAcceleratorTip Me.ButtonRun 29 | ShowAcceleratorTip Me.ButtonCancel 30 | 31 | #If Mac Then 32 | ResizeUserForm Me 33 | #End If 34 | End Sub 35 | 36 | Private Sub UserForm_Activate() 37 | #If Mac Then 38 | MacEnableAccelerators Me 39 | #End If 40 | End Sub 41 | 42 | Private Sub LoadSettings() 43 | ComboBoxLaTexEngine.List = GetLaTexEngineDisplayList() 44 | ComboBoxLaTexEngine.ListIndex = GetITSetting("LaTeXEngineID", 0) 45 | TextBoxTempFolder.Text = GetTempPath() 46 | 'CheckBoxEMF.Value = CBool(GetITSetting("EMFoutput", False)) 47 | ComboBoxBitmapVector.List = GetBitmapVectorList() 48 | ComboBoxBitmapVector.ListIndex = GetITSetting("BitmapVector", 0) 49 | 50 | TextBoxLocalDPI.Text = GetITSetting("OutputDpi", "1200") 51 | textboxSize.Text = GetITSetting("PointSize", "20") 52 | checkboxTransp.value = CBool(GetITSetting("Transparent", True)) 53 | CheckBoxResetFormat.value = False 54 | TextBoxChooseColor.Text = GetITSetting("ColorHex", "000000") 55 | 56 | CheckBoxModifyEngine.value = False 57 | CheckBoxModifyTempFolder.value = False 58 | CheckBoxModifyBitmapVector.value = False 59 | CheckBoxModifyLocalDPI.value = False 60 | CheckBoxModifySize.value = False 61 | CheckBoxModifyPreserveSize.value = False 62 | CheckBoxModifyTransparency.value = False 63 | CheckBoxModifyResetFormat.value = False 64 | CheckBoxReplace.value = False 65 | Apply_CheckBoxModifyEngine 66 | Apply_CheckBoxModifyTempFolder 67 | Apply_CheckBoxModifyBitmapVector 68 | Apply_CheckBoxModifyLocalDPI 69 | Apply_CheckBoxModifySize 70 | Apply_CheckBoxModifyPreserveSize 71 | Apply_CheckBoxModifyTransparency 72 | Apply_CheckBoxModifyResetFormat 73 | Apply_CheckBoxReplace 74 | End Sub 75 | 76 | Public Sub ButtonRun_Click() 77 | BatchEditForm.Hide 78 | Dim Sel As Selection 79 | Set Sel = Application.ActiveWindow.Selection 80 | 81 | RegenerateSelectedDisplays Sel 82 | 83 | Unload BatchEditForm 84 | End Sub 85 | 86 | Public Sub ButtonCancel_Click() 87 | Unload BatchEditForm 88 | End Sub 89 | 90 | 91 | ' Enable/Disable Modifications 92 | Private Sub CheckBoxModifyEngine_Click() 93 | Apply_CheckBoxModifyEngine 94 | End Sub 95 | 96 | Private Sub CheckBoxModifyTempFolder_Click() 97 | Apply_CheckBoxModifyTempFolder 98 | End Sub 99 | 100 | Private Sub CheckBoxModifyBitmapVector_Click() 101 | Apply_CheckBoxModifyBitmapVector 102 | End Sub 103 | 104 | Private Sub CheckBoxModifyLocalDPI_Click() 105 | Apply_CheckBoxModifyLocalDPI 106 | End Sub 107 | 108 | Private Sub CheckBoxModifySize_Click() 109 | Apply_CheckBoxModifySize 110 | End Sub 111 | 112 | Private Sub CheckBoxModifyPreserveSize_Click() 113 | Apply_CheckBoxModifyPreserveSize 114 | End Sub 115 | 116 | Private Sub CheckBoxModifyTransparency_Click() 117 | Apply_CheckBoxModifyTransparency 118 | End Sub 119 | 120 | Private Sub CheckBoxModifyResetFormat_Click() 121 | Apply_CheckBoxModifyResetFormat 122 | End Sub 123 | 124 | Private Sub CheckBoxReplace_Click() 125 | Apply_CheckBoxReplace 126 | End Sub 127 | 128 | Private Sub Apply_CheckBoxModifyEngine() 129 | LabelEngine.Enabled = CheckBoxModifyEngine.value 130 | ComboBoxLaTexEngine.Enabled = CheckBoxModifyEngine.value 131 | End Sub 132 | 133 | Private Sub Apply_CheckBoxModifyTempFolder() 134 | LabelTempFolder.Enabled = CheckBoxModifyTempFolder.value 135 | TextBoxTempFolder.Enabled = CheckBoxModifyTempFolder.value 136 | End Sub 137 | 138 | Private Sub Apply_CheckBoxModifyBitmapVector() 139 | LabelOutput.Enabled = CheckBoxModifyBitmapVector.value 140 | ComboBoxBitmapVector.Enabled = CheckBoxModifyBitmapVector.value 141 | End Sub 142 | 143 | Private Sub Apply_CheckBoxModifyLocalDPI() 144 | LabelLocalDPI.Enabled = CheckBoxModifyLocalDPI.value 145 | TextBoxLocalDPI.Enabled = CheckBoxModifyLocalDPI.value 146 | LabelDPI.Enabled = CheckBoxModifyLocalDPI.value 147 | End Sub 148 | 149 | Private Sub Apply_CheckBoxModifySize() 150 | LabelSize.Enabled = CheckBoxModifySize.value 151 | textboxSize.Enabled = CheckBoxModifySize.value 152 | LabelPTS.Enabled = CheckBoxModifySize.value 153 | End Sub 154 | 155 | Private Sub Apply_CheckBoxModifyPreserveSize() 156 | CheckBoxForcePreserveSize.Enabled = CheckBoxModifyPreserveSize.value 157 | End Sub 158 | 159 | Private Sub Apply_CheckBoxModifyTransparency() 160 | checkboxTransp.Enabled = CheckBoxModifyTransparency.value 161 | TextBoxChooseColor.Enabled = CheckBoxModifyTransparency.value 162 | LabelChooseColor.Enabled = CheckBoxModifyTransparency.value 163 | End Sub 164 | 165 | Private Sub Apply_CheckBoxModifyResetFormat() 166 | CheckBoxResetFormat.Enabled = CheckBoxModifyResetFormat.value 167 | End Sub 168 | 169 | Private Sub Apply_CheckBoxReplace() 170 | LabelReplace.Enabled = CheckBoxReplace.value 171 | TextBoxFind.Enabled = CheckBoxReplace.value 172 | LabelWith.Enabled = CheckBoxReplace.value 173 | TextBoxReplacement.Enabled = CheckBoxReplace.value 174 | End Sub 175 | 176 | 177 | Private Sub ComboBoxBitmapVector_Change() 178 | Apply_BitmapVector_Change 179 | End Sub 180 | 181 | Private Sub Apply_BitmapVector_Change() 182 | If ComboBoxBitmapVector.ListIndex = 1 Then 183 | CheckBoxModifyLocalDPI.value = False 184 | CheckBoxModifyTransparency.value = False 185 | CheckBoxModifyLocalDPI.Enabled = False 186 | CheckBoxModifyTransparency.Enabled = True 187 | checkboxTransp.Visible = False 188 | checkboxTransp.value = True 189 | TextBoxChooseColor.Visible = True 190 | LabelChooseColor.Visible = True 191 | Else 192 | CheckBoxModifyLocalDPI.Enabled = True 193 | CheckBoxModifyTransparency.Enabled = True 194 | checkboxTransp.Visible = True 195 | TextBoxChooseColor.Visible = False 196 | LabelChooseColor.Visible = False 197 | End If 198 | Apply_CheckBoxModifyLocalDPI 199 | Apply_CheckBoxModifyTransparency 200 | End Sub 201 | 202 | Private Sub CheckBoxForcePreserveSize_Click() 203 | If CheckBoxForcePreserveSize.value = True Then 204 | CheckBoxModifySize.Enabled = False 205 | CheckBoxModifySize.value = False 206 | Else 207 | CheckBoxModifySize.Enabled = True 208 | End If 209 | Apply_CheckBoxModifySize 210 | End Sub 211 | 212 | -------------------------------------------------------------------------------- /BatchEditForm.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jonathan-LeRoux/IguanaTex/bf549383004d3443fa5600e21330b521b34049e5/BatchEditForm.frx -------------------------------------------------------------------------------- /CopyToClipboard.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "CopyToClipboard" 2 | Option Explicit 3 | 4 | #If VBA7 Then 5 | Declare PtrSafe Function GlobalUnlock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr 6 | Declare PtrSafe Function GlobalLock Lib "kernel32" (ByVal hMem As LongPtr) As LongPtr 7 | Declare PtrSafe Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, _ 8 | ByVal dwBytes As LongPtr) As LongPtr 9 | Declare PtrSafe Function CloseClipboard Lib "user32" () As Long 10 | Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hWnd As LongPtr) As LongPtr 11 | Declare PtrSafe Function EmptyClipboard Lib "user32" () As Long 12 | Declare PtrSafe Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, _ 13 | ByVal lpString2 As Any) As Long 14 | Declare PtrSafe Function SetClipboardData Lib "user32" (ByVal wFormat _ 15 | As Long, ByVal hMem As LongPtr) As LongPtr 16 | #Else 17 | Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long 18 | Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long 19 | Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long, _ 20 | ByVal dwBytes As Long) As Long 21 | Declare Function CloseClipboard Lib "User32" () As Long 22 | Declare Function OpenClipboard Lib "User32" (ByVal hwnd As Long) As Long 23 | Declare Function EmptyClipboard Lib "User32" () As Long 24 | Declare Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any, _ 25 | ByVal lpString2 As Any) As Long 26 | Declare Function SetClipboardData Lib "User32" (ByVal wFormat _ 27 | As Long, ByVal hMem As Long) As Long 28 | #End If 29 | 30 | Public Const GHND = &H42 31 | Public Const CF_TEXT = 1 32 | Public Const MAXSIZE = 4096 33 | 34 | Sub ClipBoard_SetData(MyString As String) 35 | 'PURPOSE: API function to copy text to clipboard 36 | 'SOURCE: www.msdn.microsoft.com/en-us/library/office/ff192913.aspx 37 | 38 | #If VBA7 Then 39 | Dim hGlobalMemory As LongPtr 40 | Dim lpGlobalMemory As LongPtr 41 | Dim hClipMemory As LongPtr 42 | #Else 43 | Dim hGlobalMemory As Long 44 | Dim lpGlobalMemory As Long 45 | Dim hClipMemory As Long 46 | #End If 47 | 48 | Dim x As Long 49 | 50 | 'Allocate moveable global memory 51 | hGlobalMemory = GlobalAlloc(GHND, Len(MyString) + 1) 52 | 53 | 'Lock the block to get a far pointer to this memory. 54 | lpGlobalMemory = GlobalLock(hGlobalMemory) 55 | 56 | 'Copy the string to this global memory. 57 | lpGlobalMemory = lstrcpy(lpGlobalMemory, MyString) 58 | 59 | 'Unlock the memory. 60 | If GlobalUnlock(hGlobalMemory) <> 0 Then 61 | MsgBox "Could not unlock memory location. Copy aborted." 62 | GoTo OutOfHere2 63 | End If 64 | 65 | 'Open the Clipboard to copy data to. 66 | If OpenClipboard(0&) = 0 Then 67 | MsgBox "Could not open the Clipboard. Copy aborted." 68 | Exit Sub 69 | End If 70 | 71 | 'Clear the Clipboard. 72 | x = EmptyClipboard() 73 | 74 | 'Copy the data to the Clipboard. 75 | hClipMemory = SetClipboardData(CF_TEXT, hGlobalMemory) 76 | 77 | OutOfHere2: 78 | If CloseClipboard() = 0 Then 79 | MsgBox "Could not close Clipboard." 80 | End If 81 | 82 | End Sub 83 | 84 | 85 | Function Clipboard(Optional StoreText As String) As String 86 | 87 | #If Mac Then 88 | ' In old forums (e.g., https://answers.microsoft.com/en-us/msoffice/forum/msoffice_excel-mso_mac-mso_mac2011/read-clipboard-contents-in-vba-excel-for-mac-not/4485ab02-dced-4bf2-853d-fc667f5782a8), 89 | ' people complain this doesn't work properly, but it seems to be working in my version of PowerPoint (Office365). 90 | 'Dim myData As DataObject 91 | 'Set myData = New DataObject 92 | 'myData.SetText StoreText 93 | 'myData.PutInClipboard 94 | Dim x As Variant 95 | 96 | Select Case True 97 | Case Len(StoreText) 98 | 'Write to the clipboard 99 | AppleScriptTask "IguanaTex.scpt", "MacSetClipboard", StoreText 100 | Case Else 101 | 'Read from the clipboard (no variable passed through) 102 | x = AppleScriptTask("IguanaTex.scpt", "MacSetClipboard", vbNullString) 103 | 'If IsNull(x) Then 104 | ' x = vbNullString 105 | 'End If 106 | Clipboard = x 107 | End Select 108 | #Else 109 | 'PURPOSE: Read/Write to Clipboard 110 | 'Source: ExcelHero.com (Daniel Ferry) 111 | ' https://stackoverflow.com/questions/14219455/excel-vba-code-to-copy-a-specific-string-to-clipboard/60896244#60896244 112 | 113 | Dim x As Variant 114 | 115 | 'Store as variant for 64-bit VBA support 116 | x = StoreText 117 | 118 | 'Create HTMLFile Object 119 | With CreateObject("htmlfile") 120 | With .parentWindow.clipboardData 121 | Select Case True 122 | Case Len(StoreText) 123 | 'Write to the clipboard 124 | .setData "text", x 125 | Case Else 126 | 'Read from the clipboard (no variable passed through) 127 | x = .GetData("text") 128 | If IsNull(x) Then 129 | x = vbNullString 130 | End If 131 | Clipboard = x 132 | End Select 133 | End With 134 | End With 135 | #End If 136 | End Function 137 | 138 | -------------------------------------------------------------------------------- /Defaults.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "Defaults" 2 | Option Explicit 3 | 4 | #If Mac Then 5 | Public Const DEFAULT_TEMP_DIR As String = vbNullString 6 | Public Const DEFAULT_TEX_EXE_PATH As String = "/Library/TeX/texbin/" 7 | Public Const DEFAULT_TEX_EXTRA_PATH As String = vbNullString 8 | Public Const DEFAULT_LIBGS As String = "/usr/local/lib/libgs.dylib" 9 | Public Const DEFAULT_VECTOR_OUTPUT_TYPE As String = "dvisvgm" 10 | Public Const DEFAULT_PICTURE_OUTPUT_TYPE As String = "PDF" 11 | Public Const DEFAULT_GS_COMMAND As String = "/usr/local/bin/gs" 12 | Public Const DEFAULT_IM_CONV As String = vbNullString 13 | Public Const DEFAULT_TEX2IMG_COMMAND As String = vbNullString 14 | Public Const DEFAULT_EDITOR As String = "open -b 'texstudio'" 15 | Public Const DEFAULT_ADDIN_FOLDER As String = "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/" 16 | Public Const DEFAULT_LATEXIT_METADATA_COMMAND As String = DEFAULT_ADDIN_FOLDER & "LaTeXiT-metadata-macos" 17 | Public Const NEWLINE As String = vbLf 18 | Public Const PathSep As String = "/" 19 | Public Const WrongPathSep As String = "\" 20 | 21 | #Else 22 | Public Const DEFAULT_TEMP_DIR As String = "c:\temp\" 23 | Public Const DEFAULT_TEX_EXE_PATH As String = vbNullString 24 | Public Const DEFAULT_TEX_EXTRA_PATH As String = vbNullString 25 | Public Const DEFAULT_LIBGS As String = vbNullString 26 | Public Const DEFAULT_VECTOR_OUTPUT_TYPE As String = "dvisvgm" 27 | Public Const DEFAULT_PICTURE_OUTPUT_TYPE As String = "PNG" 28 | Public Const DEFAULT_GS_COMMAND As String = "C:\Program Files (x86)\gs\gs9.15\bin\gswin32c.exe" 29 | Public Const DEFAULT_IM_CONV As String = "C:\Program Files\ImageMagick\magick.exe" 30 | Public Const DEFAULT_TEX2IMG_COMMAND As String = "%USERPROFILE%\Downloads\TeX2img\TeX2imgc.exe" 31 | Public Const DEFAULT_EDITOR As String = "C:\Program Files (x86)\TeXstudio\texstudio.exe" 32 | Public Const DEFAULT_LATEXIT_METADATA_COMMAND As String = "%USERPROFILE%\Downloads\LaTeXiT-metadata\LaTeXiT-metadata-win.exe" 33 | Public Const NEWLINE As String = vbCrLf 34 | Public Const PathSep As String = "\" 35 | Public Const WrongPathSep As String = "/" 36 | 37 | #End If 38 | 39 | Public Const IGUANATEX_VERSION As Integer = 162 40 | 41 | Public Const DEFAULT_LATEX_CODE As String = "\documentclass{article}" & NEWLINE & "\usepackage{amsmath}" & NEWLINE & "\pagestyle{empty}" & NEWLINE & _ 42 | "\begin{document}" & NEWLINE & NEWLINE & NEWLINE & NEWLINE & NEWLINE & "\end{document}" 43 | Public Const DEFAULT_LATEX_CODE_PRE As String = "\documentclass{article}" & NEWLINE & "\usepackage{amsmath}" & NEWLINE & "\pagestyle{empty}" & NEWLINE & _ 44 | "\begin{document}" & NEWLINE & NEWLINE 45 | Public Const DEFAULT_LATEX_CODE_POST As String = NEWLINE & NEWLINE & "\end{document}" 46 | -------------------------------------------------------------------------------- /Dictionary.cls: -------------------------------------------------------------------------------- 1 | VERSION 1.0 CLASS 2 | BEGIN 3 | MultiUse = -1 'True 4 | END 5 | Attribute VB_Name = "Dictionary" 6 | Attribute VB_GlobalNameSpace = False 7 | Attribute VB_Creatable = False 8 | Attribute VB_PredeclaredId = False 9 | Attribute VB_Exposed = False 10 | '' 11 | ' Dictionary v1.4.1 12 | ' (c) Tim Hall - https://github.com/timhall/VBA-Dictionary 13 | ' 14 | ' Drop-in replacement for Scripting.Dictionary on Mac 15 | ' 16 | ' @author: tim.hall.engr@gmail.com 17 | ' @license: MIT (http://www.opensource.org/licenses/mit-license.php 18 | ' 19 | ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' 20 | Option Explicit 21 | 22 | ' --------------------------------------------- ' 23 | ' Constants and Private Variables 24 | ' --------------------------------------------- ' 25 | 26 | #Const UseScriptingDictionaryIfAvailable = True 27 | 28 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 29 | 30 | ' dict_KeyValue 0: FormattedKey, 1: OriginalKey, 2: Value 31 | Private dict_pKeyValues As collection 32 | Private dict_pKeys() As Variant 33 | Private dict_pItems() As Variant 34 | Private dict_pObjectKeys As collection 35 | Private dict_pCompareMode As CompareMethod 36 | 37 | #Else 38 | 39 | Private dict_pDictionary As Object 40 | 41 | #End If 42 | 43 | ' --------------------------------------------- ' 44 | ' Types 45 | ' --------------------------------------------- ' 46 | 47 | Public Enum CompareMethod 48 | BinaryCompare = VBA.vbBinaryCompare 49 | TextCompare = VBA.vbTextCompare 50 | DatabaseCompare = VBA.vbDatabaseCompare 51 | End Enum 52 | 53 | ' --------------------------------------------- ' 54 | ' Properties 55 | ' --------------------------------------------- ' 56 | 57 | Public Property Get CompareMode() As CompareMethod 58 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 59 | CompareMode = dict_pCompareMode 60 | #Else 61 | CompareMode = dict_pDictionary.CompareMode 62 | #End If 63 | End Property 64 | Public Property Let CompareMode(value As CompareMethod) 65 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 66 | If Me.count > 0 Then 67 | ' Can't change CompareMode for Dictionary that contains data 68 | ' http://msdn.microsoft.com/en-us/library/office/gg278481(v=office.15).aspx 69 | Err.Raise 5 ' Invalid procedure call or argument 70 | End If 71 | 72 | dict_pCompareMode = value 73 | #Else 74 | dict_pDictionary.CompareMode = value 75 | #End If 76 | End Property 77 | 78 | Public Property Get count() As Long 79 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 80 | count = dict_pKeyValues.count 81 | #Else 82 | count = dict_pDictionary.count 83 | #End If 84 | End Property 85 | 86 | Public Property Get item(Key As Variant) As Variant 87 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 88 | Dim dict_KeyValue As Variant 89 | dict_KeyValue = dict_GetKeyValue(Key) 90 | 91 | If Not IsEmpty(dict_KeyValue) Then 92 | If VBA.IsObject(dict_KeyValue(2)) Then 93 | Set item = dict_KeyValue(2) 94 | Else 95 | item = dict_KeyValue(2) 96 | End If 97 | Else 98 | ' Not found -> Returns Empty 99 | End If 100 | #Else 101 | If VBA.IsObject(dict_pDictionary.item(Key)) Then 102 | Set item = dict_pDictionary.item(Key) 103 | Else 104 | item = dict_pDictionary.item(Key) 105 | End If 106 | #End If 107 | End Property 108 | Public Property Let item(Key As Variant, value As Variant) 109 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 110 | If Me.Exists(Key) Then 111 | dict_ReplaceKeyValue dict_GetKeyValue(Key), Key, value 112 | Else 113 | dict_AddKeyValue Key, value 114 | End If 115 | #Else 116 | dict_pDictionary.item(Key) = value 117 | #End If 118 | End Property 119 | Public Property Set item(Key As Variant, value As Variant) 120 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 121 | If Me.Exists(Key) Then 122 | dict_ReplaceKeyValue dict_GetKeyValue(Key), Key, value 123 | Else 124 | dict_AddKeyValue Key, value 125 | End If 126 | #Else 127 | Set dict_pDictionary.item(Key) = value 128 | #End If 129 | End Property 130 | 131 | Public Property Let Key(Previous As Variant, Updated As Variant) 132 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 133 | Dim dict_KeyValue As Variant 134 | dict_KeyValue = dict_GetKeyValue(Previous) 135 | 136 | If Not VBA.IsEmpty(dict_KeyValue) Then 137 | dict_ReplaceKeyValue dict_KeyValue, Updated, dict_KeyValue(2) 138 | End If 139 | #Else 140 | dict_pDictionary.Key(Previous) = Updated 141 | #End If 142 | End Property 143 | 144 | ' ============================================= ' 145 | ' Public Methods 146 | ' ============================================= ' 147 | 148 | '' 149 | ' Add an item with the given key 150 | ' 151 | ' @param {Variant} Key 152 | ' @param {Variant} Item 153 | ' --------------------------------------------- ' 154 | Public Sub Add(Key As Variant, item As Variant) 155 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 156 | If Not Me.Exists(Key) Then 157 | dict_AddKeyValue Key, item 158 | Else 159 | ' This key is already associated with an element of this collection 160 | Err.Raise 457 161 | End If 162 | #Else 163 | dict_pDictionary.Add Key, item 164 | #End If 165 | End Sub 166 | 167 | '' 168 | ' Check if an item exists for the given key 169 | ' 170 | ' @param {Variant} Key 171 | ' @return {Boolean} 172 | ' --------------------------------------------- ' 173 | Public Function Exists(Key As Variant) As Boolean 174 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 175 | Exists = Not IsEmpty(dict_GetKeyValue(Key)) 176 | #Else 177 | Exists = dict_pDictionary.Exists(Key) 178 | #End If 179 | End Function 180 | 181 | '' 182 | ' Get an array of all items 183 | ' 184 | ' @return {Variant} 185 | ' --------------------------------------------- ' 186 | Public Function items() As Variant 187 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 188 | If Me.count > 0 Then 189 | items = dict_pItems 190 | Else 191 | ' Split("") creates initialized empty array that matches Dictionary Keys and Items 192 | items = VBA.Split("") 193 | End If 194 | #Else 195 | items = dict_pDictionary.items 196 | #End If 197 | End Function 198 | 199 | '' 200 | ' Get an array of all keys 201 | ' 202 | ' @return {Variant} 203 | ' --------------------------------------------- ' 204 | Public Function Keys() As Variant 205 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 206 | If Me.count > 0 Then 207 | Keys = dict_pKeys 208 | Else 209 | ' Split("") creates initialized empty array that matches Dictionary Keys and Items 210 | Keys = VBA.Split("") 211 | End If 212 | #Else 213 | Keys = dict_pDictionary.Keys 214 | #End If 215 | End Function 216 | 217 | '' 218 | ' Remove an item for the given key 219 | ' 220 | ' @param {Variant} Key 221 | ' --------------------------------------------- ' 222 | Public Sub Remove(Key As Variant) 223 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 224 | Dim dict_KeyValue As Variant 225 | dict_KeyValue = dict_GetKeyValue(Key) 226 | 227 | If Not VBA.IsEmpty(dict_KeyValue) Then 228 | dict_RemoveKeyValue dict_KeyValue 229 | Else 230 | ' Application-defined or object-defined error 231 | Err.Raise 32811 232 | End If 233 | #Else 234 | dict_pDictionary.Remove Key 235 | #End If 236 | End Sub 237 | 238 | '' 239 | ' Remove all items 240 | ' --------------------------------------------- ' 241 | Public Sub RemoveAll() 242 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 243 | Set dict_pKeyValues = New collection 244 | 245 | Erase dict_pKeys 246 | Erase dict_pItems 247 | #Else 248 | dict_pDictionary.RemoveAll 249 | #End If 250 | End Sub 251 | 252 | ' ============================================= ' 253 | ' Private Functions 254 | ' ============================================= ' 255 | 256 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 257 | 258 | Private Function dict_GetKeyValue(dict_Key As Variant) As Variant 259 | On Error Resume Next 260 | dict_GetKeyValue = dict_pKeyValues(dict_GetFormattedKey(dict_Key)) 261 | Err.Clear 262 | End Function 263 | 264 | Private Sub dict_AddKeyValue(dict_Key As Variant, dict_Value As Variant, Optional dict_Index As Long = -1) 265 | If Me.count = 0 Then 266 | ReDim dict_pKeys(0 To 0) 267 | ReDim dict_pItems(0 To 0) 268 | Else 269 | ReDim Preserve dict_pKeys(0 To UBound(dict_pKeys) + 1) 270 | ReDim Preserve dict_pItems(0 To UBound(dict_pItems) + 1) 271 | End If 272 | 273 | Dim dict_FormattedKey As String 274 | dict_FormattedKey = dict_GetFormattedKey(dict_Key) 275 | 276 | If dict_Index >= 0 And dict_Index < dict_pKeyValues.count Then 277 | ' Shift keys/items after + including index into empty last slot 278 | Dim dict_i As Long 279 | For dict_i = UBound(dict_pKeys) To dict_Index + 1 Step -1 280 | dict_pKeys(dict_i) = dict_pKeys(dict_i - 1) 281 | If VBA.IsObject(dict_pItems(dict_i - 1)) Then 282 | Set dict_pItems(dict_i) = dict_pItems(dict_i - 1) 283 | Else 284 | dict_pItems(dict_i) = dict_pItems(dict_i - 1) 285 | End If 286 | Next dict_i 287 | 288 | ' Add key/item at index 289 | dict_pKeys(dict_Index) = dict_Key 290 | If VBA.IsObject(dict_Value) Then 291 | Set dict_pItems(dict_Index) = dict_Value 292 | Else 293 | dict_pItems(dict_Index) = dict_Value 294 | End If 295 | 296 | ' Add key-value at proper index 297 | dict_pKeyValues.Add Array(dict_FormattedKey, dict_Key, dict_Value), dict_FormattedKey, before:=dict_Index + 1 298 | Else 299 | ' Add key-value as last item 300 | If VBA.IsObject(dict_Key) Then 301 | Set dict_pKeys(UBound(dict_pKeys)) = dict_Key 302 | Else 303 | dict_pKeys(UBound(dict_pKeys)) = dict_Key 304 | End If 305 | If VBA.IsObject(dict_Value) Then 306 | Set dict_pItems(UBound(dict_pItems)) = dict_Value 307 | Else 308 | dict_pItems(UBound(dict_pItems)) = dict_Value 309 | End If 310 | 311 | dict_pKeyValues.Add Array(dict_FormattedKey, dict_Key, dict_Value), dict_FormattedKey 312 | End If 313 | End Sub 314 | 315 | Private Sub dict_ReplaceKeyValue(dict_KeyValue As Variant, dict_Key As Variant, dict_Value As Variant) 316 | Dim dict_Index As Long 317 | Dim dict_i As Integer 318 | 319 | dict_Index = dict_GetKeyIndex(dict_KeyValue(1)) 320 | 321 | ' Remove existing dict_Value 322 | dict_RemoveKeyValue dict_KeyValue, dict_Index 323 | 324 | ' Add new dict_Key dict_Value back 325 | dict_AddKeyValue dict_Key, dict_Value, dict_Index 326 | End Sub 327 | 328 | Private Sub dict_RemoveKeyValue(dict_KeyValue As Variant, Optional ByVal dict_Index As Long = -1) 329 | Dim dict_i As Long 330 | If dict_Index = -1 Then 331 | dict_Index = dict_GetKeyIndex(dict_KeyValue(1)) 332 | End If 333 | 334 | If dict_Index >= 0 And dict_Index <= UBound(dict_pKeys) Then 335 | ' Shift keys/items after index down 336 | For dict_i = dict_Index To UBound(dict_pKeys) - 1 337 | dict_pKeys(dict_i) = dict_pKeys(dict_i + 1) 338 | 339 | If VBA.IsObject(dict_pItems(dict_i + 1)) Then 340 | Set dict_pItems(dict_i) = dict_pItems(dict_i + 1) 341 | Else 342 | dict_pItems(dict_i) = dict_pItems(dict_i + 1) 343 | End If 344 | Next dict_i 345 | 346 | ' Resize keys/items to remove empty slot 347 | If UBound(dict_pKeys) = 0 Then 348 | Erase dict_pKeys 349 | Erase dict_pItems 350 | Else 351 | ReDim Preserve dict_pKeys(0 To UBound(dict_pKeys) - 1) 352 | ReDim Preserve dict_pItems(0 To UBound(dict_pItems) - 1) 353 | End If 354 | End If 355 | 356 | dict_pKeyValues.Remove dict_KeyValue(0) 357 | dict_RemoveObjectKey dict_KeyValue(1) 358 | End Sub 359 | 360 | Private Function dict_GetFormattedKey(dict_Key As Variant) As String 361 | If VBA.IsObject(dict_Key) Then 362 | dict_GetFormattedKey = dict_GetObjectKey(dict_Key) 363 | ElseIf VarType(dict_Key) = VBA.vbBoolean Then 364 | dict_GetFormattedKey = IIf(dict_Key, "-1__-1", "0__0") 365 | ElseIf VarType(dict_Key) = VBA.vbString Then 366 | dict_GetFormattedKey = dict_Key 367 | 368 | If Me.CompareMode = CompareMethod.BinaryCompare Then 369 | ' Collection does not have method of setting key comparison 370 | ' So case-sensitive keys aren't supported by default 371 | ' -> Approach: Append lowercase characters to original key 372 | ' AbC -> AbC___b_, abc -> abc__abc, ABC -> ABC_____ 373 | Dim dict_Lowercase As String 374 | dict_Lowercase = "" 375 | 376 | Dim dict_i As Integer 377 | Dim dict_Char As String 378 | Dim dict_Ascii As Integer 379 | For dict_i = 1 To VBA.Len(dict_GetFormattedKey) 380 | dict_Char = VBA.Mid$(dict_GetFormattedKey, dict_i, 1) 381 | dict_Ascii = VBA.Asc(dict_Char) 382 | If dict_Ascii >= 97 And dict_Ascii <= 122 Then 383 | dict_Lowercase = dict_Lowercase & dict_Char 384 | Else 385 | dict_Lowercase = dict_Lowercase & "_" 386 | End If 387 | Next dict_i 388 | 389 | If dict_Lowercase <> "" Then 390 | dict_GetFormattedKey = dict_GetFormattedKey & "__" & dict_Lowercase 391 | End If 392 | End If 393 | Else 394 | ' For numbers, add duplicate to distinguish from strings 395 | ' -> 123 -> "123__123" 396 | ' "123" -> "123" 397 | dict_GetFormattedKey = VBA.CStr(dict_Key) & "__" & CStr(dict_Key) 398 | End If 399 | End Function 400 | 401 | Private Function dict_GetObjectKey(dict_ObjKey As Variant) As String 402 | Dim dict_i As Integer 403 | For dict_i = 1 To dict_pObjectKeys.count 404 | If dict_pObjectKeys.item(dict_i) Is dict_ObjKey Then 405 | dict_GetObjectKey = "__object__" & dict_i 406 | Exit Function 407 | End If 408 | Next dict_i 409 | 410 | dict_pObjectKeys.Add dict_ObjKey 411 | dict_GetObjectKey = "__object__" & dict_pObjectKeys.count 412 | End Function 413 | 414 | Private Sub dict_RemoveObjectKey(dict_ObjKey As Variant) 415 | Dim dict_i As Integer 416 | For dict_i = 1 To dict_pObjectKeys.count 417 | If dict_pObjectKeys.item(dict_i) Is dict_ObjKey Then 418 | dict_pObjectKeys.Remove dict_i 419 | Exit Sub 420 | End If 421 | Next dict_i 422 | End Sub 423 | 424 | Private Function dict_GetKeyIndex(dict_Key As Variant) As Long 425 | Dim dict_i As Long 426 | For dict_i = 0 To UBound(dict_pKeys) 427 | If VBA.IsObject(dict_pKeys(dict_i)) And VBA.IsObject(dict_Key) Then 428 | If dict_pKeys(dict_i) Is dict_Key Then 429 | dict_GetKeyIndex = dict_i 430 | Exit For 431 | End If 432 | ElseIf VBA.IsObject(dict_pKeys(dict_i)) Or VBA.IsObject(dict_Key) Then 433 | ' Both need to be objects to check equality, skip 434 | ElseIf dict_pKeys(dict_i) = dict_Key Then 435 | dict_GetKeyIndex = dict_i 436 | Exit For 437 | End If 438 | Next dict_i 439 | End Function 440 | 441 | #End If 442 | 443 | Private Sub Class_Initialize() 444 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 445 | Set dict_pKeyValues = New collection 446 | 447 | Erase dict_pKeys 448 | Erase dict_pItems 449 | Set dict_pObjectKeys = New collection 450 | #Else 451 | Set dict_pDictionary = CreateObject("Scripting.Dictionary") 452 | #End If 453 | End Sub 454 | 455 | Private Sub Class_Terminate() 456 | #If Mac Or Not UseScriptingDictionaryIfAvailable Then 457 | Set dict_pKeyValues = Nothing 458 | Set dict_pObjectKeys = Nothing 459 | #Else 460 | Set dict_pDictionary = Nothing 461 | #End If 462 | End Sub 463 | 464 | 465 | -------------------------------------------------------------------------------- /ErrorForm.frm: -------------------------------------------------------------------------------- 1 | VERSION 5.00 2 | Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} ErrorForm 3 | Caption = "Error while running process" 4 | ClientHeight = 1848 5 | ClientLeft = 156 6 | ClientTop = 612 7 | ClientWidth = 10068 8 | OleObjectBlob = "ErrorForm.frx":0000 9 | StartUpPosition = 1 'CenterOwner 10 | End 11 | Attribute VB_Name = "ErrorForm" 12 | Attribute VB_GlobalNameSpace = False 13 | Attribute VB_Creatable = False 14 | Attribute VB_PredeclaredId = True 15 | Attribute VB_Exposed = False 16 | Option Explicit 17 | 18 | Private Sub UserForm_Initialize() 19 | Me.Top = Application.Top + 110 20 | Me.Left = Application.Left + 25 21 | ShowAcceleratorTip Me.CopyCommandButton 22 | ShowAcceleratorTip Me.CloseErrorButton 23 | 24 | ' Me.Height = 180 25 | ' Me.Width = 344 26 | ' #If Mac Then 27 | ' ResizeUserForm Me 28 | ' #End If 29 | End Sub 30 | 31 | Private Sub UserForm_Activate() 32 | Dim spacing As Long 33 | spacing = 8 34 | 35 | Me.Height = 180 36 | Me.Width = 344 37 | 38 | Dim LabelCommand As String 39 | Dim ErrorMessage As String 40 | LabelCommand = Me.LabelCommand.Caption 41 | Me.LabelCommand.Caption = vbNullString 42 | ErrorMessage = Me.LabelError.Caption 43 | Me.LabelError.Caption = vbNullString 44 | 45 | With Me.LabelError 46 | .AutoSize = True 47 | .WordWrap = True 48 | .Width = 324 49 | Me.LabelError.Caption = ErrorMessage 50 | .AutoSize = False 51 | .Height = .Height + 2 52 | .Width = 324 53 | End With 54 | With Me.LabelCommand 55 | .AutoSize = True 56 | .WordWrap = True 57 | .Width = 252 58 | Me.LabelCommand.Caption = LabelCommand 59 | .AutoSize = False 60 | .Height = .Height + 2 61 | .Width = 252 62 | End With 63 | 64 | If Me.LabelError.Caption = vbNullString Then 65 | Me.LabelError.Height = 0 66 | Me.LabelError.Top = 0 67 | End If 68 | 69 | Me.LabelLastCommandPrompt.Top = Me.LabelError.Top + Me.LabelError.Height + spacing 70 | Me.LabelCommand.Top = Me.LabelLastCommandPrompt.Top + Me.LabelLastCommandPrompt.Height + spacing / 2 71 | Me.CopyCommandButton.Top = Me.LabelCommand.Top + (Me.LabelCommand.Height - 2) / 2 - Me.CopyCommandButton.Height / 2 72 | Me.CloseErrorButton.Top = Me.LabelCommand.Top + Me.LabelCommand.Height + spacing 73 | Me.Height = Me.CloseErrorButton.Top + Me.CloseErrorButton.Height + spacing + 22 74 | 75 | #If Mac Then 76 | ResizeUserForm Me 77 | MacEnableAccelerators Me 78 | #End If 79 | End Sub 80 | 81 | Sub CloseErrorButton_Click() 82 | Me.Hide 83 | End Sub 84 | 85 | Sub CopyCommandButton_Click() 86 | Clipboard Me.LabelCommand.Caption 87 | End Sub 88 | 89 | Private Sub Userform_QueryClose(Cancel As Integer, CloseMode As Integer) 90 | If CloseMode = vbFormControlMenu Then Cancel = True 91 | End Sub 92 | -------------------------------------------------------------------------------- /ErrorForm.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jonathan-LeRoux/IguanaTex/bf549383004d3443fa5600e21330b521b34049e5/ErrorForm.frx -------------------------------------------------------------------------------- /ExportVBA.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "ExportVBA" 2 | Option Explicit 3 | ' Modified from https://gist.github.com/steve-jansen/7589478 to work in PowerPoint 4 | ' 5 | ' PowerPoint macro to export all VBA source code in this project to text files for proper source control versioning 6 | ' Requires enabling the PowerPoint setting in Options/Trust Center/Trust Center Settings/Macro Settings/Trust access to the VBA project object model 7 | Public Sub ExportVisualBasicCode() 8 | Const Module As Long = 1 9 | Const ClassModule As Long = 2 10 | Const form As Long = 3 11 | Const Document As Long = 100 12 | Const Padding As Long = 24 13 | 14 | Dim VBComponent As Object 15 | Dim count As Integer 16 | Dim path As String 17 | Dim directory As String 18 | Dim Extension As String 19 | #If Mac Then 20 | Dim fs As New MacFileSystemObject 21 | #Else 22 | Dim fs As New FileSystemObject 23 | #End If 24 | 25 | Dim MyPath As String 26 | MyPath = ActivePresentation.FullName 27 | directory = Left$(MyPath, InStrRev(MyPath, ".") - 1) & "_VBA" 28 | count = 0 29 | 30 | If Not fs.FolderExists(directory) Then 31 | fs.CreateFolder directory 32 | End If 33 | Set fs = Nothing 34 | 35 | For Each VBComponent In ActivePresentation.VBProject.VBComponents 36 | Select Case VBComponent.Type 37 | Case ClassModule, Document 38 | Extension = ".cls" 39 | Case form 40 | Extension = ".frm" 41 | Case Module 42 | Extension = ".bas" 43 | Case Else 44 | Extension = ".txt" 45 | End Select 46 | 47 | 48 | On Error Resume Next 49 | Err.Clear 50 | 51 | path = directory & PathSep & VBComponent.Name & Extension 52 | VBComponent.Export path 53 | 54 | If Err.Number <> 0 Then 55 | MsgBox "Failed to export " & VBComponent.Name & " to " & path, vbCritical 56 | Else 57 | count = count + 1 58 | Debug.Print "Exported " & Left$(VBComponent.Name & ":" & Space(Padding), Padding) & path 59 | End If 60 | 61 | On Error GoTo 0 62 | Next 63 | 64 | MsgBox "Successfully exported " & CStr(count) & " VBA files to " & directory 65 | 66 | End Sub 67 | -------------------------------------------------------------------------------- /ExternalEditorForm.frm: -------------------------------------------------------------------------------- 1 | VERSION 5.00 2 | Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} ExternalEditorForm 3 | Caption = "External Editor" 4 | ClientHeight = 2688 5 | ClientLeft = 84 6 | ClientTop = 396 7 | ClientWidth = 5232 8 | OleObjectBlob = "ExternalEditorForm.frx":0000 9 | StartUpPosition = 1 'CenterOwner 10 | End 11 | Attribute VB_Name = "ExternalEditorForm" 12 | Attribute VB_GlobalNameSpace = False 13 | Attribute VB_Creatable = False 14 | Attribute VB_PredeclaredId = True 15 | Attribute VB_Exposed = False 16 | Option Explicit 17 | Private Sub UserForm_Initialize() 18 | Me.Top = Application.Top + 110 19 | Me.Left = Application.Left + 25 20 | Me.Height = 158 21 | Me.Width = 270 22 | ShowAcceleratorTip Me.CmdButtonGenerate 23 | ShowAcceleratorTip Me.CmdButtonReload 24 | ShowAcceleratorTip Me.CmdButtonCancel 25 | #If Mac Then 26 | ResizeUserForm Me 27 | #End If 28 | End Sub 29 | 30 | Private Sub UserForm_Activate() 31 | #If Mac Then 32 | MacEnableAccelerators Me 33 | #End If 34 | End Sub 35 | 36 | Sub CmdButtonCancel_Click() 37 | Unload ExternalEditorForm 38 | End Sub 39 | 40 | Private Sub LoadTextIntoLatexForm() 41 | Dim SelStartPos As Long 42 | SelStartPos = LatexForm.TextWindow1.SelStart 43 | 44 | Dim TempPath As String 45 | TempPath = CleanPath(LatexForm.TextBoxTempFolder.Text) 46 | 47 | LatexForm.TextWindow1.Text = ReadAll(TempPath & "ext_" & DefaultFilePrefix & ".tex") 48 | 49 | Unload ExternalEditorForm 50 | LatexForm.TextWindow1.SetFocus 51 | If SelStartPos < Len(LatexForm.TextWindow1.Text) Then 52 | LatexForm.TextWindow1.SelStart = SelStartPos 53 | End If 54 | 55 | End Sub 56 | 57 | Sub CmdButtonReload_Click() 58 | LoadTextIntoLatexForm 59 | LatexForm.Hide 60 | LatexForm.Show vbModal 61 | End Sub 62 | 63 | Sub CmdButtonGenerate_Click() 64 | LoadTextIntoLatexForm 65 | DoEvents 66 | LatexForm.ButtonRun_Click 67 | End Sub 68 | 69 | Public Sub LaunchExternalEditor(TempPath As String, LatexCode As String) 70 | ' Put the temporary path in the right format and test if it is writable 71 | TempPath = CleanPath(TempPath) 72 | If Not IsPathWritable(TempPath) Then Exit Sub 73 | 74 | Dim FilePrefix As String 75 | FilePrefix = "ext_" & DefaultFilePrefix 76 | 77 | ' Write latex to a temp file 78 | WriteToFile TempPath, FilePrefix, ".tex", LatexCode 79 | 80 | ' Launch external editor 81 | On Error GoTo ShellError 82 | #If Mac Then 83 | AppleScriptTask "IguanaTex.scpt", "MacExecute", GetEditorPath() & " " & ShellEscape(TempPath & FilePrefix & ".tex") 84 | #Else 85 | Shell ShellEscape(GetEditorPath()) & " " & ShellEscape(TempPath & FilePrefix & ".tex"), vbNormalFocus 86 | #End If 87 | 88 | ' Show dialog form to reload from file or cancel 89 | Me.Show 90 | Exit Sub 91 | 92 | ShellError: 93 | MsgBox "Error Launching External Editor." & vbCrLf & _ 94 | Err.Description, vbOKOnly Or vbExclamation, _ 95 | "Error" 96 | Exit Sub 97 | End Sub 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /ExternalEditorForm.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jonathan-LeRoux/IguanaTex/bf549383004d3443fa5600e21330b521b34049e5/ExternalEditorForm.frx -------------------------------------------------------------------------------- /IconvWrapper.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "IconvWrapper" 2 | Option Explicit 3 | 4 | #If Mac Then 5 | Private Declare PtrSafe Function iconv_open Lib "/usr/lib/libiconv.dylib" (ByVal tocode As String, ByVal fromcode As String) As LongLong 6 | Private Declare PtrSafe Function iconv_close Lib "/usr/lib/libiconv.dylib" (ByVal cd As LongPtr) As Integer 7 | Private Declare PtrSafe Function iconv Lib "/usr/lib/libiconv.dylib" (ByVal cd As LongPtr, ByRef inbuf As LongPtr, ByRef inbytesleft As LongLong, ByRef outbuf As LongPtr, ByRef outbytesleft As LongLong) As LongLong 8 | 9 | Private Sub RunIconv(ByVal cd As LongPtr, ByRef inBytes() As Byte, ByRef outBytes() As Byte) 10 | Dim inbuf As LongPtr 11 | inbuf = VarPtr(inBytes(0)) 12 | Dim inbytesleft As LongLong 13 | inbytesleft = ArrayLength(inBytes) 14 | 15 | Dim outbuf As LongPtr 16 | outbuf = VarPtr(outBytes(0)) 17 | Dim outbytesleft As LongLong 18 | outbytesleft = ArrayLength(outBytes) 19 | 20 | While inbytesleft > 0 21 | If outbytesleft = 0 Then 22 | ReDim Preserve outBytes(UBound(outBytes) + CLng(inbytesleft) * 2) 23 | outbytesleft = CLng(inbytesleft) * 2 24 | End If 25 | If iconv(cd, inbuf, inbytesleft, outbuf, outbytesleft) = -1& Then GoTo Error 26 | Wend 27 | 28 | ReDim Preserve outBytes(UBound(outBytes) - CLng(outbytesleft)) 29 | Exit Sub 30 | 31 | Error: 32 | MsgBox "iconv failed, return empty string" 33 | ReDim outBytes(0) 34 | End Sub 35 | 36 | Public Function Utf8ToString(Utf8() As Byte) As String 37 | If ArrayLength(Utf8) = 0 Then 38 | Utf8ToString = "" 39 | Exit Function 40 | End If 41 | 42 | Dim utf16() As Byte 43 | ReDim utf16(UBound(Utf8) * 2 + 1) 44 | 45 | Dim cd As LongLong 46 | cd = iconv_open("utf-16le", "utf-8") 47 | If cd = -1& Then GoTo Error 48 | 49 | RunIconv cd, Utf8, utf16 50 | 51 | If iconv_close(cd) = -1 Then GoTo Error 52 | 53 | 54 | Utf8ToString = utf16 55 | Exit Function 56 | 57 | Error: 58 | MsgBox "iconv failed, return empty string" 59 | Utf8ToString = "" 60 | End Function 61 | 62 | Public Function StringToUtf8(Str As String) As Byte() 63 | Dim Utf8() As Byte 64 | 65 | If Len(Str) = 0 Then 66 | StringToUtf8 = Utf8 67 | Exit Function 68 | End If 69 | 70 | Dim utf16() As Byte 71 | utf16 = Str 72 | ' trim zero bytes 73 | ReDim Preserve utf16(Len(Str) * 2 - 1) 74 | 75 | ReDim Utf8(UBound(utf16)) 76 | 77 | Dim cd As LongLong 78 | cd = iconv_open("utf-8", "utf-16le") 79 | If cd = -1& Then GoTo Error 80 | 81 | RunIconv cd, utf16, Utf8 82 | 83 | If iconv_close(cd) = -1 Then GoTo Error 84 | 85 | StringToUtf8 = Utf8 86 | Exit Function 87 | 88 | Error: 89 | MsgBox "iconv failed, return empty string" 90 | ReDim Utf8(0) 91 | StringToUtf8 = Utf8 92 | End Function 93 | 94 | 95 | #End If 96 | -------------------------------------------------------------------------------- /IguanaTexHelper/.swift-format: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "indentation": { "spaces": 4 }, 4 | "lineBreakBeforeEachArgument": true 5 | } 6 | -------------------------------------------------------------------------------- /IguanaTexHelper/DEVELOP.md: -------------------------------------------------------------------------------- 1 | Run `make help` to see all available targets. 2 | 3 | ``` 4 | $ make help 5 | all Build the library 6 | clean Delete build artifacts 7 | format Format source files using `swift-format` 8 | help Print this help message 9 | install Install the library (requires root privileges) 10 | show-bin-path Print the binary output path 11 | 12 | ``` 13 | -------------------------------------------------------------------------------- /IguanaTexHelper/Makefile: -------------------------------------------------------------------------------- 1 | SWIFT := swift 2 | SWIFT_FORMAT := swift-format 3 | 4 | SWIFT_BUILD_FLAGS := -c release --arch arm64 --arch x86_64 5 | SWIFT_FORMAT_FLAGS := --configuration .swift-format --in-place 6 | 7 | SWIFT_BIN_PATH := $(shell $(SWIFT) build $(SWIFT_BUILD_FLAGS) --show-bin-path) 8 | ADDIN_DIR := /Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/ 9 | 10 | .PHONY: help all format install show-bin-path clean 11 | 12 | all: ## Build the library 13 | $(SWIFT) build $(SWIFT_BUILD_FLAGS) 14 | 15 | install: ## Install the library (requires root privileges) 16 | install -m755 '$(SWIFT_BIN_PATH)/libIguanaTexHelper.dylib' '$(DESTDIR)$(ADDIN_DIR)' 17 | 18 | show-bin-path: ## Print the binary output path 19 | @echo '$(SWIFT_BIN_PATH)' 20 | 21 | clean: ## Delete build artifacts 22 | $(SWIFT) package clean 23 | rm -rf .build 24 | 25 | format: ## Format source files using `swift-format` 26 | $(SWIFT_FORMAT) format $(SWIFT_FORMAT_FLAGS) --recursive Sources 27 | 28 | help: ## Print this help message 29 | @grep -E '^[a-zA-Z._-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 30 | -------------------------------------------------------------------------------- /IguanaTexHelper/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "InterposeKit", 6 | "repositoryURL": "https://github.com/steipete/InterposeKit.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "17853ad69961a5114e25c60c3ce7600feac0eabd", 10 | "version": "0.0.2" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /IguanaTexHelper/Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "IguanaTexHelper", 7 | platforms: [.macOS(.v10_13)], 8 | products: [ 9 | .library( 10 | name: "IguanaTexHelper", 11 | type: .dynamic, 12 | targets: ["IguanaTexHelper"]), 13 | ], 14 | dependencies: [ 15 | .package(url: "https://github.com/steipete/InterposeKit.git", from: "0.0.2"), 16 | ], 17 | targets: [ 18 | .target( 19 | name: "IguanaTexHelper", 20 | dependencies: ["InterposeKit"]), 21 | ] 22 | ) 23 | -------------------------------------------------------------------------------- /IguanaTexHelper/README.md: -------------------------------------------------------------------------------- 1 | # IguanaTexHelper 2 | 3 | ## Build 4 | 5 | ```sh 6 | swift build -c release 7 | ``` 8 | -------------------------------------------------------------------------------- /IguanaTexHelper/Sources/IguanaTexHelper/Keyboard.swift: -------------------------------------------------------------------------------- 1 | import AppKit 2 | import Carbon 3 | import InterposeKit 4 | 5 | public typealias RawCopyPasteHandler = @convention(c) ( 6 | _ formPtr: Int, _ keyCode: Int64, _ modifierFlags: Int64 7 | ) -> Void 8 | 9 | public typealias RawAcceleratorHandler = @convention(c) ( 10 | _ formPtr: Int, _ asciiCode: Int64 11 | ) -> Void 12 | 13 | public typealias CopyPasteHandler = ( 14 | _ keyCode: Int64, _ modifierFlags: Int64 15 | ) -> Void 16 | 17 | public typealias AcceleratorHandler = ( 18 | _ asciiCode: Int64 19 | ) -> Void 20 | 21 | @_cdecl("MacEnableCopyPaste") 22 | public func MacEnableCopyPaste( 23 | formPtr: Int, 24 | handler: @escaping RawCopyPasteHandler, 25 | _: Int64, 26 | _: Int64 27 | ) -> Int64 { 28 | guard let window = NSApp.mainWindow else { return 0 } 29 | guard let _ = interposer else { return 0 } 30 | window.copyPasteHandler = { (keyCode, modifierFlags) in 31 | handler(formPtr, keyCode, modifierFlags) 32 | } 33 | return 0 34 | } 35 | 36 | @_cdecl("MacEnableAccelerators") 37 | public func MacEnableAccelerators( 38 | formPtr: Int, 39 | handler: @escaping RawAcceleratorHandler, 40 | _: Int64, 41 | _: Int64 42 | ) -> Int64 { 43 | guard let window = NSApp.mainWindow else { return 0 } 44 | guard let _ = interposer else { return 0 } 45 | window.acceleratorHandler = { asciiCode in handler(formPtr, asciiCode) } 46 | return 0 47 | } 48 | 49 | let interposer = try? Interpose(NSApplication.self) { 50 | try $0.hook( 51 | #selector(NSWindow.sendEvent(_:)), 52 | methodSignature: (@convention(c) (AnyObject, Selector, NSEvent) -> Void).self, 53 | hookSignature: (@convention(block) (AnyObject, NSEvent) -> Void).self 54 | ) { store in 55 | { `self`, event in 56 | if let newEvent = handleEvent(event) { 57 | store.original(`self`, store.selector, newEvent) 58 | } 59 | } 60 | } 61 | } 62 | 63 | func handleEvent(_ event: NSEvent) -> NSEvent? { 64 | guard 65 | event.type == .keyDown, 66 | let targetWindow = event.window, 67 | let mainWindow = NSApp.mainWindow 68 | else { 69 | return event 70 | } 71 | 72 | let keyModifierFlags = event.modifierFlags.intersection(.deviceIndependentFlagsMask) 73 | 74 | // Custom handler for copy, paste, undo, redo... 75 | if let copyPasteHandler = targetWindow.copyPasteHandler { 76 | switch (keyModifierFlags, Int(event.keyCode)) { 77 | case (.command, kVK_ANSI_C), 78 | (.command, kVK_ANSI_V), 79 | (.command, kVK_ANSI_X), 80 | (.command, kVK_ANSI_A), 81 | (.command, kVK_ANSI_Z), 82 | ([.command, .shift], kVK_ANSI_Z): 83 | copyPasteHandler(Int64(event.keyCode), Int64(keyModifierFlags.rawValue)) 84 | return nil 85 | default: 86 | break 87 | } 88 | } 89 | 90 | // Disable command+* keys if accelerators are enabled 91 | if targetWindow.acceleratorHandler != nil && keyModifierFlags == [.command] { 92 | return nil 93 | } 94 | 95 | // Map control+command+* to accelerators 96 | if keyModifierFlags == [.control, .command], 97 | let char = event.charactersIgnoringModifiers?.first, 98 | char.isLetter && char.isASCII, 99 | let asciiCode = char.asciiValue, 100 | let acceleratorHandler = mainWindow.acceleratorHandler 101 | { 102 | acceleratorHandler(Int64(asciiCode)) 103 | return nil 104 | } 105 | 106 | return event 107 | } 108 | 109 | struct Keys { 110 | static var copyPasteHandler: UInt8 = 0 111 | static var acceleratorHandler: UInt8 = 0 112 | } 113 | 114 | extension NSWindow { 115 | fileprivate var copyPasteHandler: CopyPasteHandler? { 116 | get { objc_getAssociatedObject(self, &Keys.copyPasteHandler) as? CopyPasteHandler } 117 | set { 118 | objc_setAssociatedObject( 119 | self, 120 | &Keys.copyPasteHandler, 121 | newValue, 122 | .OBJC_ASSOCIATION_RETAIN_NONATOMIC 123 | ) 124 | } 125 | } 126 | fileprivate var acceleratorHandler: AcceleratorHandler? { 127 | get { objc_getAssociatedObject(self, &Keys.acceleratorHandler) as? AcceleratorHandler } 128 | set { 129 | objc_setAssociatedObject( 130 | self, 131 | &Keys.acceleratorHandler, 132 | newValue, 133 | .OBJC_ASSOCIATION_RETAIN_NONATOMIC 134 | ) 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /IguanaTexHelper/Sources/IguanaTexHelper/Resize.swift: -------------------------------------------------------------------------------- 1 | import AppKit 2 | 3 | public typealias ResizeHandler = @convention(c) (_ formPtr: Int, Double, Double, Double, Double) 4 | -> Void 5 | 6 | @_cdecl("MacMakeFormResizable") 7 | public func MacMakeFormResizable(formPtr: Int, handler: @escaping ResizeHandler, _: Int64, _: Int64) 8 | -> Int64 9 | { 10 | guard let window = NSApp.mainWindow else { return 0 } 11 | window.styleMask.insert(.resizable) 12 | 13 | NotificationCenter.default.addObserver( 14 | forName: NSWindow.didResizeNotification, 15 | object: window, 16 | queue: nil 17 | ) { _ in guard window.inLiveResize else { return } 18 | guard let screen = window.screen else { return } 19 | let frame = window.frame 20 | handler( 21 | formPtr, 22 | Double(frame.minX), 23 | Double(screen.frame.maxY - frame.maxY), 24 | Double(frame.width), 25 | Double(frame.height) 26 | ) 27 | } 28 | 29 | return 0 30 | } 31 | -------------------------------------------------------------------------------- /IguanaTexHelper/Sources/IguanaTexHelper/TextWindow.swift: -------------------------------------------------------------------------------- 1 | import AppKit 2 | 3 | class TextWindow: NSWindow { 4 | override var canBecomeKey: Bool { true } 5 | override var parent: NSWindow? { 6 | willSet { 7 | guard parent != nil else { return } 8 | NotificationCenter.default.removeObserver( 9 | self, 10 | name: NSWindow.didBecomeMainNotification, 11 | object: parent 12 | ) 13 | } 14 | didSet { 15 | guard parent != nil else { return } 16 | NotificationCenter.default.addObserver( 17 | self, 18 | selector: #selector(onParentDidBecomeMain(_:)), 19 | name: NSWindow.didBecomeMainNotification, 20 | object: parent 21 | ) 22 | } 23 | } 24 | 25 | weak var resizeTarget: AnyObject? = nil 26 | let scrollView: NSScrollView = NSScrollView() 27 | let textView: NSTextView = NSTextView() 28 | var wordWrap: Bool = true { didSet { setupWordWrap() } } 29 | 30 | init() { 31 | super.init( 32 | contentRect: NSZeroRect, 33 | styleMask: .borderless, 34 | backing: .buffered, 35 | defer: false 36 | ) 37 | setupViews() 38 | setupWordWrap() 39 | } 40 | 41 | func setupViews() { 42 | textView.allowsUndo = true 43 | textView.isRichText = false 44 | textView.font = NSFont.userFixedPitchFont(ofSize: 10) 45 | textView.isAutomaticDashSubstitutionEnabled = false 46 | textView.isAutomaticQuoteSubstitutionEnabled = false 47 | textView.maxSize = NSSize( 48 | width: CGFloat.greatestFiniteMagnitude, 49 | height: CGFloat.greatestFiniteMagnitude 50 | ) 51 | textView.isVerticallyResizable = true 52 | textView.isHorizontallyResizable = true 53 | textView.autoresizingMask = [.width, .height] 54 | 55 | scrollView.borderType = .bezelBorder 56 | scrollView.hasVerticalScroller = true 57 | scrollView.autohidesScrollers = true 58 | scrollView.autoresizingMask = [.width, .height] 59 | 60 | scrollView.documentView = textView 61 | self.contentView = scrollView 62 | self.initialFirstResponder = textView 63 | } 64 | 65 | func setupWordWrap() { 66 | scrollView.hasHorizontalScroller = wordWrap 67 | textView.textContainer?.containerSize = NSSize( 68 | width: wordWrap ? scrollView.contentSize.width : CGFloat.greatestFiniteMagnitude, 69 | height: CGFloat.greatestFiniteMagnitude 70 | ) 71 | textView.textContainer?.widthTracksTextView = wordWrap 72 | textView.sizeToFit() 73 | } 74 | 75 | @objc func onParentDidBecomeMain(_ notificaton: Notification) { 76 | self.orderFront(nil) 77 | } 78 | } 79 | 80 | var textWindows: [Int64: TextWindow] = [:] 81 | var lastHandle: Int64 = 0 82 | 83 | @_cdecl("TWInit") 84 | public func TWInit() -> Int64 { 85 | let handle = lastHandle + 1 86 | lastHandle += 1 87 | let window = TextWindow() 88 | window.isReleasedWhenClosed = false 89 | textWindows[handle] = window 90 | return handle 91 | } 92 | 93 | @_cdecl("TWTerm") 94 | public func TWTerm(_ handle: Int64, _: Int64, _: Int64, _: Int64) -> Int64 { 95 | guard let window = textWindows[handle] else { return 0 } 96 | window.close() 97 | textWindows[handle] = nil 98 | return 0 99 | } 100 | 101 | @_cdecl("TWShow") 102 | public func TWShow(_ handle: Int64, _: Int64, _: Int64, _: Int64) -> Int64 { 103 | guard let window = textWindows[handle] else { return 0 } 104 | guard let parent = NSApp.mainWindow else { return 0 } 105 | parent.addChildWindow(window, ordered: .above) 106 | return 0 107 | } 108 | 109 | @_cdecl("TWHide") 110 | public func TWHide(_ handle: Int64, _: Int64, _: Int64, _: Int64) -> Int64 { 111 | guard let window = textWindows[handle] else { return 0 } 112 | window.orderOut(nil) 113 | return 0 114 | } 115 | 116 | func getFocusedAccessibility(_ node: AnyObject) -> AnyObject? { 117 | let isAccessibilityFocusedSelector = #selector(NSAccessibilityProtocol.isAccessibilityFocused) 118 | let accessibilityChildrenSelector = #selector(NSAccessibilityProtocol.accessibilityChildren) 119 | 120 | let ref = _unsafeReferenceCast(node, to: NSAccessibilityProtocol.self) 121 | if ref.responds(to: isAccessibilityFocusedSelector) && ref.isAccessibilityFocused() { 122 | return node 123 | } 124 | 125 | if let children = ref.responds(to: accessibilityChildrenSelector) 126 | ? ref.accessibilityChildren() : nil 127 | { 128 | for child in children { 129 | if let result = getFocusedAccessibility(child as AnyObject) { 130 | return result 131 | } 132 | } 133 | } 134 | 135 | return nil 136 | } 137 | 138 | func getAccessibilityFrame(_ node: AnyObject) -> NSRect? { 139 | let accessibilityFrameSelector = #selector( 140 | NSAccessibilityProtocol.accessibilityFrame as (NSAccessibilityProtocol) -> () -> NSRect) 141 | guard node.responds(to: accessibilityFrameSelector) else { return nil } 142 | return _unsafeReferenceCast(node, to: NSAccessibilityProtocol.self).accessibilityFrame() 143 | } 144 | 145 | @_cdecl("TWSetResizeTarget") 146 | public func SetResizeTarget(_ handle: Int64, _: Int64, _: Int64, _: Int64) -> Int64 { 147 | guard let window = textWindows[handle] else { return 0 } 148 | guard let parent = NSApp.mainWindow else { return 0 } 149 | guard let target = getFocusedAccessibility(parent) else { return 0 } 150 | window.resizeTarget = target 151 | return 0 152 | } 153 | 154 | @_cdecl("TWResize") 155 | public func TWResize(_ handle: Int64, _: Int64, _: Int64, _: Int64) -> Int64 { 156 | guard let window = textWindows[handle] else { return 0 } 157 | guard let target = window.resizeTarget else { return 0 } 158 | guard let frame = getAccessibilityFrame(target) else { return 0 } 159 | window.setFrame(frame, display: true) 160 | return 0 161 | } 162 | 163 | @_cdecl("TWFocus") 164 | public func TWFocus(_ handle: Int64, _: Int64, _: Int64, _: Int64) -> Int64 { 165 | guard let window = textWindows[handle] else { return 0 } 166 | window.makeKey() 167 | return 0 168 | } 169 | 170 | @_cdecl("TWGetByteLength") 171 | public func TWGetByteLength(_ handle: Int64, _: Int64, _: Int64, _: Int64) -> Int64 { 172 | guard let window = textWindows[handle] else { return 0 } 173 | let string = window.textView.string as NSString 174 | return Int64(string.lengthOfBytes(using: String.Encoding.utf16LittleEndian.rawValue)) 175 | } 176 | 177 | @_cdecl("TWGetBytes") 178 | public func TWGetBytes(_ handle: Int64, buffer: UnsafeMutableRawPointer?, length: Int64, _: Int64) 179 | -> Int64 180 | { 181 | guard let window = textWindows[handle] else { return 0 } 182 | let string = window.textView.string as NSString 183 | var usedLength: Int = 0 184 | string.getBytes( 185 | buffer, 186 | maxLength: Int(length), 187 | usedLength: &usedLength, 188 | encoding: String.Encoding.utf16LittleEndian.rawValue, 189 | options: [], 190 | range: NSRange(location: 0, length: Int(length)), 191 | remaining: nil 192 | ) 193 | return Int64(usedLength) 194 | } 195 | 196 | @_cdecl("TWSetBytes") 197 | public func TWSetBytes(_ handle: Int64, buffer: UnsafeRawPointer?, length: Int64, _: Int64) -> Int64 198 | { 199 | guard let window = textWindows[handle] else { return 0 } 200 | if let buffer = buffer, 201 | let string = NSString( 202 | bytes: buffer, 203 | length: Int(length), 204 | encoding: String.Encoding.utf16LittleEndian.rawValue 205 | ) 206 | { 207 | window.textView.string = string as String 208 | } else { 209 | window.textView.string = "" 210 | } 211 | return 0 212 | } 213 | 214 | @_cdecl("TWGetSelStart") 215 | public func TWGetSelStart(_ handle: Int64, _: Int64, _: Int64, _: Int64) -> Int64 { 216 | guard let window = textWindows[handle] else { return 0 } 217 | return Int64(window.textView.selectedRange.location) 218 | } 219 | 220 | @_cdecl("TWSetSelStart") 221 | public func TWSetSelStart(_ handle: Int64, value: Int64, _: Int64, _: Int64) -> Int64 { 222 | guard let window = textWindows[handle] else { return 0 } 223 | window.textView.selectedRange = NSRange(location: Int(value), length: 0) 224 | return 0 225 | } 226 | 227 | @_cdecl("TWGetFontSize") 228 | public func TWGetFontSize(_ handle: Int64, _: Int64, _: Int64, _: Int64) -> Float64 { 229 | guard let window = textWindows[handle] else { return 0 } 230 | return Float64(window.textView.font?.pointSize ?? 0) 231 | } 232 | 233 | @_cdecl("TWSetFontSize") 234 | public func TWSetFontSize(_ handle: Int64, value: Float64, _: Int64, _: Int64) -> Int64 { 235 | guard let window = textWindows[handle] else { return 0 } 236 | window.textView.font = NSFont.userFixedPitchFont(ofSize: CGFloat(value)) 237 | return 0 238 | } 239 | 240 | @_cdecl("TWGetWordWrap") 241 | public func TWGetWordWrap(_ handle: Int64, _: Int64, _: Int64, _: Int64) -> Int64 { 242 | guard let window = textWindows[handle] else { return 0 } 243 | return window.wordWrap ? 1 : 0 244 | } 245 | 246 | @_cdecl("TWSetWordWrap") 247 | public func TWSetWordWrap(_ handle: Int64, value: Int64, _: Int64, _: Int64) -> Int64 { 248 | guard let window = textWindows[handle] else { return 0 } 249 | window.wordWrap = value != 0 250 | return 0 251 | } 252 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | Attribution 3.0 Unported 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR 10 | DAMAGES RESULTING FROM ITS USE. 11 | 12 | License 13 | 14 | THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE 15 | COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY 16 | COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS 17 | AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. 18 | 19 | BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE 20 | TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY 21 | BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS 22 | CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND 23 | CONDITIONS. 24 | 25 | 1. Definitions 26 | 27 | a. "Adaptation" means a work based upon the Work, or upon the Work and 28 | other pre-existing works, such as a translation, adaptation, 29 | derivative work, arrangement of music or other alterations of a 30 | literary or artistic work, or phonogram or performance and includes 31 | cinematographic adaptations or any other form in which the Work may be 32 | recast, transformed, or adapted including in any form recognizably 33 | derived from the original, except that a work that constitutes a 34 | Collection will not be considered an Adaptation for the purpose of 35 | this License. For the avoidance of doubt, where the Work is a musical 36 | work, performance or phonogram, the synchronization of the Work in 37 | timed-relation with a moving image ("synching") will be considered an 38 | Adaptation for the purpose of this License. 39 | b. "Collection" means a collection of literary or artistic works, such as 40 | encyclopedias and anthologies, or performances, phonograms or 41 | broadcasts, or other works or subject matter other than works listed 42 | in Section 1(f) below, which, by reason of the selection and 43 | arrangement of their contents, constitute intellectual creations, in 44 | which the Work is included in its entirety in unmodified form along 45 | with one or more other contributions, each constituting separate and 46 | independent works in themselves, which together are assembled into a 47 | collective whole. A work that constitutes a Collection will not be 48 | considered an Adaptation (as defined above) for the purposes of this 49 | License. 50 | c. "Distribute" means to make available to the public the original and 51 | copies of the Work or Adaptation, as appropriate, through sale or 52 | other transfer of ownership. 53 | d. "Licensor" means the individual, individuals, entity or entities that 54 | offer(s) the Work under the terms of this License. 55 | e. "Original Author" means, in the case of a literary or artistic work, 56 | the individual, individuals, entity or entities who created the Work 57 | or if no individual or entity can be identified, the publisher; and in 58 | addition (i) in the case of a performance the actors, singers, 59 | musicians, dancers, and other persons who act, sing, deliver, declaim, 60 | play in, interpret or otherwise perform literary or artistic works or 61 | expressions of folklore; (ii) in the case of a phonogram the producer 62 | being the person or legal entity who first fixes the sounds of a 63 | performance or other sounds; and, (iii) in the case of broadcasts, the 64 | organization that transmits the broadcast. 65 | f. "Work" means the literary and/or artistic work offered under the terms 66 | of this License including without limitation any production in the 67 | literary, scientific and artistic domain, whatever may be the mode or 68 | form of its expression including digital form, such as a book, 69 | pamphlet and other writing; a lecture, address, sermon or other work 70 | of the same nature; a dramatic or dramatico-musical work; a 71 | choreographic work or entertainment in dumb show; a musical 72 | composition with or without words; a cinematographic work to which are 73 | assimilated works expressed by a process analogous to cinematography; 74 | a work of drawing, painting, architecture, sculpture, engraving or 75 | lithography; a photographic work to which are assimilated works 76 | expressed by a process analogous to photography; a work of applied 77 | art; an illustration, map, plan, sketch or three-dimensional work 78 | relative to geography, topography, architecture or science; a 79 | performance; a broadcast; a phonogram; a compilation of data to the 80 | extent it is protected as a copyrightable work; or a work performed by 81 | a variety or circus performer to the extent it is not otherwise 82 | considered a literary or artistic work. 83 | g. "You" means an individual or entity exercising rights under this 84 | License who has not previously violated the terms of this License with 85 | respect to the Work, or who has received express permission from the 86 | Licensor to exercise rights under this License despite a previous 87 | violation. 88 | h. "Publicly Perform" means to perform public recitations of the Work and 89 | to communicate to the public those public recitations, by any means or 90 | process, including by wire or wireless means or public digital 91 | performances; to make available to the public Works in such a way that 92 | members of the public may access these Works from a place and at a 93 | place individually chosen by them; to perform the Work to the public 94 | by any means or process and the communication to the public of the 95 | performances of the Work, including by public digital performance; to 96 | broadcast and rebroadcast the Work by any means including signs, 97 | sounds or images. 98 | i. "Reproduce" means to make copies of the Work by any means including 99 | without limitation by sound or visual recordings and the right of 100 | fixation and reproducing fixations of the Work, including storage of a 101 | protected performance or phonogram in digital form or other electronic 102 | medium. 103 | 104 | 2. Fair Dealing Rights. Nothing in this License is intended to reduce, 105 | limit, or restrict any uses free from copyright or rights arising from 106 | limitations or exceptions that are provided for in connection with the 107 | copyright protection under copyright law or other applicable laws. 108 | 109 | 3. License Grant. Subject to the terms and conditions of this License, 110 | Licensor hereby grants You a worldwide, royalty-free, non-exclusive, 111 | perpetual (for the duration of the applicable copyright) license to 112 | exercise the rights in the Work as stated below: 113 | 114 | a. to Reproduce the Work, to incorporate the Work into one or more 115 | Collections, and to Reproduce the Work as incorporated in the 116 | Collections; 117 | b. to create and Reproduce Adaptations provided that any such Adaptation, 118 | including any translation in any medium, takes reasonable steps to 119 | clearly label, demarcate or otherwise identify that changes were made 120 | to the original Work. For example, a translation could be marked "The 121 | original work was translated from English to Spanish," or a 122 | modification could indicate "The original work has been modified."; 123 | c. to Distribute and Publicly Perform the Work including as incorporated 124 | in Collections; and, 125 | d. to Distribute and Publicly Perform Adaptations. 126 | e. For the avoidance of doubt: 127 | 128 | i. Non-waivable Compulsory License Schemes. In those jurisdictions in 129 | which the right to collect royalties through any statutory or 130 | compulsory licensing scheme cannot be waived, the Licensor 131 | reserves the exclusive right to collect such royalties for any 132 | exercise by You of the rights granted under this License; 133 | ii. Waivable Compulsory License Schemes. In those jurisdictions in 134 | which the right to collect royalties through any statutory or 135 | compulsory licensing scheme can be waived, the Licensor waives the 136 | exclusive right to collect such royalties for any exercise by You 137 | of the rights granted under this License; and, 138 | iii. Voluntary License Schemes. The Licensor waives the right to 139 | collect royalties, whether individually or, in the event that the 140 | Licensor is a member of a collecting society that administers 141 | voluntary licensing schemes, via that society, from any exercise 142 | by You of the rights granted under this License. 143 | 144 | The above rights may be exercised in all media and formats whether now 145 | known or hereafter devised. The above rights include the right to make 146 | such modifications as are technically necessary to exercise the rights in 147 | other media and formats. Subject to Section 8(f), all rights not expressly 148 | granted by Licensor are hereby reserved. 149 | 150 | 4. Restrictions. The license granted in Section 3 above is expressly made 151 | subject to and limited by the following restrictions: 152 | 153 | a. You may Distribute or Publicly Perform the Work only under the terms 154 | of this License. You must include a copy of, or the Uniform Resource 155 | Identifier (URI) for, this License with every copy of the Work You 156 | Distribute or Publicly Perform. You may not offer or impose any terms 157 | on the Work that restrict the terms of this License or the ability of 158 | the recipient of the Work to exercise the rights granted to that 159 | recipient under the terms of the License. You may not sublicense the 160 | Work. You must keep intact all notices that refer to this License and 161 | to the disclaimer of warranties with every copy of the Work You 162 | Distribute or Publicly Perform. When You Distribute or Publicly 163 | Perform the Work, You may not impose any effective technological 164 | measures on the Work that restrict the ability of a recipient of the 165 | Work from You to exercise the rights granted to that recipient under 166 | the terms of the License. This Section 4(a) applies to the Work as 167 | incorporated in a Collection, but this does not require the Collection 168 | apart from the Work itself to be made subject to the terms of this 169 | License. If You create a Collection, upon notice from any Licensor You 170 | must, to the extent practicable, remove from the Collection any credit 171 | as required by Section 4(b), as requested. If You create an 172 | Adaptation, upon notice from any Licensor You must, to the extent 173 | practicable, remove from the Adaptation any credit as required by 174 | Section 4(b), as requested. 175 | b. If You Distribute, or Publicly Perform the Work or any Adaptations or 176 | Collections, You must, unless a request has been made pursuant to 177 | Section 4(a), keep intact all copyright notices for the Work and 178 | provide, reasonable to the medium or means You are utilizing: (i) the 179 | name of the Original Author (or pseudonym, if applicable) if supplied, 180 | and/or if the Original Author and/or Licensor designate another party 181 | or parties (e.g., a sponsor institute, publishing entity, journal) for 182 | attribution ("Attribution Parties") in Licensor's copyright notice, 183 | terms of service or by other reasonable means, the name of such party 184 | or parties; (ii) the title of the Work if supplied; (iii) to the 185 | extent reasonably practicable, the URI, if any, that Licensor 186 | specifies to be associated with the Work, unless such URI does not 187 | refer to the copyright notice or licensing information for the Work; 188 | and (iv) , consistent with Section 3(b), in the case of an Adaptation, 189 | a credit identifying the use of the Work in the Adaptation (e.g., 190 | "French translation of the Work by Original Author," or "Screenplay 191 | based on original Work by Original Author"). The credit required by 192 | this Section 4 (b) may be implemented in any reasonable manner; 193 | provided, however, that in the case of a Adaptation or Collection, at 194 | a minimum such credit will appear, if a credit for all contributing 195 | authors of the Adaptation or Collection appears, then as part of these 196 | credits and in a manner at least as prominent as the credits for the 197 | other contributing authors. For the avoidance of doubt, You may only 198 | use the credit required by this Section for the purpose of attribution 199 | in the manner set out above and, by exercising Your rights under this 200 | License, You may not implicitly or explicitly assert or imply any 201 | connection with, sponsorship or endorsement by the Original Author, 202 | Licensor and/or Attribution Parties, as appropriate, of You or Your 203 | use of the Work, without the separate, express prior written 204 | permission of the Original Author, Licensor and/or Attribution 205 | Parties. 206 | c. Except as otherwise agreed in writing by the Licensor or as may be 207 | otherwise permitted by applicable law, if You Reproduce, Distribute or 208 | Publicly Perform the Work either by itself or as part of any 209 | Adaptations or Collections, You must not distort, mutilate, modify or 210 | take other derogatory action in relation to the Work which would be 211 | prejudicial to the Original Author's honor or reputation. Licensor 212 | agrees that in those jurisdictions (e.g. Japan), in which any exercise 213 | of the right granted in Section 3(b) of this License (the right to 214 | make Adaptations) would be deemed to be a distortion, mutilation, 215 | modification or other derogatory action prejudicial to the Original 216 | Author's honor and reputation, the Licensor will waive or not assert, 217 | as appropriate, this Section, to the fullest extent permitted by the 218 | applicable national law, to enable You to reasonably exercise Your 219 | right under Section 3(b) of this License (right to make Adaptations) 220 | but not otherwise. 221 | 222 | 5. Representations, Warranties and Disclaimer 223 | 224 | UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR 225 | OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY 226 | KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, 227 | INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, 228 | FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF 229 | LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, 230 | WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION 231 | OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. 232 | 233 | 6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE 234 | LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR 235 | ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES 236 | ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS 237 | BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 238 | 239 | 7. Termination 240 | 241 | a. This License and the rights granted hereunder will terminate 242 | automatically upon any breach by You of the terms of this License. 243 | Individuals or entities who have received Adaptations or Collections 244 | from You under this License, however, will not have their licenses 245 | terminated provided such individuals or entities remain in full 246 | compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will 247 | survive any termination of this License. 248 | b. Subject to the above terms and conditions, the license granted here is 249 | perpetual (for the duration of the applicable copyright in the Work). 250 | Notwithstanding the above, Licensor reserves the right to release the 251 | Work under different license terms or to stop distributing the Work at 252 | any time; provided, however that any such election will not serve to 253 | withdraw this License (or any other license that has been, or is 254 | required to be, granted under the terms of this License), and this 255 | License will continue in full force and effect unless terminated as 256 | stated above. 257 | 258 | 8. Miscellaneous 259 | 260 | a. Each time You Distribute or Publicly Perform the Work or a Collection, 261 | the Licensor offers to the recipient a license to the Work on the same 262 | terms and conditions as the license granted to You under this License. 263 | b. Each time You Distribute or Publicly Perform an Adaptation, Licensor 264 | offers to the recipient a license to the original Work on the same 265 | terms and conditions as the license granted to You under this License. 266 | c. If any provision of this License is invalid or unenforceable under 267 | applicable law, it shall not affect the validity or enforceability of 268 | the remainder of the terms of this License, and without further action 269 | by the parties to this agreement, such provision shall be reformed to 270 | the minimum extent necessary to make such provision valid and 271 | enforceable. 272 | d. No term or provision of this License shall be deemed waived and no 273 | breach consented to unless such waiver or consent shall be in writing 274 | and signed by the party to be charged with such waiver or consent. 275 | e. This License constitutes the entire agreement between the parties with 276 | respect to the Work licensed here. There are no understandings, 277 | agreements or representations with respect to the Work not specified 278 | here. Licensor shall not be bound by any additional provisions that 279 | may appear in any communication from You. This License may not be 280 | modified without the mutual written agreement of the Licensor and You. 281 | f. The rights granted under, and the subject matter referenced, in this 282 | License were drafted utilizing the terminology of the Berne Convention 283 | for the Protection of Literary and Artistic Works (as amended on 284 | September 28, 1979), the Rome Convention of 1961, the WIPO Copyright 285 | Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 286 | and the Universal Copyright Convention (as revised on July 24, 1971). 287 | These rights and subject matter take effect in the relevant 288 | jurisdiction in which the License terms are sought to be enforced 289 | according to the corresponding provisions of the implementation of 290 | those treaty provisions in the applicable national law. If the 291 | standard suite of rights granted under applicable copyright law 292 | includes additional rights not granted under this License, such 293 | additional rights are deemed to be included in the License; this 294 | License is not intended to restrict the license of any rights under 295 | applicable law. 296 | 297 | 298 | Creative Commons Notice 299 | 300 | Creative Commons is not a party to this License, and makes no warranty 301 | whatsoever in connection with the Work. Creative Commons will not be 302 | liable to You or any party on any legal theory for any damages 303 | whatsoever, including without limitation any general, special, 304 | incidental or consequential damages arising in connection to this 305 | license. Notwithstanding the foregoing two (2) sentences, if Creative 306 | Commons has expressly identified itself as the Licensor hereunder, it 307 | shall have all rights and obligations of Licensor. 308 | 309 | Except for the limited purpose of indicating to the public that the 310 | Work is licensed under the CCPL, Creative Commons does not authorize 311 | the use by either party of the trademark "Creative Commons" or any 312 | related trademark or logo of Creative Commons without the prior 313 | written consent of Creative Commons. Any permitted use will be in 314 | compliance with Creative Commons' then-current trademark usage 315 | guidelines, as may be published on its website or otherwise made 316 | available upon request from time to time. For the avoidance of doubt, 317 | this trademark restriction does not form part of this License. 318 | 319 | Creative Commons may be contacted at https://creativecommons.org/. 320 | -------------------------------------------------------------------------------- /LatexForm.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jonathan-LeRoux/IguanaTex/bf549383004d3443fa5600e21330b521b34049e5/LatexForm.frx -------------------------------------------------------------------------------- /LoadVectorGraphicsForm.frm: -------------------------------------------------------------------------------- 1 | VERSION 5.00 2 | Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} LoadVectorGraphicsForm 3 | Caption = "Load Vector Graphics File" 4 | ClientHeight = 3408 5 | ClientLeft = 96 6 | ClientTop = 324 7 | ClientWidth = 7020 8 | OleObjectBlob = "LoadVectorGraphicsForm.frx":0000 9 | StartUpPosition = 1 'CenterOwner 10 | End 11 | Attribute VB_Name = "LoadVectorGraphicsForm" 12 | Attribute VB_GlobalNameSpace = False 13 | Attribute VB_Creatable = False 14 | Attribute VB_PredeclaredId = True 15 | Attribute VB_Exposed = False 16 | Option Explicit 17 | 18 | Private Sub ComboBoxVectorOutputType_Change() 19 | SetVectorTypeDependencies 20 | End Sub 21 | 22 | Private Sub SetVectorTypeDependencies() 23 | If ComboBoxVectorOutputType.ListIndex = 0 Then 24 | CheckBoxCleanUp.value = False 25 | CheckBoxCleanUp.Enabled = False 26 | CheckBoxConvertLines.value = False 27 | CheckBoxConvertLines.Enabled = False 28 | Else 29 | CheckBoxCleanUp.Enabled = True 30 | CheckBoxConvertLines.Enabled = True 31 | CheckBoxCleanUp.value = GetITSetting("LoadVectorFileCleanUp", True) 32 | CheckBoxConvertLines.value = GetITSetting("LoadVectorFileConvertLines", False) 33 | End If 34 | End Sub 35 | 36 | Sub CommandButtonSave_Click() 37 | SetITSetting "LoadVectorFileConvertLines", REG_DWORD, BoolToInt(CheckBoxConvertLines.value) 38 | SetITSetting "LoadVectorFileScaling", REG_SZ, textboxScalor.Text 39 | SetITSetting "LoadVectorFileCalibrationX", REG_SZ, TextBoxCalibrationX.Text 40 | SetITSetting "LoadVectorFileCalibrationY", REG_SZ, TextBoxCalibrationY.Text 41 | SetITSetting "LoadVectorFileOutputTypeIdx", REG_DWORD, ComboBoxVectorOutputType.ListIndex 42 | SetITSetting "LoadVectorFileCleanUp", REG_DWORD, BoolToInt(CheckBoxCleanUp.value) 43 | End Sub 44 | 45 | Private Sub UserForm_Initialize() 46 | Me.Top = Application.Top + 110 47 | Me.Left = Application.Left + 25 48 | Me.Height = 194 49 | Me.Width = 355 50 | #If Mac Then 51 | Me.LabelInsertPath.Caption = "Insert path of .pdf/.dvi/.xdv/.ps/.eps/.svg file:" 52 | ResizeUserForm Me 53 | ComboBoxVectorOutputType.Enabled = False 54 | #End If 55 | textboxScalor.Text = GetITSetting("LoadVectorFileScaling", "1") 56 | CheckBoxConvertLines.value = GetITSetting("LoadVectorFileConvertLines", False) 57 | TextBoxCalibrationX.Text = GetITSetting("LoadVectorFileCalibrationX", "1") 58 | TextBoxCalibrationY.Text = GetITSetting("LoadVectorFileCalibrationY", "1") 59 | ComboBoxVectorOutputType.List = Array("SVG via PDF w/ dvisvgm", "EMF w/ pdfiumdraw") 60 | ComboBoxVectorOutputType.ListIndex = GetITSetting("LoadVectorFileOutputTypeIdx", 0) 61 | CheckBoxCleanUp.value = GetITSetting("LoadVectorFileCleanUp", True) 62 | SetVectorTypeDependencies 63 | ShowAcceleratorTip Me.ButtonLoadFile 64 | ShowAcceleratorTip Me.ButtonCancel 65 | ShowAcceleratorTip Me.CommandButtonSave 66 | 67 | End Sub 68 | 69 | Private Sub UserForm_Activate() 70 | #If Mac Then 71 | MacEnableAccelerators Me 72 | #End If 73 | End Sub 74 | 75 | Sub ButtonCancel_Click() 76 | Unload LoadVectorGraphicsForm 77 | End Sub 78 | 79 | Private Function isInsertableVectorFile(file As String) As Boolean 80 | Dim Ext As String 81 | Ext = GetExtension(file) 82 | #If Mac Then 83 | isInsertableVectorFile = Ext = "pdf" Or Ext = "dvi" Or Ext = "xdv" Or Ext = "ps" Or Ext = "eps" Or Ext = "svg" 84 | #Else 85 | isInsertableVectorFile = Ext = "pdf" Or Ext = "dvi" Or Ext = "xdv" Or Ext = "ps" Or Ext = "eps" Or Ext = "emf" Or Ext = "svg" 86 | #End If 87 | End Function 88 | 89 | Sub ButtonPath_Click() 90 | #If Mac Then 91 | TextBoxFile.Text = MacChooseFileOfType("pdf,dvi,xdv,ps,eps,svg") 92 | #Else 93 | TextBoxFile.Text = BrowseFilePath(TextBoxFile.Text, "Vector graphics files", "*.pdf;*.dvi;*.xdv;*.ps;*.eps;*.emf;*.svg", "&Select file") 94 | #End If 95 | TextBoxFile.SetFocus 96 | End Sub 97 | 98 | Private Sub TextBoxFile_Change() 99 | Dim path As String, Ext As String 100 | path = TextBoxFile.Text 101 | Ext = GetExtension(path) 102 | ButtonLoadFile.Enabled = FileExists(path) And isInsertableVectorFile(path) 103 | If Ext = "emf" And isInsertableVectorFile(path) Then 104 | ComboBoxVectorOutputType.ListIndex = 1 105 | ComboBoxVectorOutputType.Enabled = False 106 | SetVectorTypeDependencies 107 | ElseIf Ext = "svg" Then 108 | ComboBoxVectorOutputType.ListIndex = 0 109 | ComboBoxVectorOutputType.Enabled = False 110 | SetVectorTypeDependencies 111 | End If 112 | End Sub 113 | 114 | Sub ButtonLoadFile_Click() 115 | DoInsertVectorGraphicsFile 116 | Unload LoadVectorGraphicsForm 117 | End Sub 118 | 119 | 120 | Private Sub DoInsertVectorGraphicsFile() 121 | Dim NewShape As Shape 122 | Dim TimeOutTimeString As String 123 | Dim TimeOutTime As Long 124 | TimeOutTimeString = GetITSetting("TimeOutTime", "20") ' Wait 20 seconds for the processes to complete 125 | TimeOutTime = val(NormalizeDecimalNumber(TimeOutTimeString)) * 1000 126 | Dim debugMode As Boolean 127 | debugMode = False 128 | #If Mac Then 129 | Dim fs As New MacFileSystemObject 130 | #Else 131 | Dim fs As New FileSystemObject 132 | #End If 133 | 134 | Dim StartFolder As String 135 | ' The StartFolder doesn't really matter here because everything is relative to the input file, 136 | ' we just need any folder from which to launch the commands 137 | 'If ActivePresentation.path <> vbNullString Then 138 | ' StartFolder = ActivePresentation.path 139 | 'Else 140 | If GetTempPath() <> vbNullString Then 141 | StartFolder = GetTempPath() 142 | Else 143 | #If Mac Then 144 | StartFolder = "/" 145 | #Else 146 | StartFolder = "C:\" 147 | #End If 148 | End If 149 | 150 | Dim posX As Single, posY As Single, ScalingX As Single, ScalingY As Single 151 | Dim Sel As Selection 152 | Set Sel = Application.ActiveWindow.Selection 153 | If Sel.Type = ppSelectionShapes Then 154 | ' if something is selected on a slide, use its position for the new display 155 | posX = Sel.ShapeRange(1).Left 156 | posY = Sel.ShapeRange(1).Top 157 | Else 158 | posX = 200 159 | posY = 200 160 | End If 161 | ScalingX = val(NormalizeDecimalNumber(textboxScalor.value)) * val(NormalizeDecimalNumber(TextBoxCalibrationX.value)) 162 | ScalingY = val(NormalizeDecimalNumber(textboxScalor.value)) * val(NormalizeDecimalNumber(TextBoxCalibrationY.value)) 163 | 164 | ' Get the path and extension of the file to be inserted 165 | Dim path As String, Ext As String, pdfPath As String, psPath As String 166 | path = TextBoxFile.Text 167 | Ext = GetExtension(path) 168 | 169 | Dim TeXExePath As String, TeXExeExt As String 170 | TeXExePath = GetITSetting("TeXExePath", DEFAULT_TEX_EXE_PATH) 171 | TeXExeExt = vbNullString 172 | Dim VectorOutputTypeList As Variant 173 | VectorOutputTypeList = Array("dvisvgm", "pdfiumdraw") 174 | Dim VectorOutputType As String 175 | VectorOutputType = VectorOutputTypeList(ComboBoxVectorOutputType.ListIndex) 176 | 177 | Dim ConvertLines As Boolean 178 | ConvertLines = CheckBoxConvertLines.value 179 | Dim CleanUp As Boolean 180 | CleanUp = CheckBoxCleanUp.value 181 | 182 | Dim RetVal As Long 183 | Dim ErrorMessage As String 184 | Dim RunCommand As String 185 | 186 | If Ext = "svg" Or Ext = "emf" Then 187 | Set NewShape = AddDisplayShape(path, posX, posY) 188 | Else 189 | If VectorOutputType = "dvisvgm" Then ' Convert to SVG 190 | Dim libgsPath As String 191 | libgsPath = GetITSetting("Libgs", DEFAULT_LIBGS) 192 | Dim libgsString As String 193 | If libgsPath <> vbNullString Then 194 | libgsString = " --libgs=" & ShellEscape(libgsPath) 195 | Else 196 | libgsString = vbNullString 197 | End If 198 | Dim InputTypeSwitch As String 199 | If Ext = "ps" Or Ext = "eps" Then 200 | InputTypeSwitch = " --eps" 201 | ElseIf Ext = "pdf" Then 202 | InputTypeSwitch = " --pdf" 203 | Else 204 | InputTypeSwitch = vbNullString 205 | End If 206 | Dim svgPath As String 207 | svgPath = path & "_tmp.svg" 208 | If fs.FileExists(svgPath) Then fs.DeleteFile svgPath 209 | RunCommand = ShellEscape(TeXExePath & "dvisvgm" & TeXExeExt) & InputTypeSwitch & " -o " & ShellEscape(svgPath) _ 210 | & libgsString & " " & ShellEscape(path) 211 | RetVal& = Execute(RunCommand, StartFolder, debugMode, TimeOutTime) 212 | If (RetVal& <> 0 Or Not fs.FileExists(svgPath)) Then 213 | ' Error in EPS/PS/PDF to SVG conversion 214 | ErrorMessage = "Error while using dvisvgm to convert input file to SVG." 215 | ShowError ErrorMessage, RunCommand 216 | Exit Sub 217 | End If 218 | Ext = "svg" 219 | Set NewShape = AddDisplayShape(svgPath, posX, posY) 220 | If fs.FileExists(svgPath) Then fs.DeleteFile svgPath 221 | Else 'Convert to EMF 222 | If TeXExePath <> vbNullString Then TeXExeExt = ".exe" 223 | Dim DeleteTmpPDF As Boolean 224 | DeleteTmpPDF = False 225 | ' If .dvi/.xdv/.ps/.eps file, convert to .pdf first, using ps2pdf/eps2pdf/dvipdfmx 226 | If Ext = "ps" Or Ext = "eps" Or Ext = "dvi" Or Ext = "xdv" Then 227 | psPath = path 228 | pdfPath = path + "_tmp.pdf" 229 | If fs.FileExists(pdfPath) Then fs.DeleteFile pdfPath 230 | Dim pspdf_command As String 231 | Dim pdfpath_prefix As String 232 | pdfpath_prefix = vbNullString 233 | If Ext = "ps" Then 234 | pspdf_command = "ps2pdf" 235 | ElseIf Ext = "eps" Then 236 | pspdf_command = "epspdf" 237 | Else 238 | pspdf_command = "dvipdfmx" 239 | pdfpath_prefix = "-o " 240 | End If 241 | RunCommand = ShellEscape(TeXExePath & pspdf_command & TeXExeExt) & " " + ShellEscape(psPath) + " " + pdfpath_prefix + ShellEscape(pdfPath) 242 | RetVal& = Execute(RunCommand, StartFolder, debugMode, TimeOutTime) 243 | If (RetVal& <> 0 Or Not fs.FileExists(pdfPath)) Then 244 | ErrorMessage = "DVI/XDV/PS/EPS to PDF conversion failed" _ 245 | & vbNewLine & "Make sure " & pspdf_command & " is installed (it comes with, e.g., Tex Live, MikTeX or Ghostscript) and can be run from anywhere via the command line" 246 | ShowError ErrorMessage, RunCommand 247 | Exit Sub 248 | End If 249 | Ext = "pdf" 250 | path = pdfPath 251 | DeleteTmpPDF = True 252 | End If 253 | ' Now we're dealing with a .pdf file 254 | 255 | ' Convert .pdf file to .emf using pdfiumdraw, which is part of TeX2img 256 | If Ext = "pdf" Then 257 | Dim emfPath As String 258 | emfPath = path + "_tmp.emf" 259 | If fs.FileExists(emfPath) Then fs.DeleteFile emfPath 260 | Dim tex2img_command As String 261 | Dim pdfiumdraw_command As String 262 | tex2img_command = GetITSetting("TeX2img Command", DEFAULT_TEX2IMG_COMMAND) 263 | pdfiumdraw_command = GetFolderFromPath(tex2img_command) & "pdfiumdraw.exe" 264 | RunCommand = ShellEscape(pdfiumdraw_command) & " --extent=50 --emf --transparent --pages=1 --output=" & ShellEscape(emfPath) _ 265 | & " " & ShellEscape(path) 266 | RetVal& = Execute(RunCommand, StartFolder, debugMode, TimeOutTime) 267 | If (RetVal& <> 0 Or Not fs.FileExists(emfPath)) Then 268 | ErrorMessage = " PDF to EMF conversion failed" _ 269 | & vbNewLine & "Make sure to correctly set the path to Tex2imgc.exe in Main Settings." _ 270 | & vbNewLine & "IguanaTex uses that path to find pdfiumdraw.exe." 271 | ShowError ErrorMessage, RunCommand 272 | Exit Sub 273 | End If 274 | Ext = "emf" 275 | Set NewShape = AddDisplayShape(emfPath, posX, posY) 276 | If Not debugMode Then 277 | If fs.FileExists(emfPath) Then fs.DeleteFile emfPath 278 | If DeleteTmpPDF Then 279 | If fs.FileExists(pdfPath) Then fs.DeleteFile pdfPath 280 | End If 281 | End If 282 | End If 283 | End If 284 | End If 285 | 286 | If Ext = "emf" Then 287 | Set NewShape = ConvertEMF(NewShape, ScalingX, ScalingY, posX, posY, Ext, ConvertLines, CleanUp) 288 | ElseIf Ext = "svg" Then 289 | Set NewShape = convertSVG(NewShape, ScalingX, ScalingY, posX, posY) 290 | Else 291 | MsgBox "We got lost somehow." 292 | End If 293 | NewShape.Select 294 | End Sub 295 | 296 | 297 | -------------------------------------------------------------------------------- /LoadVectorGraphicsForm.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jonathan-LeRoux/IguanaTex/bf549383004d3443fa5600e21330b521b34049e5/LoadVectorGraphicsForm.frx -------------------------------------------------------------------------------- /LogFileViewer.frm: -------------------------------------------------------------------------------- 1 | VERSION 5.00 2 | Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} LogFileViewer 3 | Caption = "Error in Latex Code" 4 | ClientHeight = 6960 5 | ClientLeft = 48 6 | ClientTop = 336 7 | ClientWidth = 8844.001 8 | OleObjectBlob = "LogFileViewer.frx":0000 9 | StartUpPosition = 1 'CenterOwner 10 | End 11 | Attribute VB_Name = "LogFileViewer" 12 | Attribute VB_GlobalNameSpace = False 13 | Attribute VB_Creatable = False 14 | Attribute VB_PredeclaredId = True 15 | Attribute VB_Exposed = False 16 | Option Explicit 17 | Private Sub UserForm_Initialize() 18 | Me.Top = Application.Top + 110 19 | Me.Left = Application.Left + 25 20 | Me.Height = 372 21 | Me.Width = 451 22 | ShowAcceleratorTip Me.CloseLogButton 23 | ShowAcceleratorTip Me.CmdButtonExternalEditor 24 | #If Mac Then 25 | ResizeUserForm Me 26 | #End If 27 | End Sub 28 | 29 | Private Sub UserForm_Activate() 30 | #If Mac Then 31 | MacEnableAccelerators Me 32 | #End If 33 | End Sub 34 | 35 | Sub CloseLogButton_Click() 36 | Dim SelStartPos As Long 37 | SelStartPos = LatexForm.TextWindow1.SelStart 38 | Dim TempPath As String 39 | TempPath = CleanPath(LatexForm.TextBoxTempFolder.Text) 40 | 41 | LatexForm.TextWindow1.Text = ReadAll(TempPath & DefaultFilePrefix & ".tex") 42 | 43 | CloseLogButton.Caption = "Close" 44 | Unload LogFileViewer 45 | 'If LatexForm.isFormModeless Then 46 | ' LatexForm.Hide 47 | ' LatexForm.Show vbModal 48 | 'End If 49 | LatexForm.TextWindow1.SetFocus 50 | If SelStartPos < Len(LatexForm.TextWindow1.Text) Then 51 | LatexForm.TextWindow1.SelStart = SelStartPos 52 | End If 53 | End Sub 54 | 55 | Sub CmdButtonExternalEditor_Click() 56 | Dim TempPath As String 57 | TempPath = CleanPath(LatexForm.TextBoxTempFolder.Text) 58 | If Not IsPathWritable(TempPath) Then Exit Sub 59 | 60 | LogFileViewer.Caption = ShellEscape(GetEditorPath()) & " " & ShellEscape(TempPath & DefaultFilePrefix & ".tex") 61 | CloseLogButton.Caption = "Reload modified code" 62 | #If Mac Then 63 | AppleScriptTask "IguanaTex.scpt", "MacExecute", GetEditorPath() & " " & ShellEscape(TempPath & DefaultFilePrefix & ".tex") 64 | #Else 65 | Shell ShellEscape(GetEditorPath()) & " " & ShellEscape(TempPath & DefaultFilePrefix & ".tex"), vbNormalFocus 66 | #End If 67 | End Sub 68 | 69 | #If Mac Then 70 | 71 | #Else 72 | ' Mousewheel functions 73 | 74 | Private Sub TextBox1_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, _ 75 | ByVal x As Single, ByVal Y As Single) 76 | If Not Me Is Nothing Then 77 | HookListBoxScroll Me, Me.TextBox1 78 | End If 79 | End Sub 80 | 81 | Private Sub Userform_QueryClose(Cancel As Integer, CloseMode As Integer) 82 | UnhookListBoxScroll 83 | End Sub 84 | 85 | #End If 86 | -------------------------------------------------------------------------------- /LogFileViewer.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jonathan-LeRoux/IguanaTex/bf549383004d3443fa5600e21330b521b34049e5/LogFileViewer.frx -------------------------------------------------------------------------------- /MacFileSystemObject.cls: -------------------------------------------------------------------------------- 1 | VERSION 1.0 CLASS 2 | BEGIN 3 | MultiUse = -1 'True 4 | END 5 | Attribute VB_Name = "MacFileSystemObject" 6 | Attribute VB_GlobalNameSpace = False 7 | Attribute VB_Creatable = False 8 | Attribute VB_PredeclaredId = False 9 | Attribute VB_Exposed = False 10 | ' Partial replacement (in Mac) for Scripting.FileSystemObject 11 | 12 | Option Explicit 13 | #If Mac Then 14 | 15 | Public Function FileExists(pathname As String) As Boolean 16 | FileExists = (Dir(pathname) <> "") 17 | End Function 18 | 19 | Public Function FolderExists(pathname As String) As Boolean 20 | FolderExists = (Dir(pathname) <> "") 21 | End Function 22 | 23 | Public Sub CreateFolder(pathname As String) 24 | MkDir pathname 25 | End Sub 26 | 27 | 'Public Sub CopyFile(pathfrom As String, pathto As String) 28 | '#If Mac Then 29 | ' cp pathfrom pathto 30 | '#Else 31 | ' fs.CopyFile pathfrom, pathto 32 | '#End If 33 | 'End Sub 34 | 35 | ' calls `find -name -delete` 36 | Public Sub FindDelete(dirname As String, pattern As String) 37 | AppleScriptTask "IguanaTex.scpt", "MacExecute", "find " & ShellEscape(dirname) & " -name " & ShellEscape(pattern) & " -delete" 38 | End Sub 39 | 40 | ' does not support path globbing. use `FindDelete` instead. 41 | Public Sub DeleteFile(pathname As String) 42 | If FileExists(pathname) Then 43 | ' remove readonly attribute if set 44 | SetAttr pathname, vbNormal 45 | Kill pathname 46 | End If 47 | End Sub 48 | #End If 49 | ' 50 | 'Private Sub Class_Initialize() 51 | '#If Mac Then 52 | ' ' 53 | '#Else 54 | ' Dim fs As New Scripting.FileSystemObject 55 | '#End If 56 | 'End Sub 57 | ' 58 | 'Private Sub Class_Terminate() 59 | ' Set fs = Nothing 60 | 'End Sub 61 | -------------------------------------------------------------------------------- /MacUtils.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "MacUtils" 2 | Option Explicit 3 | Option Private Module 4 | 5 | Public Const gUserFormResizeFactor As Double = 1.333333 6 | 7 | #If Mac Then 8 | ' macOS virtual keycodes. See 9 | ' or https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values#code_values_on_mac 10 | Private Const kVK_ANSI_A As LongLong = &H0 11 | Private Const kVK_ANSI_Z As LongLong = &H6 12 | Private Const kVK_ANSI_X As LongLong = &H7 13 | Private Const kVK_ANSI_C As LongLong = &H8 14 | Private Const kVK_ANSI_V As LongLong = &H9 15 | 16 | Private Const NSEventModifierFlagShift As LongLong = &H20000 17 | Private Const NSEventModifierFlagCommand As LongLong = &H100000 18 | 19 | Private Declare PtrSafe Function MacEnableCopyPaste_Native _ 20 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 21 | Alias "MacEnableCopyPaste" _ 22 | (ByVal formPtr As LongPtr, ByVal handler As LongPtr, ByVal c As LongLong, ByVal d As LongLong) As LongLong 23 | Private Declare PtrSafe Function MacEnableAccelerators_Native _ 24 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 25 | Alias "MacEnableAccelerators" _ 26 | (ByVal formPtr As LongPtr, ByVal handler As LongPtr, ByVal c As LongLong, ByVal d As LongLong) As LongLong 27 | 28 | Private Sub MacDoCopyPaste(ByVal formPtr As LongPtr, ByVal keyCode As LongLong, ByVal modifierFlags As LongLong) 29 | Dim form As Variant 30 | Set form = GetItemByPtr(UserForms, formPtr) 31 | If form Is Nothing Then 32 | Exit Sub 33 | End If 34 | 35 | If keyCode = kVK_ANSI_Z And modifierFlags = NSEventModifierFlagCommand Then 36 | form.UndoAction 37 | Exit Sub 38 | ElseIf keyCode = kVK_ANSI_Z And modifierFlags = NSEventModifierFlagCommand + NSEventModifierFlagShift Then 39 | form.RedoAction 40 | Exit Sub 41 | End If 42 | 43 | Dim ctrl As Control 44 | Set ctrl = form.ActiveControl 45 | Do 46 | If TypeOf ctrl Is Frame Then 47 | Set ctrl = ctrl.ActiveControl 48 | ElseIf TypeOf ctrl Is MultiPage Then 49 | Set ctrl = ctrl.Pages(ctrl.value).ActiveControl 50 | Else 51 | Exit Do 52 | End If 53 | Loop 54 | 55 | If Not (TypeOf ctrl Is TextBox) Then 56 | Exit Sub 57 | End If 58 | 59 | If keyCode = kVK_ANSI_A And modifierFlags = NSEventModifierFlagCommand Then 60 | ctrl.SelStart = 0 61 | ctrl.SelLength = Len(ctrl) 62 | ElseIf keyCode = kVK_ANSI_C And modifierFlags = NSEventModifierFlagCommand Then 63 | ctrl.Copy 64 | ElseIf keyCode = kVK_ANSI_V And modifierFlags = NSEventModifierFlagCommand Then 65 | ctrl.Paste 66 | ElseIf keyCode = kVK_ANSI_X And modifierFlags = NSEventModifierFlagCommand Then 67 | ctrl.Cut 68 | End If 69 | End Sub 70 | 71 | Private Sub MacDoAccelerator(ByVal formPtr As LongPtr, ByVal asciiCode As LongLong) 72 | Dim form As Variant 73 | Set form = GetItemByPtr(UserForms, formPtr) 74 | If form Is Nothing Then 75 | Debug.Print "Form Not Found" 76 | Exit Sub 77 | End If 78 | 79 | Dim ch As String 80 | ch = UCase(Chr(CLng(asciiCode))) 81 | If ch = vbNullString Then 82 | Exit Sub 83 | End If 84 | 85 | Dim ctrl As Control 86 | On Error Resume Next 87 | For Each ctrl In form.Controls 88 | If TypeOf ctrl Is MultiPage Then 89 | Dim page As page 90 | For Each page In ctrl.Pages 91 | If UCase(Left(page.Accelerator, 1)) = ch Then 92 | ctrl.value = page.index 93 | Exit Sub 94 | End If 95 | Next 96 | ElseIf TypeOf ctrl Is CheckBox Or TypeOf ctrl Is CommandButton Then 97 | If UCase(Left(ctrl.Accelerator, 1)) = ch Then 98 | If TypeOf ctrl Is CheckBox Then 99 | ctrl.value = IsNull(ctrl.value) Or Not ctrl.value 100 | End If 101 | CallByName form, ctrl.Name & "_Click", VbMethod 102 | Exit Sub 103 | End If 104 | End If 105 | Next 106 | End Sub 107 | 108 | Public Sub MacEnableCopyPaste(ByRef currentForm As Variant) 109 | MacEnableCopyPaste_Native ObjPtr(currentForm), AddressOf MacDoCopyPaste, 0, 0 110 | End Sub 111 | 112 | Public Sub MacEnableAccelerators(ByRef currentForm As Variant) 113 | MacEnableAccelerators_Native ObjPtr(currentForm), AddressOf MacDoAccelerator, 0, 0 114 | End Sub 115 | #End If 116 | 117 | Public Function ReadAllBytes(FileName As String) As Byte() 118 | Dim fnum As Integer 119 | fnum = FreeFile() 120 | Open FileName For Binary Access Read As fnum 121 | 122 | Dim length As Long 123 | length = FileLen(FileName) 124 | 125 | Dim data() As Byte 126 | If length <> 0 Then 127 | ReDim data(length - 1) 128 | Get #fnum, , data 129 | End If 130 | 131 | Close #fnum 132 | 133 | ReadAllBytes = data 134 | End Function 135 | 136 | #If Mac Then 137 | Public Function MacTempPath() As String 138 | MacTempPath = MacScript("POSIX path of (path to temporary items)") 139 | End Function 140 | 141 | Public Function MacChooseFileOfType(typeStr As String) As String 142 | MacChooseFileOfType = AppleScriptTask("IguanaTex.scpt", "MacChooseFileOfType", typeStr) 143 | End Function 144 | 145 | Public Function MacChooseApp(DefaultValue As String) As String 146 | MacChooseApp = AppleScriptTask("IguanaTex.scpt", "MacChooseApp", DefaultValue) 147 | End Function 148 | #End If 149 | 150 | Sub ResizeUserForm(frm As Object, Optional dResizeFactor As Double = 0#) 151 | 'Created by Jon Peltier 152 | Dim ctrl As Control 153 | Dim sColWidths As String 154 | Dim vColWidths As Variant 155 | Dim iCol As Long 156 | 157 | If dResizeFactor = 0 Then dResizeFactor = gUserFormResizeFactor 158 | With frm 159 | '.Resize = True 160 | .Height = .Height * dResizeFactor 161 | .Width = .Width * dResizeFactor 162 | 163 | For Each ctrl In frm.Controls 164 | With ctrl 165 | .Height = .Height * dResizeFactor 166 | .Width = .Width * dResizeFactor 167 | .Left = .Left * dResizeFactor 168 | .Top = .Top * dResizeFactor 169 | On Error Resume Next 170 | .Font.Size = .Font.Size * dResizeFactor 171 | On Error GoTo 0 172 | 173 | ' multi column listboxes, comboboxes 174 | Select Case TypeName(ctrl) 175 | Case "ListBox", "ComboBox" 176 | If ctrl.ColumnCount > 1 Then 177 | sColWidths = ctrl.ColumnWidths 178 | vColWidths = Split(sColWidths, ";") 179 | For iCol = LBound(vColWidths) To UBound(vColWidths) 180 | vColWidths(iCol) = val(vColWidths(iCol)) * dResizeFactor 181 | Next 182 | sColWidths = Join(vColWidths, ";") 183 | ctrl.ColumnWidths = sColWidths 184 | End If 185 | End Select 186 | End With 187 | Next 188 | End With 189 | End Sub 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /MouseWheel.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "MouseWheel" 2 | ' From https://social.msdn.microsoft.com/Forums/en-US/7d584120-a929-4e7c-9ec2-9998ac639bea/mouse-scroll-in-userform-listbox-in-excel-2010?forum=isvvba 3 | ' 4 | 'Enables mouse wheel scrolling in controls 5 | Option Explicit 6 | Option Private Module 7 | 8 | #If Mac Then 9 | 10 | #Else 11 | #If Win64 Then 12 | Private Type POINTAPI 13 | XY As LongLong 14 | End Type 15 | #Else 16 | Private Type POINTAPI 17 | x As Long 18 | Y As Long 19 | End Type 20 | #End If 21 | 22 | Private Type MOUSEHOOKSTRUCT 23 | Pt As POINTAPI 24 | hWnd As Long 25 | wHitTestCode As Long 26 | dwExtraInfo As Long 27 | End Type 28 | 29 | #If VBA7 Then 30 | Private Declare PtrSafe Function FindWindow Lib "user32" _ 31 | Alias "FindWindowA" ( _ 32 | ByVal lpClassName As String, _ 33 | ByVal lpWindowName As String) As Long ' not sure if this should be LongPtr 34 | #If Win64 Then 35 | Private Declare PtrSafe Function GetWindowLongPtr Lib "user32" _ 36 | Alias "GetWindowLongPtrA" ( _ 37 | ByVal hWnd As LongPtr, _ 38 | ByVal nIndex As Long) As LongPtr 39 | #Else 40 | Private Declare PtrSafe Function GetWindowLong Lib "user32" _ 41 | Alias "GetWindowLongA" ( _ 42 | ByVal hWnd As LongPtr, _ 43 | ByVal nIndex As Long) As LongPtr 44 | #End If 45 | Private Declare PtrSafe Function SetWindowsHookEx Lib "user32" _ 46 | Alias "SetWindowsHookExA" ( _ 47 | ByVal idHook As Long, _ 48 | ByVal lpfn As LongPtr, _ 49 | ByVal hmod As LongPtr, _ 50 | ByVal dwThreadId As Long) As LongPtr 51 | Private Declare PtrSafe Function CallNextHookEx Lib "user32" ( _ 52 | ByVal hHook As LongPtr, _ 53 | ByVal nCode As Long, _ 54 | ByVal wParam As LongPtr, _ 55 | lParam As Any) As LongPtr 56 | Private Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" ( _ 57 | ByVal hHook As LongPtr) As LongPtr ' MAYBE Long 58 | #If Win64 Then 59 | Private Declare PtrSafe Function WindowFromPoint Lib "user32" ( _ 60 | ByVal Point As LongLong) As LongPtr ' 61 | #Else 62 | Private Declare PtrSafe Function WindowFromPoint Lib "user32" ( _ 63 | ByVal xPoint As Long, _ 64 | ByVal yPoint As Long) As LongPtr ' 65 | #End If 66 | Private Declare PtrSafe Function GetCursorPos Lib "user32" ( _ 67 | ByRef lpPoint As POINTAPI) As LongPtr 'MAYBE Long 68 | #Else 69 | Private Declare Function FindWindow Lib "user32" _ 70 | Alias "FindWindowA" ( _ 71 | ByVal lpClassName As String, _ 72 | ByVal lpWindowName As String) As Long 73 | Private Declare Function GetWindowLong Lib "user32.dll" _ 74 | Alias "GetWindowLongA" ( _ 75 | ByVal hWnd As Long, _ 76 | ByVal nIndex As Long) As Long 77 | Private Declare Function SetWindowsHookEx Lib "user32" _ 78 | Alias "SetWindowsHookExA" ( _ 79 | ByVal idHook As Long, _ 80 | ByVal lpfn As Long, _ 81 | ByVal hmod As Long, _ 82 | ByVal dwThreadId As Long) As Long 83 | Private Declare Function CallNextHookEx Lib "user32" ( _ 84 | ByVal hHook As Long, _ 85 | ByVal nCode As Long, _ 86 | ByVal wParam As Long, _ 87 | lParam As Any) As Long 88 | Private Declare Function UnhookWindowsHookEx Lib "user32" ( _ 89 | ByVal hHook As Long) As Long 90 | Private Declare Function WindowFromPoint Lib "user32" ( _ 91 | ByVal xPoint As Long, _ 92 | ByVal yPoint As Long) As Long 93 | Private Declare Function GetCursorPos Lib "user32.dll" ( _ 94 | ByRef lpPoint As POINTAPI) As Long 95 | #End If 96 | 97 | Private Const WH_MOUSE_LL As Long = 14 98 | Private Const WM_MOUSEWHEEL As Long = &H20A 99 | Private Const HC_ACTION As Long = 0 100 | Private Const GWL_HINSTANCE As Long = (-6) 101 | 'Private Const WM_KEYDOWN As Long = &H100 102 | 'Private Const WM_KEYUP As Long = &H101 103 | 'Private Const VK_UP As Long = &H26 104 | 'Private Const VK_DOWN As Long = &H28 105 | 'Private Const WM_LBUTTONDOWN As Long = &H201 106 | Private mCtl As MSForms.Control 107 | Private mbHook As Boolean 108 | #If VBA7 Then 109 | Private mLngMouseHook As LongPtr 110 | Private mListBoxHwnd As LongPtr 111 | #Else 112 | Private mLngMouseHook As Long 113 | Private mListBoxHwnd As Long 114 | #End If 115 | 116 | Sub HookListBoxScroll(frm As Object, ctl As MSForms.Control) 117 | Dim tPT As POINTAPI 118 | #If VBA7 Then 119 | Dim lngAppInst As LongPtr 120 | Dim hwndUnderCursor As LongPtr 121 | #Else 122 | Dim lngAppInst As Long 123 | Dim hwndUnderCursor As Long 124 | #End If 125 | GetCursorPos tPT 126 | #If Win64 Then 127 | hwndUnderCursor = WindowFromPoint(tPT.XY) 128 | #Else 129 | hwndUnderCursor = WindowFromPoint(tPT.x, tPT.Y) 130 | #End If 131 | If Not frm.ActiveControl Is ctl Then 132 | ctl.SetFocus 133 | End If 134 | If mListBoxHwnd <> hwndUnderCursor Then 135 | UnhookListBoxScroll 136 | Set mCtl = ctl 137 | mListBoxHwnd = hwndUnderCursor 138 | #If Win64 Then 139 | lngAppInst = GetWindowLongPtr(mListBoxHwnd, GWL_HINSTANCE) 140 | #Else 141 | lngAppInst = GetWindowLong(mListBoxHwnd, GWL_HINSTANCE) 142 | #End If 143 | ' PostMessage mListBoxHwnd, WM_LBUTTONDOWN, 0&, 0& 144 | If Not mbHook Then 145 | mLngMouseHook = SetWindowsHookEx( _ 146 | WH_MOUSE_LL, AddressOf MouseProc, lngAppInst, 0) 147 | mbHook = mLngMouseHook <> 0 148 | End If 149 | End If 150 | End Sub 151 | 152 | Sub UnhookListBoxScroll() 153 | If mbHook Then 154 | Set mCtl = Nothing 155 | UnhookWindowsHookEx mLngMouseHook 156 | mLngMouseHook = 0 157 | mListBoxHwnd = 0 158 | mbHook = False 159 | End If 160 | End Sub 161 | #If VBA7 Then 162 | Private Function MouseProc( _ 163 | ByVal nCode As Long, ByVal wParam As Long, _ 164 | ByRef lParam As MOUSEHOOKSTRUCT) As LongPtr 165 | #Else 166 | Private Function MouseProc( _ 167 | ByVal nCode As Long, ByVal wParam As Long, _ 168 | ByRef lParam As MOUSEHOOKSTRUCT) As Long 169 | #End If 170 | Dim idx As Long 171 | Dim tPT As POINTAPI 172 | On Error GoTo errH 173 | If (nCode = HC_ACTION) Then 174 | GetCursorPos tPT 175 | #If Win64 Then 176 | ' I moved to ignoring the point returned in lParam because it may be in the wrong coordinates depending on DPI 177 | ' GetCursorPos gives consistent coordinates regradless. 178 | ' This may create some racing issues, but it seems to be working fine as far as I can tell... 179 | 'If WindowFromPoint(lParam.Pt.XY) = mListBoxHwnd Then 180 | If WindowFromPoint(tPT.XY) = mListBoxHwnd Then 181 | If wParam = WM_MOUSEWHEEL Then 182 | MouseProc = True 183 | ' If lParam.hWnd > 0 Then 184 | ' postMessage mListBoxHwnd, WM_KEYDOWN, VK_UP, 0 185 | ' Else 186 | ' postMessage mListBoxHwnd, WM_KEYDOWN, VK_DOWN, 0 187 | ' End If 188 | ' postMessage mListBoxHwnd, WM_KEYUP, VK_UP, 0 189 | If TypeOf mCtl Is Frame Then 190 | If lParam.hWnd > 0 Then idx = -10 Else idx = 10 191 | idx = idx + mCtl.ScrollTop 192 | If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then 193 | mCtl.ScrollTop = idx 194 | End If 195 | ElseIf TypeOf mCtl Is UserForm Then 196 | If lParam.hWnd > 0 Then idx = -10 Else idx = 10 197 | idx = idx + mCtl.ScrollTop 198 | If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then 199 | mCtl.ScrollTop = idx 200 | End If 201 | ElseIf TypeOf mCtl Is TextBox Then 202 | If lParam.hWnd > 0 Then idx = -3 Else idx = 3 203 | idx = idx + mCtl.CurLine 204 | If idx < 0 Then idx = 0 205 | If idx > mCtl.LineCount - 1 Then idx = mCtl.LineCount - 1 206 | mCtl.CurLine = idx 207 | Else 208 | If lParam.hWnd > 0 Then idx = -1 Else idx = 1 209 | idx = idx + mCtl.ListIndex 210 | If idx < 0 Then idx = 0 211 | If idx > mCtl.ListCount - 1 Then idx = mCtl.ListCount - 1 212 | mCtl.ListIndex = idx 213 | End If 214 | Exit Function 215 | End If 216 | Else 217 | UnhookListBoxScroll 218 | End If 219 | #Else 220 | If WindowFromPoint(tPT.x, tPT.Y) = mListBoxHwnd Then 221 | If wParam = WM_MOUSEWHEEL Then 222 | MouseProc = True 223 | ' If lParam.hWnd > 0 Then 224 | ' postMessage mListBoxHwnd, WM_KEYDOWN, VK_UP, 0 225 | ' Else 226 | ' postMessage mListBoxHwnd, WM_KEYDOWN, VK_DOWN, 0 227 | ' End If 228 | ' postMessage mListBoxHwnd, WM_KEYUP, VK_UP, 0 229 | If TypeOf mCtl Is Frame Then 230 | If lParam.hWnd > 0 Then idx = -10 Else idx = 10 231 | idx = idx + mCtl.ScrollTop 232 | If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then 233 | mCtl.ScrollTop = idx 234 | End If 235 | ElseIf TypeOf mCtl Is UserForm Then 236 | If lParam.hWnd > 0 Then idx = -10 Else idx = 10 237 | idx = idx + mCtl.ScrollTop 238 | If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then 239 | mCtl.ScrollTop = idx 240 | End If 241 | Else 242 | If lParam.hWnd > 0 Then idx = -1 Else idx = 1 243 | idx = idx + mCtl.ListIndex 244 | If idx >= 0 Then mCtl.ListIndex = idx 245 | End If 246 | Exit Function 247 | End If 248 | Else 249 | UnhookListBoxScroll 250 | End If 251 | #End If 252 | End If 253 | MouseProc = CallNextHookEx( _ 254 | mLngMouseHook, nCode, wParam, ByVal lParam) 255 | Exit Function 256 | errH: 257 | Debug.Print "error" 258 | UnhookListBoxScroll 259 | End Function 260 | '#Else 261 | ' Private Function MouseProc( _ 262 | ' ByVal nCode As Long, ByVal wParam As Long, _ 263 | ' ByRef lParam As MOUSEHOOKSTRUCT) As Long 264 | ' Dim idx As Long 265 | ' On Error GoTo errH 266 | ' If (nCode = HC_ACTION) Then 267 | ' If WindowFromPoint(lParam.Pt.X, lParam.Pt.Y) = mListBoxHwnd Then 268 | ' If wParam = WM_MOUSEWHEEL Then 269 | ' MouseProc = True 270 | '' If lParam.hWnd > 0 Then 271 | '' postMessage mListBoxHwnd, WM_KEYDOWN, VK_UP, 0 272 | '' Else 273 | '' postMessage mListBoxHwnd, WM_KEYDOWN, VK_DOWN, 0 274 | '' End If 275 | '' postMessage mListBoxHwnd, WM_KEYUP, VK_UP, 0 276 | ' If TypeOf mCtl Is Frame Then 277 | ' If lParam.hWnd > 0 Then idx = -10 Else idx = 10 278 | ' idx = idx + mCtl.ScrollTop 279 | ' If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then 280 | ' mCtl.ScrollTop = idx 281 | ' End If 282 | ' ElseIf TypeOf mCtl Is UserForm Then 283 | ' If lParam.hWnd > 0 Then idx = -10 Else idx = 10 284 | ' idx = idx + mCtl.ScrollTop 285 | ' If idx >= 0 And idx < ((mCtl.ScrollHeight - mCtl.Height) + 17.25) Then 286 | ' mCtl.ScrollTop = idx 287 | ' End If 288 | ' Else 289 | ' If lParam.hWnd > 0 Then idx = -1 Else idx = 1 290 | ' idx = idx + mCtl.ListIndex 291 | ' If idx >= 0 Then mCtl.ListIndex = idx 292 | ' End If 293 | ' Exit Function 294 | ' End If 295 | ' Else 296 | ' UnhookListBoxScroll 297 | ' End If 298 | ' End If 299 | ' MouseProc = CallNextHookEx( _ 300 | ' mLngMouseHook, nCode, wParam, ByVal lParam) 301 | ' Exit Function 302 | 'errH: 303 | ' UnhookListBoxScroll 304 | ' End Function 305 | '#End If 306 | 307 | #End If 308 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IguanaTex 2 | 3 | (C) [Jonathan Le Roux](https://www.jonathanleroux.org/) and Zvika Ben-Haim (Windows), [Tsung-Ju Chiang](https://github.com/tsung-ju) and Jonathan Le Roux (Mac) 4 | 5 | IguanaTex is a PowerPoint add-in which allows you to insert LaTeX equations into your PowerPoint presentation on Windows and Mac. It is distributed completely for free, along with its source code. 6 | 7 | This repository hosts the source code in a form that can be easily tracked, shared, and discussed (the VBA code is exported using the [ExportVBA macro](https://github.com/Jonathan-LeRoux/IguanaTex/blob/master/ExportVBA.bas)). 8 | 9 | The add-in file (.ppam) and its source version (.pptm) can be found in the [Releases](https://github.com/Jonathan-LeRoux/IguanaTex/releases). 10 | 11 | ## Table of Contents 12 | 13 | - [System Requirements](#system-requirements) 14 | - [Windows](#windows) 15 | - [Mac](#mac) 16 | - [Download and Install](#download-and-install) 17 | - [Windows](#windows) 18 | - [Mac](#mac) 19 | - [Automatic installation with Homebrew](#automatic-installation-with-homebrew) 20 | - [Manual installation](#manual-installation) 21 | - [Other installation settings](#other-installation-settings) 22 | - [Tips, Bugs, and Known Issues](#tips-bugs-and-known-issues) 23 | - [What to do if something does not work, or does not work as you expected](#what-to-do-if-something-does-not-work-or-does-not-work-as-you-expected) 24 | - [Debugging an issue](#debugging-an-issue) 25 | - [Keyboard shortcuts](#keyboard-shortcuts) 26 | - [Known Issues](#known-issues) 27 | - [Stay up to date: IguanaTex Google Group](#stay-up-to-date-iguanatex-google-group) 28 | - [License](#license) 29 | 30 | ## System Requirements 31 | 32 | ### Windows 33 | 34 | - OS: Windows 2000 or later (32- or 64-bit). 35 | - PowerPoint: 36 | - IguanaTex has been tested with Office 365, Office 2019, Office 2021 (including LTSC version), PowerPoint 2003, 2010, 2013, 2016, 2019 (both 32 and 64 bit). It is likely to also work in PowerPoint 2000 and 2007. 37 | - SVG support is available for Office 365 and recent retail versions of PowerPoint. Support is confirmed for PowerPoint 2021 at least for versions 2108 and above, and likely (although unconfirmed) for PowerPoint 2019 and maybe even PowerPoint 2016 for the same versions. Note that volume licensed versions, which are at version 1808 as of August 2023, do not support SVG conversion to Shape, which is required by IguanaTex. 38 | - LaTeX: [TeXLive](https://www.tug.org/texlive/) or [MiKTeX](http://miktex.org/) 39 | - [GhostScript](http://www.ghostscript.com/download/gsdnld.html) (if the latest version raises issues, try gs9.26) 40 | - [ImageMagick](http://www.imagemagick.org/script/download.php#windows) 41 | - (Optional) [TeX2img](https://github.com/abenori/TeX2img), used for Shape output via EMF ([Download](https://www.ms.u-tokyo.ac.jp/~abenori/soft/index.html#TEX2IMG)) 42 | - (Optional) [LaTeXiT-metadata](https://github.com/LaTeXiT-metadata/LaTeXiT-metadata-Win), used to convert displays generated with [LaTeXiT](https://www.chachatelier.fr/latexit/) on Mac into IguanaTex displays 43 | 44 | ### Mac 45 | 46 | - Intel or Apple Silicon Mac 47 | - On Apple Silicon based Macs, PowerPoint needs to be run with the setting "Open using Rosetta." 48 | - PowerPoint for Mac: 49 | - Office 365, Office 2021 (including LTSC version), Powerpoint 2019, PowerPoint 2016 (Version 16.16.7 190210 or later) 50 | - SVG support is available for Office 365 and recent retail versions of PowerPoint, including 2019 and 2021. Note that volume licensed (LTSC) versions do not support SVG conversion to Shape, which is required by IguanaTex. 51 | - [MacTeX](https://www.tug.org/mactex/) 52 | - Ghostscript library: For SVG/Shape support, download and install [Ghostscript-10.04.0.pkg](https://pages.uoregon.edu/koch/Ghostscript-10.04.0.pkg) and [Ghostscript-10.04.0-Extras.pkg](https://pages.uoregon.edu/koch/Ghostscript-10.04.0-Extras.pkg) (Once MacTeX 2025 is released, this should no longer be necessary). [More details about SVG support via `dvisvgm` in MacTeX](https://tug.org/mactex/aboutdvisvgm.html). 53 | - (Optional) [LaTeXiT-metadata](https://github.com/LaTeXiT-metadata/LaTeXiT-metadata-MacOS), used to convert [LaTeXiT](https://www.chachatelier.fr/latexit/) displays into IguanaTex displays 54 | 55 | 56 | ## Download and Install 57 | 58 | ### Windows Installation 59 | 60 | 1. **Download the .ppam add-in** file from this repository's [Releases page](https://github.com/Jonathan-LeRoux/IguanaTex/releases) and save it in a [Trusted Location](https://learn.microsoft.com/en-us/DeployOffice/security/trusted-locations) (see [this Microsoft article](https://learn.microsoft.com/en-us/DeployOffice/security/internet-macros-blocked#guidance-on-allowing-vba-macros-to-run-in-files-you-trust)), such as `%appdata%\Microsoft\Addins` (i.e., `C:\Users\user_name\Appdata\Roaming\Microsoft\Addins`). If you get a malware warning, try "Trust"-ing the file (Right-Click > Properties). You may have better luck downloading the `.pptm` file, Trusting it, opening it in PowerPoint, and using "Save As" to create your own `.ppam` file. 61 | 2. **Load the add-in**: in "File" > "Options" > "Add-Ins" > "Manage:" (lower part of the window), choose "PowerPoint Add-Ins" in the selection box. Then press "Go...", then click "Add New", select the `.ppam` file in the folder where you downloaded it, then "Close" (if you downloaded the .pptm source and saved it as `.ppam`, it will be in the default Add-In folder). 62 | 3. **Create and set a temporary file folder**: IguanaTex needs access to a folder with read/write permissions to store temporary files. 63 | - The default is "C:\Temp\". If you have write permissions under "C:\", create the folder "C:\Temp\". You're all set. 64 | - If you cannot create this folder, choose or create a folder with write permission at any other location. In the IguanaTex tab, choose "Main Settings" and put the path to the folder of your choice. You can also use a relative path under the presentation's folder (e.g., ".\" for the presentation folder itself). 65 | 4. **Install and set path to GhostScript and ImageMagick** (required for Picture outputs, except if using "Latex (DVI)" engine): 66 | - Needed to convert intermediate PDF files into PNG before insertion into PowerPoint as a Picture object. In the Picture generation process, all LaTeX engines except "Latex (DVI)" output PDF files. Even when generating a Shape, it is often better to first generate a Picture then convert to Shape: Picture generation is faster and more robust, so it can be convenient to work on a display in Picture mode then do a final conversion to Shape, preserving the size. 67 | - Set the **full** path to `gswin32c.exe` or `gswin64c.exe` (note the "`c`"!) and to ImageMagick's magick.exe in the "Main Settings" window. 68 | - Best way to make sure the path is correct is to use the "..." button next to each path and navigate to the correct file. 69 | - Some default paths include `%USERPROFILE%`. It is recommended to click on "..." to make sure the path gets properly converted to the actual user profile path. 70 | 5. (Optional) **Install and set path to TeX2img**: 71 | - Only needed for vector graphics support via EMF (compared to SVG, pros of EMF are: available on all PowerPoint versions, fully modifiable shapes; cons: some displays randomly suffer from distortions) 72 | - Download from [this link](https://www.ms.u-tokyo.ac.jp/~abenori/soft/index.html#TEX2IMG) (more details on TeX2img on their [Github repo](https://github.com/abenori/TeX2img)) 73 | - After unpacking TeX2img somewhere on your machine, run TeX2img.exe once to let it automatically set the various paths to latex/ghostscript, then set the **full** path to `TeX2imgc.exe` (note the "`c`"!) in the "Main Settings" window. 74 | 6. (Optional) **Install LaTeXiT-metadata**: 75 | - Needed to convert displays generated with [LaTeXiT](https://www.chachatelier.fr/latexit/) on Mac into IguanaTex displays 76 | - Download [`LaTeXiT-metadata-Win.zip`](https://github.com/Jonathan-LeRoux/IguanaTex/releases/download/v1.60.3/LaTeXiT-metadata-Win.zip) from the Releases page, unzip, and set the path to `LaTeXiT-metadata.exe` in the "Main Settings" window. 77 | - LaTeXiT-metadata was kindly prepared by Pierre Chatelier, [LaTeXiT](https://www.chachatelier.fr/latexit/)'s author, at my request. Many thanks to him! 78 | - [Source code is now public](https://github.com/LaTeXiT-metadata/LaTeXiT-metadata-Win). 79 | 80 | ### Mac Installation 81 | 82 | #### Automatic installation with Homebrew 83 | 84 | If you use Homebrew, installation is as simple as: 85 | 86 | ```bash 87 | brew tap tsung-ju/iguanatexmac 88 | brew install --cask --no-quarantine iguanatexmac latexit-metadata 89 | ``` 90 | 91 | Then follow **5. Verify that paths are set correctly** in the Manual installation instructions below. 92 | 93 | For more details (e.g., how to **upgrade** or **uninstall**), please see [Tsung-Ju's Homebrew instructions](https://github.com/tsung-ju/homebrew-iguanatexmac). 94 | 95 | #### Manual installation 96 | 97 | 1. **Download the "prebuilt files for Mac" zip** from this repository's [Releases page](https://github.com/Jonathan-LeRoux/IguanaTex/releases) 98 | There are 3 files to install: 99 | - `IguanaTex.scpt`: AppleScript file for handling file and folder access 100 | - `libIguanaTexHelper.dylib`: library for creating native text views; source code included in the git repo, under "IguanaTexHelper/" 101 | - `IguanaTex_v1_XX_Y.ppam`: main add-in file 102 | 2. **Install `IguanaTex.scpt`** 103 | 104 | ```bash 105 | mkdir -p ~/Library/Application\ Scripts/com.microsoft.Powerpoint 106 | cp ./IguanaTex.scpt ~/Library/Application\ Scripts/com.microsoft.Powerpoint/IguanaTex.scpt 107 | ``` 108 | 109 | 3. **Install `libIguanaTexHelper.dylib`** 110 | 111 | ```bash 112 | sudo mkdir -p '/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized' 113 | sudo cp ./libIguanaTexHelper.dylib '/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib' 114 | ``` 115 | 116 | 4. **Load the add-in**: Start PowerPoint (restart if it was running when installing the dylib). From the menu bar, select Tools > PowerPoint Add-ins... > '+' , and choose `IguanaTex_v1_XX_Y.ppam` 117 | - The first time you click on one of the add-in buttons, you may be notified that `libIguanaTexHelper.dylib` was blocked. Go to the Mac's Settings, then Security and Privacy, and click "Allow Anyway". 118 | 119 | 5. **Verify that paths are set correctly**: 120 | Click on "Main Settings" in the IguanaTex ribbon tab: 121 | - Set the Temp folder used for file conversions in one of the following ways: 122 | - (Recommended) The simplest is to let Iguanatex pick the Temp folder by selecting "Absolute" and leaving the path empty. The Temp folder will be inside the PowerPoint sandbox and everything will work without having to give permissions. 123 | - (If needed) If you need the Temp folder to be a specific folder outside the sandbox, or if you'd rather it be relative to your PowerPoint presentation (e.g., because you are using specific macros in an external file), you will need to give access permission to that folder to IguanaTex. The best thing to do is to drag and drop that folder from the Finder on top of the PowerPoint application. This will allow you to give permission to the whole folder at least for the current session. 124 | - Verify that the following paths are set correctly by clicking on each "..." button next to them. If the path is correct, this should take you to its location; otherwise, you'll need to navigate to the relevant path. The defaults should match the MacTeX installation locations, but your installation may differ. 125 | - GhostScript 126 | - LaTeX binaries 127 | - libgs.dylib (used in SVG conversions; this should only be needed with older versions of MacTeX; leave empty if you get an error, which may happen if you use MacPorts' TeXLive for example) 128 | 129 | If you cannot find them or if IguanaTex complains that a command did not return, open a terminal and use `locate gs`, `locate pdflatex`, and `locate libgs`. 130 | 131 | 7. (Optional) **Install LaTeXiT-metadata**: 132 | - Needed to convert displays generated with [LaTeXiT](https://www.chachatelier.fr/latexit/) on Mac into IguanaTex displays 133 | - Download [`LaTeXiT-metadata-macos`](https://github.com/Jonathan-LeRoux/IguanaTex/releases/download/v1.60.3/LaTeXiT-metadata-macos) from the Releases page, add executable permission, and either set the path to its location in the "Main Settings" window or copy it to the secure add-in folder: 134 | `chmod 755 ./LaTeXiT-metadata-macos` 135 | `sudo cp ./LaTeXiT-metadata-macos '/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/'` 136 | - The first time LaTeXiT-metadata-macos is called by IguanaTex, Mac OS may block it. Go to the Mac's Settings, then Security and Privacy, and click "Allow Anyway". 137 | - The executable was compiled on Mac OS 10.13 but should work on all versions. Please let me know if you have any issue. 138 | - LaTeXiT-metadata was kindly prepared by Pierre Chatelier, [LaTeXiT](https://www.chachatelier.fr/latexit/)'s author, at my request. Many thanks to him! 139 | - [Source code is now public](https://github.com/LaTeXiT-metadata/LaTeXiT-metadata-MacOS). 140 | 141 | ### Other installation settings 142 | 143 | - If you have a non-standard LaTeX installation, you can specify in Main Settings the folder in which the executables are included, or more generally a prefix to be added to all commands (e.g., `wsl -e` for a LaTeX installation under the Windows Subsystem for Linux). 144 | - If you plan to use Tectonic: 145 | - if you are specifying a path or prefix for the LaTeX installation as explained above, that will be used for the Tectonic executable as well, so please make sure Tectonic is under that path or that it can be called with the specified prefix; 146 | - if you are not specifying any path or prefix, then the Tectonic executable needs to be on your PATH. 147 | - If you would like to have the option of using an external editor, e.g., when debugging LaTeX source code, you can specify the path to that editor in Main Settings. If you would like to use that editor by default over the IguanaTex edit window, check the "use as default" checkbox. 148 | 149 | ## Tips, Bugs, and Known Issues 150 | 151 | ### What to do if something does not work, or does not work as you expected 152 | 153 | Most issues originate from some steps of the installation process described above not being followed: please double-check you went through all the steps. A reboot also often helps after a first installation. 154 | 155 | If you are having trouble installing or using IguanaTex, please see the [Frequently Asked Questions](https://www.jonathanleroux.org/software/iguanatex/faq.html) and check the [Issues](https://github.com/Jonathan-LeRoux/IguanaTex/issues?q=is%3Aissue) on this repo. 156 | 157 | ### Debugging an issue 158 | 159 | When running into an issue while trying to generate a display, the first thing to do is to check the "Debug" box in the Editor window prior to clicking "Generate". This will step through the process of generating the display, so that we can know where the error occurred, and it will give the option to copy each command so that they can be run in a Terminal or Command Prompt. 160 | 161 | If this does not solve the issue, or the issue does not occur during the generation process, the next step is to try to debug in the VBA Editor. To do so: 162 | 163 | - open the source `.pptm` file in PowerPoint. 164 | - open the VBA Editor (`Alt+F11` on Windows, `Tools > Macro > Visual Basic Editor` on Mac). 165 | - search for "Macros" under "Module" in the exploration pane on the left. 166 | - place a breakpoint, for example at Line 7 (`Load LatexForm` under `NewLatexEquation()`) by clicking in the margin. 167 | - Launch the display generation process: 168 | - on Windows, click on the "New LaTeX Display" button in the IguanaTex ribbon (if the add-in is loaded, you will likely have two IguanaTex tabs in the ribbon, one for the loaded add-in and the other for the `.pptm` file: just try one, and if the IguanaTex window appears without hitting the breakpoint, try the other), or in the VBA Editor click `Tools > Macros...` and select `NewLatexEquation` and `Run`. 169 | - on Mac, clicking on the buttons in the ribbon does not work for `.pptm` files, so instead click `Tools > Macro > Macros...` and select `NewLatexEquation` and `Run`. 170 | - The code will stop at the breakpoint. 171 | - Step Over (Shift+F8 on Windows, Shift+⌘+O on Mac) until hitting the bug. If the bug occurs on a line calling another function, you can run again and then Step Into (F8 on Windows, Shift+⌘+I on Mac) when you reach that line. 172 | - Eventually, you'll reach the actual line causing the bug. Now, either try to fix it, or open an issue. 173 | 174 | ### Keyboard shortcuts 175 | 176 | Accelerator keys (i.e., keyboard shortcuts): many of IguanaTex's commands ("Generate", "Cancel", etc) can be accessed by using a combination of modifier keys and a single letter. Look for the underlined letter in the corresponding button's text/label. 177 | 178 | - Windows: Alt + letter. For example, instead of clicking on the "Generate" button, you can use `Alt + g`. (This is the standard Office behavior on Windows) 179 | - Mac: Ctrl + Cmd + letter. For example, instead of clicking on the "Generate" button, you can use `Ctrl + ⌘ + g`. (Accelerator keys are not available in the standard Office for Mac, this was specially coded by Tsung-Ju for IguanaTex) 180 | 181 | ### Known Issues 182 | 183 | - "Picture" displays created on Mac (which are inserted PDFs) appear cropped on Windows ([Issue #32](https://github.com/Jonathan-LeRoux/IguanaTex/issues/32)). Regenerating them on Windows fixes the issue. This seems to be a bug with the way PowerPoint handles some PDFs on Mac, internally storing them as EMF files. The PDFs created by LaTeXiT do not have that issue, however, so there may be a way to circumvent this bug in a future version of IguanaTex. 184 | - IguanaTex macros cannot be added to the Quick Access Toolbar on Mac ([Issue #23](https://github.com/Jonathan-LeRoux/IguanaTex/issues/23)): this is a [known bug](https://answers.microsoft.com/en-us/msoffice/forum/all/can-add-in-commands-be-added-to-the-quick-access/6872187f-3c17-40ee-8620-80a4068edc82) on which Microsoft is allegedly working, although there has been no progress for multiple years. 185 | - There may be some scaling issues when changing the format of a file (Picture <-> Shape, or even within the various SVG and EMF Shape formats). The best way to handle this is to use the "Convert to Shape"/"Convert to Picture" functions, which regenerate the display in the desired format while keeping the size fixed. One can then further modify the content if needed, and the scaling will be correct. 186 | - For Shape (i.e., vector graphics) displays, the default "SVG via DVI w/ dvisvgm" is recommended because of issues sometimes observed with other modes: 187 | - Some displays obtained via "EMF w/ TeX2img" or "EMF w/ pdfiumdraw" appear distorted. This is a PowerPoint bug that sometimes occurs when ungrouping an EMF file into a Shape object. 188 | - Some displays obtained with "SVG via PDF w/ dvisvgm" have symbols or parts of symbol missing. This is because certain lines are represented in PDF by open paths with a certain line width, instead of closed paths, and are thus handled differently by PowerPoint when converting to a Shape object. See [this discussion](https://github.com/mgieseki/dvisvgm/issues/166) for more details. 189 | 190 | ## Stay up to date: IguanaTex Google Group 191 | 192 | To be informed of the release of new versions, you can subscribe to the [IguanaTex Google Group](https://groups.google.com/d/forum/iguanatex). 193 | 194 | ## License 195 | 196 | [![CC BY 3.0][cc-by-image]][cc-by] 197 | 198 | This work is licensed under a 199 | [Creative Commons Attribution 3.0 Unported License][cc-by]. 200 | 201 | [cc-by]: http://creativecommons.org/licenses/by/3.0/ 202 | [cc-by-image]: https://i.creativecommons.org/l/by/3.0/88x31.png 203 | [cc-by-shield]: https://img.shields.io/badge/License-CC%20BY%203.0-lightgrey.svg 204 | -------------------------------------------------------------------------------- /RegenerateForm.frm: -------------------------------------------------------------------------------- 1 | VERSION 5.00 2 | Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} RegenerateForm 3 | Caption = "Regenerating" 4 | ClientHeight = 1920 5 | ClientLeft = 48 6 | ClientTop = 384 7 | ClientWidth = 4032 8 | OleObjectBlob = "RegenerateForm.frx":0000 9 | StartUpPosition = 1 'CenterOwner 10 | End 11 | Attribute VB_Name = "RegenerateForm" 12 | Attribute VB_GlobalNameSpace = False 13 | Attribute VB_Creatable = False 14 | Attribute VB_PredeclaredId = True 15 | Attribute VB_Exposed = False 16 | Option Explicit 17 | 18 | Private Sub UserForm_Initialize() 19 | Me.Top = Application.Top + 110 20 | Me.Left = Application.Left + 25 21 | Me.Height = 120 22 | Me.Width = 210 23 | #If Mac Then 24 | ResizeUserForm Me 25 | #End If 26 | End Sub 27 | 28 | Private Sub UserForm_Activate() 29 | #If Mac Then 30 | MacEnableAccelerators Me 31 | #End If 32 | End Sub 33 | 34 | Sub CommandButtonCancel_Click() 35 | RegenerateContinue = False 36 | Unload RegenerateForm 37 | End Sub 38 | -------------------------------------------------------------------------------- /RegenerateForm.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jonathan-LeRoux/IguanaTex/bf549383004d3443fa5600e21330b521b34049e5/RegenerateForm.frx -------------------------------------------------------------------------------- /RegistryAccess.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "RegistryAccess" 2 | ' Portions taken from: 3 | ' http://www.kbalertz.com/kb_145679.aspx 4 | 5 | Option Explicit 6 | 7 | Public Const REG_SZ As Long = 1 8 | Public Const REG_DWORD As Long = 4 9 | 10 | Public Const HKEY_CLASSES_ROOT = &H80000000 11 | Public Const HKEY_CURRENT_USER = &H80000001 12 | Public Const HKEY_LOCAL_MACHINE = &H80000002 13 | Public Const HKEY_USERS = &H80000003 14 | 15 | Public Const ERROR_NONE = 0 16 | Public Const ERROR_BADDB = 1 17 | Public Const ERROR_BADKEY = 2 18 | Public Const ERROR_CANTOPEN = 3 19 | Public Const ERROR_CANTREAD = 4 20 | Public Const ERROR_CANTWRITE = 5 21 | Public Const ERROR_OUTOFMEMORY = 6 22 | Public Const ERROR_ARENA_TRASHED = 7 23 | Public Const ERROR_ACCESS_DENIED = 8 24 | Public Const ERROR_INVALID_PARAMETERS = 87 25 | Public Const ERROR_NO_MORE_ITEMS = 259 26 | 27 | Public Const KEY_QUERY_VALUE = &H1 28 | Public Const KEY_SET_VALUE = &H2 29 | Public Const KEY_ALL_ACCESS = &H3F 30 | 31 | Public Const REG_OPTION_NON_VOLATILE = 0 32 | 33 | #If Mac Then 34 | Public Function GetRegistryValue(Hive, Keyname, Valuename, DefaultValue) 35 | If Hive <> HKEY_CURRENT_USER Then 36 | MsgBox "GetRegistryValue with Hive other than HKEY_CURRENT_USER is not implemented. return defaultValue." 37 | GetRegistryValue = DefaultValue 38 | Exit Function 39 | End If 40 | 41 | Dim Str As String 42 | 43 | Str = GetSetting("IguanaTex", Keyname, Valuename, "") 44 | If Str = "" Then 45 | GetRegistryValue = DefaultValue 46 | Else 47 | Dim sp() As String 48 | sp = Split(Str, ":", 2) 49 | If UBound(sp) + 1 < 2 Then 50 | GetRegistryValue = DefaultValue 51 | ElseIf sp(0) = "sz" Then 52 | GetRegistryValue = sp(1) 53 | ElseIf sp(0) = "dword" Then 54 | GetRegistryValue = CLng(sp(1)) 55 | Else 56 | GetRegistryValue = DefaultValue 57 | End If 58 | End If 59 | End Function 60 | 61 | 62 | Public Sub SetRegistryValue(Hive, ByRef Keyname As String, ByRef Valuename As String, _ 63 | Valuetype As Long, value As Variant) 64 | If Hive <> HKEY_CURRENT_USER Then 65 | MsgBox "SetRegistryValue with Hive other than HKEY_CURRENT_USER is not implemented." 66 | Exit Sub 67 | End If 68 | 69 | If Valuetype = REG_SZ Then 70 | SaveSetting "IguanaTex", Keyname, Valuename, "sz:" & value 71 | ElseIf Valuetype = REG_DWORD Then 72 | SaveSetting "IguanaTex", Keyname, Valuename, "dword:" & CStr(value) 73 | Else 74 | MsgBox "Error saving registry key." 75 | End If 76 | End Sub 77 | 78 | #Else 79 | 80 | #If VBA7 Then 81 | Declare PtrSafe Function RegCloseKey Lib "advapi32.dll" _ 82 | (ByVal hKey As Long) As Long 83 | Declare PtrSafe Function RegCreateKeyEx Lib "advapi32.dll" Alias _ 84 | "RegCreateKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, _ 85 | ByVal Reserved As Long, ByVal lpClass As String, ByVal dwOptions As Long, _ 86 | ByVal samDesired As Long, ByVal lpSecurityAttributes As Long, _ 87 | phkResult As Long, lpdwDisposition As Long) As Long 88 | Declare PtrSafe Function RegOpenKeyEx Lib "advapi32.dll" Alias _ 89 | "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, _ 90 | ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long 91 | Declare PtrSafe Function RegQueryValueExString Lib "advapi32.dll" Alias _ 92 | "RegQueryValueExW" (ByVal hKey As Long, ByVal lpValueName As LongPtr, _ 93 | ByVal lpReserved As Long, lpType As Long, ByVal lpData As LongPtr, _ 94 | lpcbData As Long) As Long 95 | Declare PtrSafe Function RegQueryValueExLong Lib "advapi32.dll" Alias _ 96 | "RegQueryValueExW" (ByVal hKey As Long, ByVal lpValueName As LongPtr, _ 97 | ByVal lpReserved As Long, lpType As Long, lpData As Long, _ 98 | lpcbData As Long) As Long 99 | Declare PtrSafe Function RegQueryValueExNULL Lib "advapi32.dll" Alias _ 100 | "RegQueryValueExW" (ByVal hKey As Long, ByVal lpValueName As LongPtr, _ 101 | ByVal lpReserved As Long, lpType As Long, ByVal lpData As Long, _ 102 | lpcbData As Long) As Long 103 | Declare PtrSafe Function RegSetValueExString Lib "advapi32.dll" Alias _ 104 | "RegSetValueExW" (ByVal hKey As Long, ByVal lpValueName As LongPtr, _ 105 | ByVal Reserved As Long, ByVal dwType As Long, ByVal lpValue As LongPtr, _ 106 | ByVal cbData As Long) As Long 107 | Declare PtrSafe Function RegSetValueExLong Lib "advapi32.dll" Alias _ 108 | "RegSetValueExW" (ByVal hKey As Long, ByVal lpValueName As LongPtr, _ 109 | ByVal Reserved As Long, ByVal dwType As Long, lpValue As Long, _ 110 | ByVal cbData As Long) As Long 111 | #Else 112 | Declare Function RegCloseKey Lib "advapi32.dll" _ 113 | (ByVal hKey As Long) As Long 114 | Declare Function RegCreateKeyEx Lib "advapi32.dll" Alias _ 115 | "RegCreateKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, _ 116 | ByVal Reserved As Long, ByVal lpClass As String, ByVal dwOptions As Long, _ 117 | ByVal samDesired As Long, ByVal lpSecurityAttributes As Long, _ 118 | phkResult As Long, lpdwDisposition As Long) As Long 119 | Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias _ 120 | "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, _ 121 | ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long 122 | Declare Function RegQueryValueExString Lib "advapi32.dll" Alias _ 123 | "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, _ 124 | ByVal lpReserved As Long, lpType As Long, ByVal lpData As String, _ 125 | lpcbData As Long) As Long 126 | Declare Function RegQueryValueExLong Lib "advapi32.dll" Alias _ 127 | "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, _ 128 | ByVal lpReserved As Long, lpType As Long, lpData As Long, _ 129 | lpcbData As Long) As Long 130 | Declare Function RegQueryValueExNULL Lib "advapi32.dll" Alias _ 131 | "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, _ 132 | ByVal lpReserved As Long, lpType As Long, ByVal lpData As Long, _ 133 | lpcbData As Long) As Long 134 | Declare Function RegSetValueExString Lib "advapi32.dll" Alias _ 135 | "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, _ 136 | ByVal Reserved As Long, ByVal dwType As Long, ByVal lpValue As String, _ 137 | ByVal cbData As Long) As Long 138 | Declare Function RegSetValueExLong Lib "advapi32.dll" Alias _ 139 | "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, _ 140 | ByVal Reserved As Long, ByVal dwType As Long, lpValue As Long, _ 141 | ByVal cbData As Long) As Long 142 | #End If 143 | 144 | Public Function SetValueEx(ByVal hKey As Long, sValueName As String, _ 145 | lType As Long, vValue As Variant) As Long 146 | Dim lValue As Long 147 | Dim sValue As String 148 | Select Case lType 149 | Case REG_SZ 150 | sValue = vValue & Chr$(0) 151 | #If VBA7 Then 152 | SetValueEx = RegSetValueExString(hKey, StrPtr(sValueName), 0&, _ 153 | lType, StrPtr(sValue), LenB(sValue)) 154 | #Else 155 | SetValueEx = RegSetValueExString(hKey, sValueName, 0&, _ 156 | lType, sValue, Len(sValue)) 157 | #End If 158 | Case REG_DWORD 159 | lValue = vValue 160 | #If VBA7 Then 161 | SetValueEx = RegSetValueExLong(hKey, StrPtr(sValueName), 0&, _ 162 | lType, lValue, 4) 163 | #Else 164 | SetValueEx = RegSetValueExLong(hKey, sValueName, 0&, _ 165 | lType, lValue, 4) 166 | #End If 167 | End Select 168 | End Function 169 | 170 | Public Function QueryValueEx(ByVal lhKey As Long, _ 171 | ByVal szValueName As String, vValue As Variant) As Long 172 | Dim cch As Long 173 | Dim lrc As Long 174 | Dim lType As Long 175 | Dim lValue As Long 176 | Dim sValue As String 177 | 178 | On Error GoTo QueryValueExError 179 | 180 | ' Determine the size and type of data to be read 181 | #If VBA7 Then 182 | lrc = RegQueryValueExNULL(lhKey, StrPtr(szValueName), 0&, lType, 0&, cch) 183 | #Else 184 | lrc = RegQueryValueExNULL(lhKey, szValueName, 0&, lType, 0&, cch) 185 | #End If 186 | If lrc <> ERROR_NONE Then Err.Raise 5 187 | 188 | Select Case lType 189 | ' For strings 190 | Case REG_SZ: 191 | #If VBA7 Then 192 | ' Dividing by 2 because cch is in Bytes, 193 | ' but String is allocated by number of 2-Byte characters 194 | sValue = String(cch / 2, 0) 195 | lrc = RegQueryValueExString(lhKey, StrPtr(szValueName), 0&, lType, _ 196 | StrPtr(sValue), cch) 197 | If lrc = ERROR_NONE Then 198 | vValue = Left$(sValue, cch / 2 - 1) 199 | Else 200 | vValue = Empty 201 | End If 202 | #Else 203 | ' For older versions of Office. 204 | ' No proper support of Unicode strings, which will be cut 205 | sValue = String(cch, 0) 206 | lrc = RegQueryValueExString(lhKey, szValueName, 0&, lType, _ 207 | sValue, cch) 208 | If lrc = ERROR_NONE Then 209 | vValue = Left$(sValue, cch - 1) 210 | Else 211 | vValue = Empty 212 | End If 213 | #End If 214 | ' For DWORDS 215 | Case REG_DWORD: 216 | #If VBA7 Then 217 | lrc = RegQueryValueExLong(lhKey, StrPtr(szValueName), 0&, lType, _ 218 | lValue, cch) 219 | #Else 220 | lrc = RegQueryValueExLong(lhKey, szValueName, 0&, lType, _ 221 | lValue, cch) 222 | #End If 223 | 224 | If lrc = ERROR_NONE Then vValue = lValue 225 | Case Else 226 | 'all other data types not supported 227 | lrc = -1 228 | End Select 229 | 230 | QueryValueExExit: 231 | QueryValueEx = lrc 232 | Exit Function 233 | 234 | QueryValueExError: 235 | Resume QueryValueExExit 236 | End Function 237 | 238 | Private Sub CreateNewKey(sNewKeyName As String, lPredefinedKey As Long) 239 | Dim hNewKey As Long 'handle to the new key 240 | Dim lRetVal As Long 'result of the RegCreateKeyEx function 241 | 242 | lRetVal = RegCreateKeyEx(lPredefinedKey, sNewKeyName, 0&, _ 243 | vbNullString, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, _ 244 | 0&, hNewKey, lRetVal) 245 | RegCloseKey (hNewKey) 246 | End Sub 247 | 248 | Public Function GetRegistryValue(Hive As Long, Keyname As String, Valuename As String, DefaultValue As Variant) As Variant 249 | Dim lRetVal As Long 'result of the API functions 250 | Dim hKey As Long 'handle of opened key 251 | Dim vValue As Variant 'setting of queried value 252 | 253 | lRetVal = RegOpenKeyEx(Hive, Keyname, 0, KEY_QUERY_VALUE, hKey) 254 | lRetVal = QueryValueEx(hKey, Valuename, vValue) 255 | RegCloseKey (hKey) 256 | 257 | If (lRetVal = 0) Then 258 | GetRegistryValue = vValue 259 | Else 260 | GetRegistryValue = DefaultValue 261 | End If 262 | End Function 263 | 264 | Public Sub SetRegistryValue(Hive As Long, ByRef Keyname As String, ByRef Valuename As String, _ 265 | Valuetype As Long, value As Variant) 266 | Dim lRetVal As Long 'result of the SetValueEx function 267 | Dim hKey As Long 'handle of open key 268 | 269 | 'open the specified key 270 | lRetVal = RegOpenKeyEx(Hive, Keyname, 0, KEY_SET_VALUE, hKey) 271 | If (lRetVal = 0) Then 272 | lRetVal = SetValueEx(hKey, Valuename, Valuetype, value) 273 | RegCloseKey (hKey) 274 | Else 275 | RegCloseKey (hKey) 276 | Dim MyKeyname As String 277 | MyKeyname = Keyname 278 | Dim MyPredefKey As Long 279 | MyPredefKey = Hive 280 | CreateNewKey MyKeyname, MyPredefKey 281 | lRetVal = RegOpenKeyEx(Hive, Keyname, 0, KEY_SET_VALUE, hKey) 282 | lRetVal = SetValueEx(hKey, Valuename, Valuetype, value) 283 | RegCloseKey (hKey) 284 | 285 | End If 286 | 287 | If (lRetVal <> 0) Then 288 | MsgBox "Error saving registry key." 289 | End If 290 | End Sub 291 | 292 | #End If 293 | 294 | 295 | -------------------------------------------------------------------------------- /SetTempForm.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jonathan-LeRoux/IguanaTex/bf549383004d3443fa5600e21330b521b34049e5/SetTempForm.frx -------------------------------------------------------------------------------- /ShellWait.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "ShellWait" 2 | Option Explicit 3 | 4 | #If Mac Then 5 | Public Function Execute(ByVal CommandLine As String, StartupDir As String, Optional debugMode As Boolean = False, Optional WaitTime As Long = -1) As Long 6 | Dim TeXExePath As String 7 | TeXExePath = GetFolderFromPath(GetITSetting("TeXExePath", DEFAULT_TEX_EXE_PATH)) 8 | If TeXExePath <> vbNullString Then 9 | TeXExePath = TeXExePath & ":" 10 | End If 11 | Dim TeXExtraPath As String 12 | TeXExtraPath = GetITSetting("TeXExtraPath", DEFAULT_TEX_EXTRA_PATH) 13 | If TeXExtraPath <> vbNullString Then 14 | TeXExtraPath = TeXExtraPath & ":" 15 | End If 16 | If debugMode Then 17 | ShowError vbNullString, CommandLine, "Debug mode", "Next command:", "Continue" 18 | End If 19 | Execute = CLng(AppleScriptTask("IguanaTex.scpt", "MacExecute", _ 20 | "export PATH=" & ShellEscape(TeXExePath) & ShellEscape(TeXExtraPath) & """$PATH""" & " && " & _ 21 | "cd " & ShellEscape(StartupDir) & " && " & _ 22 | CommandLine)) 23 | End Function 24 | 25 | #Else 26 | ' Portions of code below taken from: 27 | ' http://www.mvps.org/access/api/api0004.htm 28 | ' Courtesy of Terry Kreft 29 | 30 | Private Const STARTF_USESHOWWINDOW As Long = &H1 31 | Private Const NORMAL_PRIORITY_CLASS = &H20& 32 | Private Const INFINITE = -1& 33 | 34 | Private Type STARTUPINFO 35 | cb As Long 36 | lpReserved As String 37 | lpDesktop As String 38 | lpTitle As String 39 | dwX As Long 40 | dwY As Long 41 | dwXSize As Long 42 | dwYSize As Long 43 | dwXCountChars As Long 44 | dwYCountChars As Long 45 | dwFillAttribute As Long 46 | dwFlags As Long 47 | wShowWindow As Integer 48 | cbReserved2 As Integer 49 | lpReserved2 As Long 50 | hStdInput As Long 51 | hStdOutput As Long 52 | hStdError As Long 53 | End Type 54 | 55 | Private Type PROCESS_INFORMATION 56 | hProcess As Long 57 | hThread As Long 58 | dwProcessID As Long 59 | dwThreadId As Long 60 | End Type 61 | 62 | #If VBA7 Then 63 | Private Declare PtrSafe Function WaitForSingleObject Lib "kernel32" (ByVal _ 64 | hHandle As Long, ByVal dwMilliseconds As Long) As Long 65 | 66 | Private Declare PtrSafe Function CreateProcessA Lib "kernel32" (ByVal _ 67 | lpApplicationName As Long, ByVal lpCommandLine As String, ByVal _ 68 | lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _ 69 | ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _ 70 | ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, _ 71 | lpStartupInfo As STARTUPINFO, lpProcessInformation As _ 72 | PROCESS_INFORMATION) As Long 73 | 74 | Private Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal _ 75 | hObject As Long) As Long 76 | 77 | Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel32" _ 78 | (ByVal hProcess As Long, lpExitCode As Long) As Long 79 | 80 | Private Declare PtrSafe Function GetLastError Lib "kernel32" () As Long 81 | 82 | Public Declare PtrSafe Function TerminateProcess Lib "kernel32" _ 83 | (ByVal hProcess As Long, ByVal uExitCode As Long) As Long 84 | 85 | Public Declare PtrSafe Function ShellExecute Lib "shell32.dll" _ 86 | Alias "ShellExecuteA" (ByVal hWnd As Long, ByVal Operation As String, _ 87 | ByVal FileName As String, Optional ByVal Parameters As String, _ 88 | Optional ByVal directory As String, _ 89 | Optional ByVal WindowStyle As Long = vbMinimizedFocus _ 90 | ) As Long 91 | 92 | #Else 93 | Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _ 94 | hHandle As Long, ByVal dwMilliseconds As Long) As Long 95 | 96 | Private Declare Function CreateProcessA Lib "kernel32" (ByVal _ 97 | lpApplicationName As Long, ByVal lpCommandLine As String, ByVal _ 98 | lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _ 99 | ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _ 100 | ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As String, _ 101 | lpStartupInfo As STARTUPINFO, lpProcessInformation As _ 102 | PROCESS_INFORMATION) As Long 103 | 104 | Private Declare Function CloseHandle Lib "kernel32" (ByVal _ 105 | hObject As Long) As Long 106 | 107 | Private Declare Function GetExitCodeProcess Lib "kernel32" _ 108 | (ByVal hProcess As Long, lpExitCode As Long) As Long 109 | 110 | Private Declare Function GetLastError Lib "kernel32" () As Long 111 | 112 | Public Declare Function TerminateProcess Lib "kernel32" _ 113 | (ByVal hProcess As Long, ByVal uExitCode As Long) As Long 114 | 115 | Public Declare Function ShellExecute Lib "shell32.dll" _ 116 | Alias "ShellExecuteA" (ByVal hWnd As Long, ByVal Operation As String, _ 117 | ByVal Filename As String, Optional ByVal Parameters As String, _ 118 | Optional ByVal Directory As String, _ 119 | Optional ByVal WindowStyle As Long = vbMinimizedFocus _ 120 | ) As Long 121 | #End If 122 | 123 | 124 | Public Function ShellWait(pathname As String, Optional StartupDir As String, Optional WindowStyle As Long, Optional WaitTime As Long = -1) As Long 125 | Dim proc As PROCESS_INFORMATION 126 | Dim start As STARTUPINFO 127 | Dim ret As Long 128 | Dim exitcode As Long 129 | Dim lastError As Long 130 | Dim retWait As Long 131 | 132 | ' Initialize the STARTUPINFO structure: 133 | With start 134 | .cb = Len(start) 135 | If Not IsMissing(WindowStyle) Then 136 | .dwFlags = STARTF_USESHOWWINDOW 137 | .wShowWindow = WindowStyle 138 | End If 139 | End With 140 | Dim sdir As String 141 | If IsMissing(StartupDir) Then 142 | sdir = vbNullString 143 | Else 144 | sdir = StartupDir 145 | End If 146 | 147 | ' Start the shelled application: 148 | ret& = CreateProcessA(0&, pathname, 0&, 0&, 1&, _ 149 | NORMAL_PRIORITY_CLASS, 0&, sdir, start, proc) 150 | lastError& = GetLastError() 151 | If (ret& = 0) Then 152 | MsgBox "Could not start process: '" & pathname & "'. GetLastError returned " & Str$(lastError&) 153 | ShellWait = 1 154 | Exit Function 155 | End If 156 | 157 | ' Wait for the shelled application to finish: 158 | If WaitTime > 0 Then 159 | retWait& = WaitForSingleObject(proc.hProcess, WaitTime) 160 | Else 161 | retWait& = WaitForSingleObject(proc.hProcess, INFINITE) 162 | End If 163 | ' Get return value 164 | exitcode& = 1234 165 | ret& = GetExitCodeProcess(proc.hProcess, exitcode&) 166 | If (ret& = 0) Then 167 | lastError& = GetLastError() 168 | MsgBox "GetExitCodeProcess returned " + Str$(ret&) + ", GetLastError returned " + Str$(lastError&) 169 | End If 170 | ' Tidy up if time out 171 | If (retWait& = 258) Then 172 | ret& = TerminateProcess(proc.hProcess, 0) 173 | End If 174 | ' Close handle 175 | ret& = CloseHandle(proc.hProcess) 176 | ShellWait = exitcode& 177 | End Function 178 | 179 | Public Function Execute(CommandLine As String, StartupDir As String, Optional debugMode As Boolean = False, Optional WaitTime As Long = -1) As Long 180 | Dim RetVal As Long 181 | If debugMode Then 182 | ' Clipboard CommandLine 183 | ' MsgBox CommandLine, , StartupDir 184 | ShowError vbNullString, CommandLine, "Debug mode", "Next command:", "Continue" 185 | RetVal = ShellWait(CommandLine, StartupDir, 1&, WaitTime) 186 | Else 187 | RetVal = ShellWait(CommandLine, StartupDir, , WaitTime) 188 | End If 189 | Execute = RetVal 190 | End Function 191 | #End If ' Mac 192 | 193 | 194 | -------------------------------------------------------------------------------- /TextWindow.cls: -------------------------------------------------------------------------------- 1 | VERSION 1.0 CLASS 2 | BEGIN 3 | MultiUse = -1 'True 4 | END 5 | Attribute VB_Name = "TextWindow" 6 | Attribute VB_GlobalNameSpace = False 7 | Attribute VB_Creatable = False 8 | Attribute VB_PredeclaredId = False 9 | Attribute VB_Exposed = False 10 | ' Replacement for TextBox 11 | 12 | Option Explicit 13 | 14 | #If Mac Then 15 | Private Declare PtrSafe Function TWInit _ 16 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 17 | () As LongLong 18 | 19 | Private Declare PtrSafe Function TWTerm _ 20 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 21 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As LongLong 22 | 23 | Private Declare PtrSafe Function TWSetResizeTarget _ 24 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 25 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As LongLong 26 | 27 | Private Declare PtrSafe Function TWResize _ 28 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 29 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As LongLong 30 | 31 | Private Declare PtrSafe Function TWShow _ 32 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 33 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As LongLong 34 | 35 | Private Declare PtrSafe Function TWHide _ 36 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 37 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As LongLong 38 | 39 | Private Declare PtrSafe Function TWFocus _ 40 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 41 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As LongLong 42 | 43 | Private Declare PtrSafe Function TWGetByteLength _ 44 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 45 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As LongLong 46 | 47 | Private Declare PtrSafe Function TWGetBytes _ 48 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 49 | (ByVal Handle As LongLong, ByVal buffer As LongPtr, ByVal length As LongLong, ByVal d As LongLong) As LongLong 50 | 51 | Private Declare PtrSafe Function TWSetBytes _ 52 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 53 | (ByVal Handle As LongLong, ByVal data As LongPtr, ByVal length As LongLong, ByVal d As LongLong) As LongLong 54 | 55 | Private Declare PtrSafe Function TWGetSelStart _ 56 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 57 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As LongLong 58 | 59 | Private Declare PtrSafe Function TWSetSelStart _ 60 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 61 | (ByVal Handle As LongLong, ByVal value As LongLong, ByVal c As LongLong, ByVal d As LongLong) As LongLong 62 | 63 | Private Declare PtrSafe Function TWGetWordWrap _ 64 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 65 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As LongLong 66 | 67 | Private Declare PtrSafe Function TWSetWordWrap _ 68 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 69 | (ByVal Handle As LongLong, ByVal value As LongLong, ByVal c As LongLong, ByVal d As LongLong) As LongLong 70 | 71 | Private Const UNUSED As LongLong = 0 72 | 73 | ' members 74 | Private mHandle As LongLong 75 | Private mFont As New TextWindowFont 76 | 77 | ' properties 78 | Public Property Get Font() As TextWindowFont 79 | Set Font = mFont 80 | End Property 81 | 82 | Public Property Get Text() As String 83 | Dim length As LongLong 84 | length = TWGetByteLength(mHandle, UNUSED, UNUSED, UNUSED) 85 | 86 | If length <= 0 Then 87 | Text = "" 88 | Exit Property 89 | End If 90 | 91 | Dim bytes() As Byte 92 | Dim usedLength As LongLong 93 | ReDim bytes(CLng(length - 1)) 94 | usedLength = TWGetBytes(mHandle, VarPtr(bytes(0)), length, UNUSED) 95 | 96 | If usedLength <= 0 Then 97 | Text = "" 98 | Exit Property 99 | End If 100 | 101 | ReDim Preserve bytes(CLng(usedLength - 1)) 102 | Text = bytes 103 | End Property 104 | 105 | Public Property Let Text(value As String) 106 | Dim bytes() As Byte 107 | Dim length As LongLong 108 | bytes = value 109 | length = ArrayLength(bytes) 110 | If length > 0 Then 111 | TWSetBytes mHandle, VarPtr(bytes(0)), length, UNUSED 112 | Else 113 | TWSetBytes mHandle, 0, 0, UNUSED 114 | End If 115 | End Property 116 | 117 | Public Property Get SelStart() As Integer 118 | SelStart = CInt(TWGetSelStart(mHandle, UNUSED, UNUSED, UNUSED)) 119 | End Property 120 | 121 | Public Property Let SelStart(value As Integer) 122 | TWSetSelStart mHandle, CLngLng(value), UNUSED, UNUSED 123 | End Property 124 | 125 | Public Property Get WordWrap() As Boolean 126 | WordWrap = TWGetWordWrap(mHandle, UNUSED, UNUSED, UNUSED) 127 | End Property 128 | 129 | Public Property Let WordWrap(value As Boolean) 130 | TWSetWordWrap mHandle, value, UNUSED, UNUSED 131 | End Property 132 | 133 | ' constructor/destructor 134 | Private Sub Class_Initialize() 135 | mHandle = TWInit 136 | mFont.Init mHandle 137 | End Sub 138 | 139 | Private Sub Class_Terminate() 140 | TWTerm mHandle, UNUSED, UNUSED, UNUSED 141 | End Sub 142 | 143 | ' methods 144 | Public Sub Show() 145 | TWShow mHandle, UNUSED, UNUSED, UNUSED 146 | End Sub 147 | 148 | Public Sub Hide() 149 | TWHide mHandle, UNUSED, UNUSED, UNUSED 150 | End Sub 151 | 152 | Public Sub SetResizeTarget(target As Control, parentForm As UserForm) 153 | Dim backup As Control 154 | Set backup = parentForm.ActiveControl 155 | target.SetFocus 156 | TWSetResizeTarget mHandle, UNUSED, UNUSED, UNUSED 157 | If Not backup Is Nothing Then 158 | backup.SetFocus 159 | End If 160 | End Sub 161 | 162 | Public Sub ResizeAsTarget() 163 | TWResize mHandle, UNUSED, UNUSED, UNUSED 164 | End Sub 165 | 166 | Public Sub SetFocus() 167 | TWFocus mHandle, UNUSED, UNUSED, UNUSED 168 | End Sub 169 | 170 | #End If 171 | 172 | 173 | -------------------------------------------------------------------------------- /TextWindowFont.cls: -------------------------------------------------------------------------------- 1 | VERSION 1.0 CLASS 2 | BEGIN 3 | MultiUse = -1 'True 4 | END 5 | Attribute VB_Name = "TextWindowFont" 6 | Attribute VB_GlobalNameSpace = False 7 | Attribute VB_Creatable = False 8 | Attribute VB_PredeclaredId = False 9 | Attribute VB_Exposed = False 10 | ' Replacement for TextBox.Font 11 | 12 | Option Explicit 13 | 14 | #If Mac Then 15 | Private Declare PtrSafe Function TWGetFontSize _ 16 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 17 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As Double 18 | 19 | Private Declare PtrSafe Function TWSetFontSize _ 20 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 21 | (ByVal Handle As LongLong, ByVal value As Double, ByVal c As LongLong, ByVal d As LongLong) As LongLong 22 | 23 | Private Const UNUSED As LongLong = 0 24 | 25 | ' members 26 | Public mHandle As LongLong 27 | 28 | ' properties 29 | Public Property Get Size() As Double 30 | Size = CCur(TWGetFontSize(mHandle, UNUSED, UNUSED, UNUSED)) 31 | End Property 32 | 33 | Public Property Let Size(value As Double) 34 | TWSetFontSize mHandle, val(value), UNUSED, UNUSED 35 | End Property 36 | 37 | ' methods 38 | Public Sub Init(Handle As LongLong) 39 | mHandle = Handle 40 | End Sub 41 | 42 | #End If 43 | 44 | 45 | -------------------------------------------------------------------------------- /change.log: -------------------------------------------------------------------------------- 1 | New in IguanaTex 1.62.1 (January 31, 2025) 2 | - (Win/Mac) Added checkbox to let user decide whether to specify the color of a Shape display or not. Specifying a color in IguanaTex can interfere with color commands in the LaTeX source, or corrupt some displays such as tikz diagrams (fixes https://github.com/Jonathan-LeRoux/IguanaTex/issues/80) 3 | - (Win/Mac) Fixed handling of VBA Shape Tags for different locales (fixes https://github.com/Jonathan-LeRoux/IguanaTex/pull/79) 4 | - (Win/Mac) Fixed bug where error running LaTeX compilation before generation of a .log file would display a previous .log file in certain cases. 5 | 6 | New in IguanaTex 1.62 (December 3, 2024) 7 | - (Win/Mac) Added support for Tectonic (fixes https://github.com/Jonathan-LeRoux/IguanaTex/issues/63) 8 | - (Win/Mac) Allowed for custom prefix for LaTeX commands instead of only a folder specifying a path. This for example allows using a LaTeX installation under the Windows Subsystem for Linux via the prefix `wsl -e ` (because wsl does not support quotes around the command, it is treated as a special case). (fixes https://github.com/Jonathan-LeRoux/IguanaTex/issues/64) 9 | - (Win/Mac) Added button to directly generate from file without first loading into the edit window. File path in editor window's "Read from file" is now also stored when clicking "Make Default". Created macro "LoadDefaultFileAndGenerate" to generate display from default file (enables 1-click generation from file by adding macro to Quick Access Toolbar, currently only on Windows due to Microsoft bug on Mac). (fixes https://github.com/Jonathan-LeRoux/IguanaTex/issues/66 and https://github.com/Jonathan-LeRoux/IguanaTex/issues/67) 10 | - (Win/Mac) Added option to set a Fill color for Shape objects in the editor window. The color is stored when clicking "Make Default". (fixes https://github.com/Jonathan-LeRoux/IguanaTex/issues/68) 11 | - (Win/Mac) Added ability to export/import settings to/from XML (fixes https://github.com/Jonathan-LeRoux/IguanaTex/issues/71) 12 | - (Win/Mac) Added test to make sure that the temporary file IguanaTex_tmp.tex can be created, to avoid raising an error (fixes https://github.com/Jonathan-LeRoux/IguanaTex/issues/77) 13 | - (Win/Mac) Only settings that are currently visible and active in the Editor window now get saved when clicking "Make Default" (all used to be saved). 14 | - (Win/Mac) Added pop-ups (i.e., ControlTipText) to some buttons to remind the user about associated keyboard shortcut (i.e., Accelerator); fixed order of items when using Tab in Main Settings. 15 | - (Win/Mac) Update some default paths 16 | - (Mac) Fixed editor window size not being saved when clicking "Make default". The editor window size can also be set in the Main Settings on Mac. 17 | - (Mac) Automatically reset Temp folder path to default if path is set to empty 18 | 19 | New in IguanaTex 1.61 (March 27, 2024) 20 | - (Win/Mac) Changed Bitmap/Vector naming to Picture/Shape, to reflect the actual difference in how PowerPoint handles each type of display. The naming also better suits the fact that Picture displays on Mac are PDF and thus cannot be described as Bitmap. (fixes https://github.com/Jonathan-LeRoux/IguanaTex/issues/41) 21 | - (Win/Mac) Raise an error if user tries to use a combination of engine and output which requires ImageMagick without its path pointing to a file that exists (i.e., PNG output with all engines other than "latex (DVI)"). 22 | - (Mac) Implemented PNG support for Mac 23 | - (Mac) Added option in Main Settings to specify extra path(s) to handle packages that require external executables such as pygmentize (fixes https://github.com/Jonathan-LeRoux/IguanaTex/issues/55) 24 | - (Win/Mac) Added option in Main Settings to decide whether to include Alternative Text or not 25 | - (Win/Mac) Fixed bug that could occur when using dvipng and there exists already a PNG file from a prior run. 26 | - (Win/Mac) Improved handling of error when PowerPoint version does not support conversion of SVG to Shape. (somewhat fixes https://github.com/Jonathan-LeRoux/IguanaTex/issues/54) 27 | - (Win/Mac) Fixed bugs in the Load Vector Graphics File function: it was impossible to load DVI/XDV files, and they would not have been processed correctly anyway; options for post-processing in the EMF conversion case were incorrectly disabled. 28 | 29 | New in IguanaTex 1.60.3 (October 13, 2023) 30 | - (Win/Mac) Fixed bug where extracting a LaTeXiT display (or simply checking if a display was created with LaTeXiT) would replace the clipboard text 31 | - (Win/Mac) Fixed bug that resulted in unnecessarily checking if every display in a slide is a LaTeX display. This resulted in significant slowdowns particularly when checking for potential LaTeXiT displays is enabled. Code will now only check when necessary, and when necessary will only check the first time it encounters a given display. 32 | 33 | New in IguanaTex 1.60.2 (August 8, 2022) 34 | - (Win) Fixed bug occurring when using the Insert Vector Graphics File function with a presentation in a OneDrive/SharePoint directory 35 | 36 | New in IguanaTex 1.60.1 (May 26, 2022) 37 | - (Win/Mac) Fixed bug that would occur when no slide is selected 38 | - (Win) Fixed bug that prevented the add-in from running on 32 bit Windows 39 | - (Win) Changed default ImageMagick executable to magick.exe 40 | - (Mac) Moved back to using a very thin margin on Bitmap/PDF displays on Mac. This results in the displays being cropped when viewed on Windows, but at least the size is consistent, and Windows users can "regenerate" the display in PNG at the right size by using the "rasterize" function. 41 | 42 | New in IguanaTex 1.60 (May 20, 2022) 43 | - (Win/Mac) Changed Main Settings icon so that it works also on Mac (ControlsGallery icon is not available on Office for Mac, switched to ControlToolboxOutlook) 44 | - (Win/Mac) Replaced CDbl by Val in bounding box computation (fixes https://github.com/Jonathan-LeRoux/IguanaTex/issues/18) 45 | - (Win/Mac) Implemented SVG generation via XDV/DVI file with dvisvgm (the original PDF->SVG vector route is still available as another option). This circumvents issue with some symbols when converting to SVG via PDF (https://github.com/Jonathan-LeRoux/IguanaTex/issues/22). Added ControlTipText in Main Settings menu recommending the SVG via DVI route. Note that I considered adding more general support for XDV/DVI for xelatex, lualatex, and platex, but there is no good way to convert straight to PNG for the XDV/DVI files generated by these engines. Note also that platex already goes through DVI to generate PDF (and then PNG/EMF/SVG). 46 | - (Win/Mac) Added DVI/XDV support when loading vector graphics files 47 | - (Win/Mac) Refactored and simplified compilation pipeline. 48 | - (Win/Mac) Fixed bug when loading EPS file. 49 | - (Win/Mac) Made the "Close/Continue" button in the Error/Debug window the default selected button. As as side-effect, it is now clearer on Mac that clicking the "Copy" button is having an effect because the button becomes selected. Unfortunately, command buttons do not appear depressed when clicked on Mac, and because "Copy" does not have any visible effect, it wasn't clear that it was working. 50 | - (Win/Mac) Fixed bug that lead to resize issues when a display's file format changed to another during regeneration (e.g., PDF<->PNG) 51 | - (Win/Mac) On Windows, updated instructions regarding setting ImageMagick's path to magick.exe instead of convert.exe; on Mac, removed irrelevant reference in the Readme's instructions and removed the path selection in the Main Settings. 52 | - (Mac) Enabled copy, cut, paste, select all, undo, redo globally in all text forms, via usual Command+Key keyboard shortcuts (This is a major feat, thanks Tsung-Ju!!) 53 | - (Mac) Enabled shortcuts/accelerators on Mac. The accelerators are mapped to “ctrl+cmd+*” to avoid collision with system shortcuts. (Another major feat, thanks Tsung-Ju!!) 54 | - (Mac) Changed default path for LaTeXiT-metadata application on Mac to /Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/LaTeXiT-metadata-macos, and added test for its existence if the file is under that folder. We do not check otherwise because this would trigger a permission request. 55 | - (Mac) Debug option on Mac now shows command that will be run and offers the user to copy it, similarly to Windows. The only remaining difference is that the output of each run is only shown on Windows, not Mac. 56 | - (Win) Added proper unicode support for strings saved to the registry (fixes https://github.com/Jonathan-LeRoux/IguanaTex/issues/17). 57 | - (Win) Automatically replace gswin32.exe/gswin64.exe with gswin32c.exe/gswin64c.exe (with a "c") 58 | - (Win) Removed https://github.com/Jonathan-LeRoux/IguanaTex/blob/87f5b079812c75479641f55e15ac2166c94a0016/LatexForm.frm#L161 to allow use of LaTeX installations that do not rely on .exe binaries 59 | 60 | New in IguanaTex 1.59.1 (February 17, 2022) 61 | - (Mac) Add-in is now M1 compatible (new dylib, fixed bug in TextWindowFont) 62 | 63 | New in IguanaTex 1.59 (April 25, 2021) 64 | - Added Mac support: 65 | * integrated original Mac port by Tsung-Ju Chiang (https://github.com/ray851107/IguanaTexMac) into latest Windows code, leading to single code base supporting both platforms. 66 | * fixed minor issues with original Mac port: made UserForms appear the same size as on Windows (they used to be 3/4 smaller) and tweaked labels so that no text gets truncated; removed Accelerators, which are not implemented on VBA for Mac; ... 67 | * replaced PNG with PDF for "Bitmap" on Mac (except when selecting DVIPNG compilation route): PDFs are inserted as pictures on Mac, even though they're really vector graphics under the hood (internally stored as EMF); they cannot be converted into Shapes, unfortunately. 68 | * enabled "Vector" support on Mac, in which a display is inserted as SVG and converted into a Shape object. Contrary to EMF on Windows, Shapes obtained from SVG cannot be "ungrouped" so that individual elements can be modified independently. User needs to set path to libgs.9.dylib in Main Settings (if default one is not correct). 69 | * enabled support for "Load vector graphics file" on Mac, with support for PS/EPS/PDF/SVG (no EMF at this point and for the foreseeable future). SVG is used for converting PS/EPS/PDF before insertion, which means that the inserted Shape cannot be freely decomposed into smaller elements, unfortunately. 70 | * added options for setting the default height/width of the editor window in Main Settings 71 | * enabled support for dynamically resizable editor window on Mac (Thanks, Tsung-Ju!) 72 | - Significant code cleaning and refactoring: all variable declarations enforced via "Option Explicit"; coding style improvements suggested by Rubberduck; redundant code made into separate Subs/Functions. 73 | - Added SVG support on Windows (Office 365 only). See above for Mac. 74 | - Added option for selecting between SVG, EMF via TeX2img's pdfiumdraw (.tex->.pdf->.emf conversion, fast), and EMF via TeX2img itself (direct .tex->.emf conversion, slower but potentially more robust). SVG seems to lead to the best looking outcome, but one downside is that the obtained Shape cannot be "ungrouped", so that one cannot interact with individual elements. 75 | - Added option for selecting between SVG and EMF for conversion when inserting a vector graphics file, and added option to skip shape cleanup procedure, which may be irrelevant and not work with EMF or EPS files generated by some software. 76 | - Added support for reading LaTeX source from images inserted from LaTeXiT: this requires downloading executables (different ones on Windows and Mac) that parse the EMF/PDF files generated by LaTeXiT to retrieve the source. Major thanks to Pierre Chatelier, the developer of LaTeXiT, for kindly implementing all the parsing code, this would have been totally impossible without his fantastic help. 77 | - Added option to use latexmk for compilation 78 | - Added option to always keep temporary files, even when not in debug mode. 79 | - Fixed width and height in some forms to avoid issue where a form would appear much smaller than designed, likely due to display dpi issues 80 | - Replaced ClipBoard copying code with something much simpler that does not rely on Windows API (Windows) and added ClipBoard support on Mac using AppleScript (Thanks, Tsung-Ju!) 81 | - Error messages now displayed in a UserForm with a button to copy to clipboard the command that led to an error (instead of forcing copy to clipboard, which may overwrite important information without the user first giving consent) 82 | - Removed UseUTF8 option as not using it does not appear to have a clear advantage 83 | - Transparency no longer handled by making PNG non-transparent but by adding white fill to shape (simpler and does not rely on inserted image type) 84 | - Fixed bug occurring when regenerating displays in a group whose 1st element is not an IguanaTex display 85 | - Automatically replace %USERPROFILE% in paths with actual value as such types of path lead to issue in CreateProcess API call 86 | 87 | New in IguanaTex 1.58 (October 10, 2020) 88 | - Added Alt text to each shape, containing the whole LaTeX code. This is not a good ADA compliant substitute, but is better than nothing, and can also be used by people who don't have IguanaTeX installed and want to retrieve the code used to generate a display. 89 | - Fixed bugs in mouse wheel support: mouse wheel was not working well on external displays with different DPI setting; cursor was moving too far, causing a silent error resulting in unresponsiveness until another mouse action reset processing 90 | - Fixed bug where reloading the code after modifying in an external editor with external editor as default resulted in a crash. 91 | - Fixed LaTeX engine selection Combobox style so that it is clickable (used to be possible to write text in, but this had no effect, so it was useless) 92 | - Removed ability to use mouse wheel to select the LaTeX engine in the Combobox as it wasn't well supported (mouse wheel would remain active for that Combobox even when hovering over neighboring objects within the same frame, e.g., Bitmap/Vector selection, etc) and wasn't very useful. 93 | - Added mouse wheel support in the template text box. 94 | 95 | New in IguanaTex 1.57 (May 30, 2019) 96 | - Added option to make editing in external editor the default when editing an existing display; IguanaTeX then automatically loads the relevant code in the external editor. 97 | - Added option to directly generate code that was modified in an external editor without having to first reload it in the IguanaTeX edit window. 98 | 99 | New in IguanaTex 1.56 (May 16, 2018) 100 | - Added option to preserve size of the original display when modifying a display (both for single and batch edits) 101 | - Conversion between Bitmap and Vector now preserves the size of the original display. Because Vector generation is much slower than Bitmap, and scaling factors tend to be finicky, I strongly suggest first generating and editing displays in Bitmap, and at the end convert to Vector. 102 | - New displays will now be placed at the same position as the first selected shape among currently selected shapes, if any, and will default to the usual arbitrary (200,200) position otherwise. This is useful when working with large slides (e.g., posters), avoiding the need to move the IguanaTeX display to the region currently being worked on. Note: Placing a display somewhere relative to the currently visible portion of a slide is surprisingly not straightforward in PowerPoint, so I'll leave that for now. 103 | - Updated the Download link for ImageMagick 104 | - Fixed some keyboard shortcuts 105 | 106 | New in IguanaTex 1.55 (September 28, 2017) 107 | - Fixed bug in vector conversion by ensuring Freeforms have Fill set to Visible (Thanks: @flart; https://github.com/Jonathan-LeRoux/IguanaTex/issues/2) 108 | - When creating new LaTeX display, automatically use font size of text if text is currently selected or cursor is in a textbox (Thanks: @itsuhane; https://github.com/itsuhane/IguanaTex/commit/ae4268b6a2a720dcdcc019e13c5c9df6bf6bb30a) 109 | - Changed TeX2img link to version 2.0.2, as 2.0.1 was reported by some users as raising issues (Thanks: Andreas Herkle) 110 | 111 | New in IguanaTex 1.54 (January 23, 2017) 112 | - Added option to set path to LaTeX executables (useful in particular with portable installations of LaTeX) 113 | 114 | New in IguanaTex 1.53 (December 12, 2016) 115 | - Added mouse wheel support in editor window 116 | - More robust vector graphics conversion 117 | - Source code tracking 118 | * Added macro to export all modules/forms of the add-in to text files 119 | * Uploaded source code of all versions since v1.31 to Github: https://github.com/Jonathan-LeRoux/IguanaTex 120 | 121 | New in IguanaTex 1.52 (November 16, 2016) 122 | - Added function to insert a vector graphics file (.pdf/.ps/e.ps/emf) into PowerPoint as a Shape. 123 | * PowerPoint already "supports" inserting .eps and .emf files, but the result is quite ugly. This function transforms the image into Shapes and does some clean up. 124 | * This function also extends support to .ps and .pdf files. 125 | * requires TeX2img's pdfiumdraw function, already used for vector graphics support. 126 | * The user can choose a zoom factor to be applied prior to converting into Shapes. 127 | * Calibration scaling factors are provided, in case the inserted display's size does not match that of the file being inserted. This can occur on some machines depending on the resolution and dpi setting. The user can compare the original and inserted sizes, and apply the right scaling factors. These settings can be saved. 128 | - Added option to reset format when regenerating a display. This is particularly useful when a Vector display with various colors or a mix of freeforms with fills and outlines gets regenerated: without resetting the format, the formatting of the original display as a group or of its left-most character would be applied to all parts of the new display. 129 | - Simplified some rescalings in vector graphics support. This may result in the need for recalibrating the vector scaling factors in Main Settings. 130 | - Improved robustness of vector graphics conversion: 131 | * Extended conversion of Lines into Freeforms to all Lines, not only vetical or horizontal ones. 132 | * Added check for presence of a Fill before discarding Outline of a Freeform 133 | 134 | New in IguanaTex 1.51 (November 1, 2016) 135 | - fixed a bug occurring when vector graphics display includes Line objects instead of only Freeform objects 136 | 137 | New in IguanaTex 1.50 (October 31, 2016) 138 | - Added vector graphics (EMF) support 139 | * requires TeX2img for robustness purposes (https://github.com/abenori/TeX2img, Download at: http://www.math.sci.hokudai.ac.jp/~abenori/soft/bin/TeX2img_2.0.1.zip) 140 | * vector graphics displays are groups of freeform objects; added ability to edit display both when clicking on the group, or when clicking on the left-most character (allowing clicking on all characters would make other things complicated) 141 | * formatting will (should) be preserved through editing (bevel formatting will not but it does not behave well on these shapes anyway) 142 | * editing vector graphics displays that have been further grouped should work as expected, except if there are groups with the same name (check the Selection Pane) 143 | - Improvements to "Regenerate selection": 144 | * added batch edit mode: selected displays or all displays on selected slides can be modified simultaneously (e.g., changing latex engine, size, DPI, vector/bitmap, transparency, and simple text search & replace) 145 | * added progress window for batch modification, indicating "number of already processed IguanaTex displays / total number of IguanaTex displays to be processed" on each selected slide 146 | * added shortcuts for conversion to vector and conversion to bitmap 147 | - Improvements to Main Settings: 148 | * added tunable "magic rescaling factors" in X/Y directions for vector and bitmap, to allow for the user to match exactly the size of text in a PowerPoint "Text Box". Particularly useful for vector output, which appears to be slightly warped by default. I typically use a 300pt display in Times New Roman to find a good rescaling factor, although the Bitmap output should be already pretty good, so it can be used as reference for the Vector one. 149 | * added clickable download links for ghostscript, ImageMagick, TeXstudio, and TeX2img 150 | - Improvements to robustness: 151 | * fixed rescaling issue occurring when using computers with various DPI settings. Caveat: this results in a one time resizing inconsistency for displays created on monitors with DPI other than 96. (Note: I tried very hard to make this backward compatible, but came to the conclusion that it was not possible. If anyone figures it out, I'll be glad to include a fix.) 152 | * fixed bug occurring when using Debug option on PowerPoint 2016 153 | * fixed bug occurring when selecting a group 154 | * improved robustness of conversion from TexPoint template equations 155 | - Improvements to edit window: 156 | * added per-display DPI setting 157 | * added ability for each display to remember the size of its edit window 158 | * added word wrap toggle, and ability for each display to remember its word wrap status 159 | * modified text selection behavior to be character-based instead of word-based 160 | 161 | New in IguanaTex 1.47 (October 16, 2015) 162 | - added global dpi setting (default value = 1200) 163 | - added workaround to prevent crashes when editing/regenerating displays created on machines with a different locale: for example, displays created on machines with the German language pack installed will feature a transparency tag in German ("Wahr"/"Falsch"), which raises an error in previous versions of IguanaTex. This version defaults to "True" if it does not recognize the foreign keyword (and it will preserve the transparency setting if you use the same locale, even if it's not English).. 164 | 165 | New in IguanaTex 1.46 (September 1, 2015) 166 | - added basic support for TexPoint's "equation" displays. All TexPoint displays created using the "equation" function will be converted to inline equation, black text, transparent background. 167 | 168 | New in IguanaTex 1.45 (July 30, 2015) 169 | - fixed a bug occurring with grouped shapes with the same name on Powerpoint 2007 in the function that uniquifies shape names on slides 170 | - improved multiple display support: main window now opens on top of the current PowerPoint window, even when it is not on the primary display 171 | 172 | New in IguanaTex 1.44 (June 26, 2015) 173 | - platex support for Japanese input 174 | 175 | New in IguanaTex 1.43 (June 23, 2015) 176 | - fixed bug occurring when using "Edit LaTeX display" on a single Texpoint display 177 | - fixed bug occurring when inserting an IguanaTex display on a slide with a Content Placeholder of type other than text 178 | - fixed bug occurring when multiple shapes on a slide have the same name; IguanaTex will now first de-duplicate all names 179 | - fixed bug where using "Regenerate selected displays" to regenerate displays within a group actually regenerated all displays in that group, not only the selected ones 180 | - fixed bug where Transparency setting would be ignored for LaTeX engines other than LaTeX (DVI->PNG) 181 | - enabled Transparency setting to be inherited from Texpoint displays 182 | 183 | New in IguanaTex 1.42 (May 21, 2015) 184 | - fixed a bug that could occur when using multi-byte characters 185 | - fixed font size discrepancies in menus 186 | 187 | New in IguanaTex 1.41 (May 17, 2015) 188 | - added ability to launch an external editor from main window and when LaTeX compilation fails 189 | - added buttons to change the font size in the editor and template windows, and default font size setting in the Settings menu 190 | - added per-display and per-template setting for the temporary folder (defaults to the one set in the Settings menu) 191 | - added file/folder selection menus in Main Settings 192 | - prevented displays to be inserted inside content placeholders 193 | 194 | New in IguanaTex 1.40 (May 11, 2015) (Special thanks to Stephan Schedler for contributions to the code and ideas) 195 | - added option to select between absolute and relative path for temporary folder (Warning: any file starting with "IguanaTex_tmp" in the temporary folder will be deleted, unless in debug mode) 196 | - added option to read code from .tex file 197 | - added template feature: code can be saved as template for future use, templates can be modified/removed 198 | - added ability to convert Texpoint displays into IguanaTex displays 199 | - added ability to regenerate multiple displays, or all displays in multiple slides, in one click (useful to convert many Texpoint equations at once, or if several IguanaTex displays include code from a separate file via \input{}, e.g., for font/color settings in the preamble) 200 | - simplified Settings window, merging choice of "PDF->PNG vs DVI->PNG" with choice of LaTeX engine 201 | - added per-display and per-template setting for the LaTeX engine (defaults to the one set in the Settings menu) 202 | - added progress indicator 203 | - size of edit window saved through "Make default" 204 | - remember Transparency setting on a per-display basis 205 | - added scrollbars in edit window 206 | - keep temporary files when in debug mode 207 | - commands copied to clipboard in debug mode (Warning: the clipboard content will be overwritten) 208 | - fixed display size issue when using dvipng on high-dpi displays 209 | - Changed "Create"/"Modify" to "Generate"/"ReGenerate" so that Alt-G is always the keyboard shortcut to create the display 210 | - (minor) improved resizing behaviour 211 | - (minor) fixed bug where time-out time was not properly indicated in message box 212 | - (minor) some code clean up 213 | 214 | New in IguanaTex 1.37 (November 11, 2014) 215 | - added option for choosing between pdflatex, xelatex and lualatex (only for PDF->PNG conversion; DVI->PNG uses pdflatex with the dvi output option) 216 | - cursor position automatically set to where it was in the LaTeX code when creating display, as well as in the template saved through "Make Default" 217 | 218 | New in IguanaTex 1.36 (November 10, 2014) 219 | - added new conversion process through PDF to create displays, ".tex -> .pdf -> .png", using Ghostscript for the main conversion, and ImageMagick's convert to change the DPI. Default is left to the original ".tex -> .dvi -> .png" using dvipng, as it does not require installation of extra tools. The PDF route is required for Tikz support, for example. 220 | - added ability to set paths to Ghostscript and ImageMagick's convert, as well as a "Reset to default" button 221 | - added UTF-8 support for input (now default), and added option to revert back to old ANSI input. This should in particular enable the use of non-latin characters, e.g. to display Chinese/Japanese/Korean. 222 | - added option to "reset" to a given point size an existing display when editing it; changes to size and aspect ratio are then obviously lost, but rotation is preserved (as well as all other formatting) 223 | - improved error handling 224 | - added modifiable time out interval for latex/conversion processes to allow PowerPoint to recover from hangs in the subprocesses 225 | - added keyboard shortcuts (Alt+...) in the main LaTeX form 226 | - improved order of buttons when using Tab 227 | - fixed/improved positioning of buttons in the main LaTeX form 228 | 229 | New in IguanaTex 1.35 (September 11, 2014) 230 | - reset the default size when creating a new display to be in "points" and to correspond to the font size in PowerPoint (the correspondence is approximate on high-DPI monitors) 231 | - fixed a one-time bug where the first time a display is created after loading the add-in, the form to create the display does not use the default values 232 | 233 | New in IguanaTex 1.34 (July 30, 2014) 234 | - fixed a bug that could set a wrong width to the display 235 | - enabled the new versions to modify displays created with old versions of IguanaTex without changing the size 236 | 237 | New in IguanaTex 1.33 (June 28, 2014) 238 | - fixed the ribbon tab code in order not to raise an error on PowerPoint 2003 239 | 240 | New in IguanaTex 1.32 (June 26, 2014) 241 | - fixed bugs with "Make Defaults" 242 | - size textbox now hidden in Edit mode instead of greyed out 243 | - fixed bug where "X" button would not close the window 244 | 245 | New in IguanaTex 1.31 (June 24, 2014) 246 | - added ability to set the temporary folder through a button in the IguanaTex tab of the ribbon 247 | - made the add-in able to create registry keys if they do not exist, thus avoiding the need for an installer 248 | - fixed issue with menu items in the Add-Ins tab when loading/unloading the add-in 249 | 250 | New in IguanaTex 1.3 (June 23, 2014) 251 | - extended group support to groups containing subgroups (any level of hierarchy is fine), again making sure that this does not break formatting, Zorder and animation settings 252 | - fixed bug where display could only be created in a unique presentation when working with several presentations at the same time 253 | 254 | New in IguanaTex 1.2 (June 20, 2014) 255 | - added ability to keep all formatting and animation settings when editing an existing display 256 | - added ability to edit displays within groups (assuming they do not have subgroups), and made sure that this does not break formatting, Zorder and animation settings 257 | - created a dedicated ribbon, which makes it possible to add each command to the Quick Access Toolbar 258 | - included Hammad M's modifications to be able to resize the dialog box 259 | - fixed a display bug where the "Modify" button would sometimes be partly hidden 260 | - added a default size of "20" points when creating a new display 261 | - disabled the size box when modifying the display, assuming that we keep the same scaling for both height and width 262 | - bumped the dpi to 1200 263 | - made the code compatible with both 32-bit and 64-bit PowerPoint 264 | --------------------------------------------------------------------------------