├── AboutBox.frx ├── LatexForm.frx ├── SetTempForm.frx ├── BatchEditForm.frx ├── LogFileViewer.frx ├── RegenerateForm.frx ├── ExternalEditorForm.frx ├── LoadVectorGraphicsForm.frx ├── ArrayUtil.bas ├── AppEventHandler.cls ├── Defaults.bas ├── RegenerateForm.frm ├── ShellWait.bas ├── AboutBox.frm ├── IguanaTexHelper ├── IguanaTexHelper │ ├── IguanaTexHelper.h │ └── IguanaTexHelper.m └── IguanaTexHelper.xcodeproj │ ├── xcshareddata │ └── xcschemes │ │ └── IguanaTexHelper.xcscheme │ └── project.pbxproj ├── FileSystemObject.cls ├── ExternalEditorForm.frm ├── .gitignore ├── AppleScript └── IguanaTex.scpt ├── MacUtil.bas ├── ExportVBA.bas ├── LogFileViewer.frm ├── RegistryAccess.bas ├── IconvWrapper.bas ├── README.md ├── TextWindow.cls ├── BatchEditForm.frm ├── SetTempForm.frm ├── Dictionary.cls ├── LoadVectorGraphicsForm.frm ├── Macros.bas └── LatexForm.frm /AboutBox.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsung-ju/IguanaTexMac/HEAD/AboutBox.frx -------------------------------------------------------------------------------- /LatexForm.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsung-ju/IguanaTexMac/HEAD/LatexForm.frx -------------------------------------------------------------------------------- /SetTempForm.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsung-ju/IguanaTexMac/HEAD/SetTempForm.frx -------------------------------------------------------------------------------- /BatchEditForm.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsung-ju/IguanaTexMac/HEAD/BatchEditForm.frx -------------------------------------------------------------------------------- /LogFileViewer.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsung-ju/IguanaTexMac/HEAD/LogFileViewer.frx -------------------------------------------------------------------------------- /RegenerateForm.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsung-ju/IguanaTexMac/HEAD/RegenerateForm.frx -------------------------------------------------------------------------------- /ExternalEditorForm.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsung-ju/IguanaTexMac/HEAD/ExternalEditorForm.frx -------------------------------------------------------------------------------- /LoadVectorGraphicsForm.frx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tsung-ju/IguanaTexMac/HEAD/LoadVectorGraphicsForm.frx -------------------------------------------------------------------------------- /ArrayUtil.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "ArrayUtil" 2 | Public Function ArrayLength(arr As Variant) As Long 3 | On Error GoTo handler 4 | ArrayLength = UBound(arr) + 1 5 | Exit Function 6 | handler: 7 | ArrayLength = 0 8 | End Function 9 | 10 | -------------------------------------------------------------------------------- /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 | Public WithEvents App As Application 11 | Attribute App.VB_VarHelpID = -1 12 | 13 | Private Sub App_WindowBeforeDoubleClick(ByVal Sel As Selection, ByRef Cancel As Boolean) 14 | If (TryEditLatexEquation()) Then 15 | Cancel = True 16 | End If 17 | End Sub 18 | 19 | -------------------------------------------------------------------------------- /Defaults.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "Defaults" 2 | Public Const DEFAULT_TEX_EXE_PATH As String = "/Library/TeX/texbin/" 3 | Public Const DEFAULT_GS_COMMAND As String = "/usr/local/bin/gs" 4 | Public Const DEFAULT_IM_CONV As String = "/usr/local/bin/convert" 5 | Public Const DEFAULT_TEX2IMG_COMMAND As String = "/usr/local/bin/tex2img" 6 | Public Const DEFAULT_EDITOR As String = "open -b 'texstudio'" 7 | 8 | Public Const DEFAULT_LATEX_CODE As String = "\documentclass{article}" & vbLf & "\usepackage{amsmath}" & vbLf & "\pagestyle{empty}" & vbLf & "\begin{document}" & vbLf & vbLf & vbLf & vbLf & vbLf & "\end{document}" 9 | 10 | -------------------------------------------------------------------------------- /RegenerateForm.frm: -------------------------------------------------------------------------------- 1 | VERSION 5.00 2 | Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} RegenerateForm 3 | Caption = "Regenerating" 4 | ClientHeight = 1799 5 | ClientLeft = 40 6 | ClientTop = 380 7 | ClientWidth = 3920 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 | Private Sub UserForm_Initialize() 17 | Me.Top = Application.Top + 110 18 | Me.Left = Application.Left + 25 19 | 20 | End Sub 21 | 22 | Private Sub CommandButtonCancel_Click() 23 | 'CheckBoxContinue.Value = False 24 | RegenerateContinue = False 25 | Unload RegenerateForm 26 | 'End 27 | End Sub 28 | -------------------------------------------------------------------------------- /ShellWait.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "ShellWait" 2 | Public Function OpenLink(ByVal Link As String) As Long 3 | Dim ret As Long 4 | ret = CLng(AppleScriptTask("IguanaTex.scpt", "MacExecute", "open " & ShellEscape(Link))) 5 | If ret = 0 Then 6 | ' success 7 | OpenLink = 33 ' returns a value greater than 32 8 | Else 9 | ' failed 10 | OpenLink = 0 11 | End If 12 | End Function 13 | 14 | 15 | Public Function Execute(ByVal CommandLine As String, StartupDir As String, Optional debugMode As Boolean = False, Optional WaitTime As Long = -1) As Long 16 | Const RegPath = "Software\IguanaTex" 17 | Dim TeXExePath As String 18 | TeXExePath = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "TeXExePath", DEFAULT_TEX_EXE_PATH) 19 | Execute = CLng(AppleScriptTask("IguanaTex.scpt", "MacExecute", _ 20 | "export PATH=" & ShellEscape(TeXExePath) & """:$PATH""" & " && " & _ 21 | "cd " & ShellEscape(StartupDir) & " && " & _ 22 | CommandLine)) 23 | End Function 24 | 25 | -------------------------------------------------------------------------------- /AboutBox.frm: -------------------------------------------------------------------------------- 1 | VERSION 5.00 2 | Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} AboutBox 3 | Caption = "IguanaTex" 4 | ClientHeight = 4920 5 | ClientLeft = 40 6 | ClientTop = 340 7 | ClientWidth = 8820.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 | Private Sub CloseAboutButton_Click() 17 | Unload AboutBox 18 | End Sub 19 | 20 | 21 | Private Sub LabelURL_Click() 22 | Link = "http://www.jonathanleroux.org/software/iguanatex/" 23 | Dim lSuccess As Long 24 | lSuccess = OpenLink(Link) 25 | 26 | If (lSuccess = 0) Then 27 | MsgBox "Cannot open " & Link 28 | End If 29 | End Sub 30 | 31 | Private Sub UserForm_Initialize() 32 | Me.Top = Application.Top + 110 33 | Me.Left = Application.Left + 25 34 | 35 | End Sub 36 | -------------------------------------------------------------------------------- /IguanaTexHelper/IguanaTexHelper/IguanaTexHelper.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define EXPORT __attribute__((visibility ("default"))) 4 | 5 | const int64_t TextWindowStyle1 = 0; 6 | const int64_t TextWindowStyleTemplateCode = 2; 7 | 8 | EXPORT int64_t TWInit(void); 9 | EXPORT int TWTerm(int64_t handle, int64_t b, int64_t c, int64_t d); 10 | 11 | EXPORT int TWShow(int64_t handle, int64_t b, int64_t c, int64_t d); 12 | EXPORT int TWHide(int64_t handle, int64_t b, int64_t c, int64_t d); 13 | EXPORT int TWResize(int64_t handle, int64_t b, int64_t c, int64_t d); 14 | EXPORT int TWFocus(int64_t handle, int64_t b, int64_t c, int64_t d); 15 | 16 | EXPORT int TWSet(int64_t handle, const char* data, int64_t len, int64_t d); 17 | EXPORT int TWGet(int64_t handle, char** data, int64_t* len, int64_t d); 18 | 19 | EXPORT int TWGetSel(int64_t handle, int64_t b, int64_t c, int64_t d); 20 | EXPORT int TWSetSel(int64_t handle, int64_t sel, int64_t c, int64_t d); 21 | 22 | EXPORT int TWGetSZ(int64_t handle, int64_t b, int64_t c, int64_t d); 23 | EXPORT int TWSetSZ(int64_t handle, int64_t size, int64_t c, int64_t d); 24 | -------------------------------------------------------------------------------- /FileSystemObject.cls: -------------------------------------------------------------------------------- 1 | VERSION 1.0 CLASS 2 | BEGIN 3 | MultiUse = -1 'True 4 | END 5 | Attribute VB_Name = "FileSystemObject" 6 | Attribute VB_GlobalNameSpace = False 7 | Attribute VB_Creatable = False 8 | Attribute VB_PredeclaredId = False 9 | Attribute VB_Exposed = False 10 | ' Replacement for Scripting.FileSystemObject 11 | 12 | Option Explicit 13 | 14 | Public Function FileExists(pathname As String) As Boolean 15 | FileExists = (Dir(pathname) <> "") 16 | End Function 17 | 18 | Public Function FolderExists(pathname As String) As Boolean 19 | FolderExists = (Dir(pathname) <> "") 20 | End Function 21 | 22 | Public Sub CreateFolder(pathname As String) 23 | MkDir pathname 24 | End Sub 25 | 26 | ' calls `find -name -delete` 27 | Public Sub FindDelete(dirname As String, pattern As String) 28 | AppleScriptTask "IguanaTex.scpt", "MacExecute", "find " & ShellEscape(dirname) & " -name " & ShellEscape(pattern) & " -delete" 29 | End Sub 30 | 31 | ' does not support path globbing. use `FindDelete` instead. 32 | Public Sub DeleteFile(pathname As String) 33 | If FileExists(pathname) Then 34 | ' remove readonly attribute if set 35 | SetAttr pathname, vbNormal 36 | Kill pathname 37 | End If 38 | End Sub 39 | 40 | -------------------------------------------------------------------------------- /ExternalEditorForm.frm: -------------------------------------------------------------------------------- 1 | VERSION 5.00 2 | Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} ExternalEditorForm 3 | Caption = "External Editor" 4 | ClientHeight = 2037 5 | ClientLeft = 20 6 | ClientTop = 340 7 | ClientWidth = 5680 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 | Private Sub UserForm_Initialize() 17 | Me.Top = Application.Top + 110 18 | Me.Left = Application.Left + 25 19 | End Sub 20 | 21 | Private Sub CmdButtonCancel_Click() 22 | Unload ExternalEditorForm 23 | End Sub 24 | 25 | Private Sub CmdButtonReload_Click() 26 | SelStartPos = LatexForm.TextWindow1.SelStart 27 | TempPath = LatexForm.TextBoxTempFolder.Text 28 | 29 | If Left(TempPath, 1) = "." Then 30 | Dim sPath As String 31 | sPath = ActivePresentation.path 32 | If Len(sPath) > 0 Then 33 | If Right(sPath, 1) <> PathSeperator Then 34 | sPath = sPath & PathSeperator 35 | End If 36 | TempPath = sPath & TempPath 37 | Else 38 | MsgBox "You need to have saved your presentation once to use a relative path." 39 | Exit Sub 40 | End If 41 | End If 42 | 43 | LatexForm.TextWindow1.Utf8 = ReadAllBytes(TempPath & GetFilePrefix() & ".tex") 44 | 45 | Unload ExternalEditorForm 46 | LatexForm.TextWindow1.SetFocus 47 | If SelStartPos < Len(LatexForm.TextWindow1.Text) Then 48 | LatexForm.TextWindow1.SelStart = SelStartPos 49 | End If 50 | End Sub 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #### joe made this: http://goel.io/joe 2 | 3 | #### objective-c #### 4 | # Xcode 5 | # 6 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 7 | 8 | ## Build generated 9 | build/ 10 | DerivedData/ 11 | 12 | ## Various settings 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | xcuserdata/ 22 | 23 | ## Other 24 | *.moved-aside 25 | *.xccheckout 26 | *.xcscmblueprint 27 | 28 | ## Obj-C/Swift specific 29 | *.hmap 30 | *.ipa 31 | *.dSYM.zip 32 | *.dSYM 33 | 34 | # CocoaPods 35 | # 36 | # We recommend against adding the Pods directory to your .gitignore. However 37 | # you should judge for yourself, the pros and cons are mentioned at: 38 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 39 | # 40 | # Pods/ 41 | # 42 | # Add this line if you want to avoid checking in source code from the Xcode workspace 43 | *.xcworkspace 44 | 45 | # Carthage 46 | # 47 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 48 | # Carthage/Checkouts 49 | 50 | Carthage/Build 51 | 52 | # fastlane 53 | # 54 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 55 | # screenshots whenever they are needed. 56 | # For more information about the recommended setup visit: 57 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 58 | 59 | fastlane/report.xml 60 | fastlane/Preview.html 61 | fastlane/screenshots/**/*.png 62 | fastlane/test_output 63 | 64 | # Code Injection 65 | # 66 | # After new code Injection tools there's a generated folder /iOSInjectionProject 67 | # https://github.com/johnno1962/injectionforxcode 68 | 69 | iOSInjectionProject/ 70 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /MacUtil.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "MacUtil" 2 | Public Const PathSeperator As String = "/" 3 | 4 | Public Function ShellEscape(Str As String) As String 5 | ShellEscape = "'" & Replace(Replace(Str, "\", "\\"), "'", "'\''") & "'" 6 | End Function 7 | 8 | Public Function ReadAllBytes(filename As String) As Byte() 9 | Dim fnum As Integer 10 | fnum = FreeFile() 11 | Open filename For Binary Access Read As fnum 12 | 13 | Dim length As Long 14 | length = FileLen(filename) 15 | 16 | Dim data() As Byte 17 | If length <> 0 Then 18 | ReDim data(length - 1) 19 | Get #fnum, , data 20 | End If 21 | 22 | Close #fnum 23 | 24 | ReadAllBytes = data 25 | End Function 26 | 27 | Public Function ReadAll(filename As String) As String 28 | ReadAll = Utf8ToString(ReadAllBytes(filename)) 29 | End Function 30 | 31 | Public Function ReadAllExternal(pathname As String) As String 32 | ReadAllExternal = AppleScriptTask("IguanaTex.scpt", "ReadAllExternal", pathname) 33 | End Function 34 | 35 | Public Function MacTempPath() As String 36 | MacTempPath = MacScript("POSIX path of (path to temporary items)") 37 | End Function 38 | 39 | Public Function MacChooseFileOfType(typeStr As String) As String 40 | MacChooseFileOfType = AppleScriptTask("IguanaTex.scpt", "MacChooseFileOfType", typeStr) 41 | End Function 42 | 43 | Public Function MacChooseApp(defaultValue As String) As String 44 | MacChooseApp = AppleScriptTask("IguanaTex.scpt", "MacChooseApp", defaultValue) 45 | End Function 46 | 47 | Public Function MacChooseFile(defaultValue As String) As String 48 | MacChooseFile = AppleScriptTask("IguanaTex.scpt", "MacChooseFile", defaultValue) 49 | End Function 50 | 51 | Public Function MacChooseFolder(defaultValue As String) As String 52 | MacChooseFolder = AppleScriptTask("IguanaTex.scpt", "MacChooseFolder", defaultValue) 53 | End Function 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /ExportVBA.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "ExportVBA" 2 | ' Modified from https://gist.github.com/steve-jansen/7589478 to work in PowerPoint 3 | ' 4 | ' PowerPoint macro to export all VBA source code in this project to text files for proper source control versioning 5 | ' Requires enabling the PowerPoint setting in Options/Trust Center/Trust Center Settings/Macro Settings/Trust access to the VBA project object model 6 | Public Sub ExportVisualBasicCode() 7 | Const Module = 1 8 | Const ClassModule = 2 9 | Const Form = 3 10 | Const Document = 100 11 | Const Padding = 24 12 | 13 | Dim VBComponent As Object 14 | Dim count As Integer 15 | Dim path As String 16 | Dim directory As String 17 | Dim extension As String 18 | Dim fso As New FileSystemObject 19 | 20 | Dim myPath As String 21 | myPath = ActivePresentation.FullName 22 | directory = Left(myPath, InStrRev(myPath, ".") - 1) & "_VBA" 23 | count = 0 24 | 25 | If Not fso.FolderExists(directory) Then 26 | Call fso.CreateFolder(directory) 27 | End If 28 | Set fso = Nothing 29 | 30 | For Each VBComponent In ActivePresentation.VBProject.VBComponents 31 | Select Case VBComponent.Type 32 | Case ClassModule, Document 33 | extension = ".cls" 34 | Case Form 35 | extension = ".frm" 36 | Case Module 37 | extension = ".bas" 38 | Case Else 39 | extension = ".txt" 40 | End Select 41 | 42 | 43 | On Error Resume Next 44 | Err.Clear 45 | 46 | path = directory & PathSeperator & VBComponent.name & extension 47 | Call VBComponent.Export(path) 48 | 49 | If Err.Number <> 0 Then 50 | Call MsgBox("Failed to export " & VBComponent.name & " to " & path, vbCritical) 51 | Else 52 | count = count + 1 53 | Debug.Print "Exported " & Left$(VBComponent.name & ":" & Space(Padding), Padding) & path 54 | End If 55 | 56 | On Error GoTo 0 57 | Next 58 | 59 | MsgBox "Successfully exported " & CStr(count) & " VBA files to " & directory 60 | 61 | End Sub 62 | -------------------------------------------------------------------------------- /LogFileViewer.frm: -------------------------------------------------------------------------------- 1 | VERSION 5.00 2 | Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} LogFileViewer 3 | Caption = "Error in Latex Code" 4 | ClientHeight = 6975 5 | ClientLeft = 40 6 | ClientTop = 320 7 | ClientWidth = 8860.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 | Private Sub UserForm_Initialize() 17 | Me.Top = Application.Top + 110 18 | Me.Left = Application.Left + 25 19 | End Sub 20 | 21 | Private Sub CloseLogButton_Click() 22 | 23 | SelStartPos = LatexForm.TextWindow1.SelStart 24 | TempPath = LatexForm.TextBoxTempFolder.Text 25 | 26 | If Left(TempPath, 1) = "." Then 27 | Dim sPath As String 28 | sPath = ActivePresentation.path 29 | If Len(sPath) > 0 Then 30 | If Right(sPath, 1) <> PathSeperator Then 31 | sPath = sPath & PathSeperator 32 | End If 33 | TempPath = sPath & TempPath 34 | Else 35 | MsgBox "You need to have saved your presentation once to use a relative path." 36 | Exit Sub 37 | End If 38 | End If 39 | 40 | LatexForm.TextWindow1.Text = ReadAll(TempPath & GetFilePrefix() & ".tex") 41 | 42 | 43 | CloseLogButton.Caption = "Close" 44 | Unload LogFileViewer 45 | LatexForm.TextWindow1.SetFocus 46 | If SelStartPos < Len(LatexForm.TextWindow1.Text) Then 47 | LatexForm.TextWindow1.SelStart = SelStartPos 48 | End If 49 | End Sub 50 | 51 | Private Sub CmdButtonExternalEditor_Click() 52 | TempPath = LatexForm.TextBoxTempFolder.Text 53 | If Left(TempPath, 1) = "." Then 54 | Dim sPath As String 55 | sPath = ActivePresentation.path 56 | If Len(sPath) > 0 Then 57 | If Right(sPath, 1) <> PathSeperator Then 58 | sPath = sPath & PathSeperator 59 | End If 60 | TempPath = sPath & TempPath 61 | Else 62 | MsgBox "You need to have saved your presentation once to use a relative path." 63 | Exit Sub 64 | End If 65 | End If 66 | LogFileViewer.Caption = """" & GetEditorPath() & """ """ & TempPath & GetFilePrefix() & ".tex""" 67 | CloseLogButton.Caption = "Reload modified code" 68 | AppleScriptTask "IguanaTex.scpt", "MacExecute", GetEditorPath() & " " & ShellEscape(TempPath & FilePrefix & ".tex") 69 | 70 | End Sub 71 | -------------------------------------------------------------------------------- /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 | 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 | -------------------------------------------------------------------------------- /IconvWrapper.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "IconvWrapper" 2 | Option Explicit 3 | 4 | Private Declare PtrSafe Function iconv_open Lib "/usr/lib/libiconv.dylib" (ByVal tocode As String, ByVal fromcode As String) As LongLong 5 | Private Declare PtrSafe Function iconv_close Lib "/usr/lib/libiconv.dylib" (ByVal cd As LongPtr) As Integer 6 | 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 7 | 8 | Private Sub RunIconv(ByVal cd As LongPtr, ByRef inBytes() As Byte, ByRef outBytes() As Byte) 9 | Dim inbuf As LongPtr 10 | inbuf = VarPtr(inBytes(0)) 11 | Dim inbytesleft As LongLong 12 | inbytesleft = ArrayLength(inBytes) 13 | 14 | Dim outbuf As LongPtr 15 | outbuf = VarPtr(outBytes(0)) 16 | Dim outbytesleft As LongLong 17 | outbytesleft = ArrayLength(outBytes) 18 | 19 | While inbytesleft > 0 20 | If outbytesleft = 0 Then 21 | ReDim Preserve outBytes(UBound(outBytes) + CLng(inbytesleft) * 2) 22 | outbytesleft = CLng(inbytesleft) * 2 23 | End If 24 | If iconv(cd, inbuf, inbytesleft, outbuf, outbytesleft) = -1& Then GoTo Error 25 | Wend 26 | 27 | ReDim Preserve outBytes(UBound(outBytes) - CLng(outbytesleft)) 28 | Exit Sub 29 | 30 | Error: 31 | MsgBox "iconv failed, return empty string" 32 | ReDim outBytes(0) 33 | End Sub 34 | 35 | Public Function Utf8ToString(Utf8() As Byte) As String 36 | If ArrayLength(Utf8) = 0 Then 37 | Utf8ToString = "" 38 | Exit Function 39 | End If 40 | 41 | Dim utf16() As Byte 42 | ReDim utf16(UBound(Utf8) * 2 + 1) 43 | 44 | Dim cd As LongLong 45 | cd = iconv_open("utf-16le", "utf-8") 46 | If cd = -1& Then GoTo Error 47 | 48 | RunIconv cd, Utf8, utf16 49 | 50 | If iconv_close(cd) = -1 Then GoTo Error 51 | 52 | 53 | Utf8ToString = utf16 54 | Exit Function 55 | 56 | Error: 57 | MsgBox "iconv failed, return empty string" 58 | Utf8ToString = "" 59 | End Function 60 | 61 | Public Function StringToUtf8(Str As String) As Byte() 62 | Dim Utf8() As Byte 63 | 64 | If Len(Str) = 0 Then 65 | StringToUtf8 = Utf8 66 | Exit Function 67 | End If 68 | 69 | Dim utf16() As Byte 70 | utf16 = Str 71 | ' trim zero bytes 72 | ReDim Preserve utf16(Len(Str) * 2 - 1) 73 | 74 | ReDim Utf8(UBound(utf16)) 75 | 76 | Dim cd As LongLong 77 | cd = iconv_open("utf-8", "utf-16le") 78 | If cd = -1& Then GoTo Error 79 | 80 | RunIconv cd, utf16, Utf8 81 | 82 | If iconv_close(cd) = -1 Then GoTo Error 83 | 84 | StringToUtf8 = Utf8 85 | Exit Function 86 | 87 | Error: 88 | MsgBox "iconv failed, return empty string" 89 | ReDim Utf8(0) 90 | StringToUtf8 = Utf8 91 | End Function 92 | 93 | 94 | -------------------------------------------------------------------------------- /IguanaTexHelper/IguanaTexHelper.xcodeproj/xcshareddata/xcschemes/IguanaTexHelper.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 52 | 53 | 59 | 60 | 66 | 67 | 68 | 69 | 71 | 72 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NOTE: This repository is for the deprecated macOS port of IguanaTex. 2 | Support for macOS has been merged back into [the original IguanaTex](https://github.com/Jonathan-LeRoux/IguanaTex) since version 1.60, 3 | along with some additional features such as vector graphics, resizable input window, keyboard shortcuts, and support for M1 macs. 4 | 5 | # IguanaTexMac 6 | 7 | This is very experimental. Use at your own risk! 8 | 9 | ## Known Issues 10 | * Vector graphics are not supported 11 | * PowerPoint for Mac does not yet support converting emf images into shapes 12 | * See https://powerpoint.uservoice.com/forums/288925/suggestions/34217164 13 | * The input window is not resizable 14 | * Using IguanaTexMac on the Apple silicon based version of PowerPoint results in the programm crashing 15 | * Running PowerPoint with the setting “Open using Rosetta.” works (only relevant for Apple silicon based Macs) 16 | 17 | ## Prerequisites 18 | * PowerPoint for Mac. Supported versions: 19 | * PowerPoint 2016 (Version 16.16.7 190210 or later) 20 | * PowerPoint 2019 21 | * MacTeX 22 | 23 | ## Install 24 | 25 | ### Method 1: Install with [Homebrew](https://brew.sh) 26 | 27 | ```bash 28 | brew tap tsung-ju/iguanatexmac 29 | brew install --cask --no-quarantine iguanatexmac 30 | ``` 31 | 32 | To uninstall: 33 | 34 | ```bash 35 | brew uninstall --cask iguanatexmac 36 | brew untap tsung-ju/iguanatexmac 37 | # Restart PowerPoint for the changes to take effect 38 | ``` 39 | 40 | ### Method 2: Install Manually 41 | 42 | 1. [Dowload the "prebuilt files" zip from the latest release](https://github.com/tsung-ju/IguanaTexMac/releases) 43 | 44 | There are 3 files to install: 45 | * `IguanaTex.scpt` 46 | * An AppleScript file for bypassing the sandbox introduced in Office 2016 47 | * See https://msdn.microsoft.com/en-us/vba/vba-office-mac 48 | * `libIguanaTexHelper.dylib` 49 | * Library for creating native text views 50 | * The source code is included in the git repo, under the "IguanaTexHelper/" directory. 51 | * `IguanaTexMac.ppam` 52 | * The main plugin file 53 | 54 | 2. Install `IguanaTex.scpt` 55 | ```bash 56 | mkdir -p ~/Library/Application\ Scripts/com.microsoft.Powerpoint 57 | cp ./IguanaTex.scpt ~/Library/Application\ Scripts/com.microsoft.Powerpoint/IguanaTex.scpt 58 | ``` 59 | 60 | 3. Install `libIguanaTexHelper.dylib` 61 | ```bash 62 | sudo mkdir -p '/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized' 63 | sudo cp ./libIguanaTexHelper.dylib '/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib' 64 | ``` 65 | 66 | 4. Start PowerPoint. From the menu bar, select Tools > PowerPoint Add-ins... > '+' , and choose `IguanaTexMac.ppam` 67 | 68 | 69 | Original README 70 | =============== 71 | 72 | # IguanaTex 73 | 74 | (C) Jonathan Le Roux and Zvika Ben-Haim 75 | Website: http://www.jonathanleroux.org/software/iguanatex/ 76 | 77 | IguanaTex is a PowerPoint add-in which allows you to insert LaTeX equations into your PowerPoint presentation on Windows. It is distributed completely for free, along with its source code. 78 | 79 | This repository hosts the source code in a form that can be easily tracked, shared and discussed. 80 | 81 | For those interested in using IguanaTex, please download the add-in as a .ppam or .pptm file from http://www.jonathanleroux.org/software/iguanatex/. 82 | -------------------------------------------------------------------------------- /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 | 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 | Private Declare PtrSafe Function TWTerm _ 19 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 20 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As Integer 21 | 22 | Private Declare PtrSafe Function TWResize _ 23 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 24 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As Integer 25 | 26 | Private Declare PtrSafe Function TWShow _ 27 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 28 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As Integer 29 | 30 | Private Declare PtrSafe Function TWHide _ 31 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 32 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As Integer 33 | 34 | Private Declare PtrSafe Function TWSet _ 35 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 36 | (ByVal Handle As LongLong, ByVal data As LongPtr, ByVal length As LongLong, ByVal d As LongLong) As Integer 37 | 38 | Private Declare PtrSafe Function TWGet _ 39 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 40 | (ByVal Handle As LongLong, ByRef data As LongPtr, ByRef length As LongLong, ByVal d As LongLong) As Integer 41 | 42 | Private Declare PtrSafe Function TWGetSel _ 43 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 44 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As Integer 45 | 46 | Private Declare PtrSafe Function TWSetSel _ 47 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 48 | (ByVal Handle As LongLong, ByVal Sel As LongLong, ByVal c As LongLong, ByVal d As LongLong) As Integer 49 | 50 | Private Declare PtrSafe Function TWFocus _ 51 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 52 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As Integer 53 | 54 | Private Declare PtrSafe Function TWGetSZ _ 55 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 56 | (ByVal Handle As LongLong, ByVal b As LongLong, ByVal c As LongLong, ByVal d As LongLong) As Integer 57 | 58 | Private Declare PtrSafe Function TWSetSZ _ 59 | Lib "/Library/Application Support/Microsoft/Office365/User Content.localized/Add-Ins.localized/libIguanaTexHelper.dylib" _ 60 | (ByVal Handle As LongLong, ByVal sz As LongLong, ByVal c As LongLong, ByVal d As LongLong) As Integer 61 | 62 | Private Declare PtrSafe Function memcpy Lib "/usr/lib/libc.dylib" (ByVal dest As LongPtr, ByVal src As LongPtr, ByVal n As LongLong) As LongPtr 63 | Private Declare PtrSafe Sub free Lib "/usr/lib/libc.dylib" (ByVal ptr As LongPtr) 64 | 65 | ' members 66 | Private Handle As LongLong 67 | 68 | ' properties 69 | Public Property Get Utf8() As Byte() 70 | Dim ptr As LongPtr 71 | Dim length As LongLong 72 | Dim ret() As Byte 73 | 74 | TWGet Handle, ptr, length, 0 75 | 76 | If length <> 0& Then 77 | ReDim ret(CLng(length) - 1) 78 | memcpy VarPtr(ret(0)), ptr, length 79 | End If 80 | 81 | free ptr 82 | 83 | Utf8 = ret 84 | End Property 85 | 86 | Public Property Let Utf8(data() As Byte) 87 | Dim length As Long 88 | length = ArrayLength(data) 89 | If length > 0 Then 90 | TWSet Handle, VarPtr(data(0)), length, 0 91 | Else 92 | TWSet Handle, 0, 0, 0 93 | End If 94 | End Property 95 | 96 | Public Property Get Text() As String 97 | Text = Utf8ToString(Me.Utf8) 98 | End Property 99 | 100 | Public Property Let Text(Str As String) 101 | Me.Utf8 = StringToUtf8(Str) 102 | End Property 103 | 104 | Public Property Get SelStart() As Integer 105 | SelStart = TWGetSel(Handle, 0, 0, 0) 106 | End Property 107 | 108 | Public Property Let SelStart(Sel As Integer) 109 | TWSetSel Handle, Sel, 0, 0 110 | End Property 111 | 112 | Public Property Get FontSize() As Integer 113 | FontSize = TWGetSZ(Handle, 0, 0, 0) 114 | End Property 115 | 116 | Public Property Let FontSize(sz As Integer) 117 | TWSetSZ Handle, sz, 0, 0 118 | End Property 119 | 120 | ' constructor/destructor 121 | Private Sub Class_Initialize() 122 | Handle = TWInit 123 | End Sub 124 | 125 | Private Sub Class_Terminate() 126 | TWTerm Handle, 0, 0, 0 127 | End Sub 128 | 129 | ' methods 130 | Public Sub Show() 131 | TWShow Handle, 0, 0, 0 132 | End Sub 133 | 134 | Public Sub Hide() 135 | TWHide Handle, 0, 0, 0 136 | End Sub 137 | 138 | Public Sub ResizeAs(target As control, parentForm As UserForm) 139 | Dim currentFocus As control 140 | Set currentFocus = parentForm.ActiveControl 141 | target.SetFocus 142 | TWResize Handle, 0, 0, 0 143 | currentFocus.SetFocus 144 | End Sub 145 | 146 | Public Sub SetFocus() 147 | TWFocus Handle, 0, 0, 0 148 | End Sub 149 | 150 | -------------------------------------------------------------------------------- /BatchEditForm.frm: -------------------------------------------------------------------------------- 1 | VERSION 5.00 2 | Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} BatchEditForm 3 | Caption = "Batch edit" 4 | ClientHeight = 5955 5 | ClientLeft = 40 6 | ClientTop = 380 7 | ClientWidth = 4720 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 | Dim RegPath As String 17 | Dim LaTexEngineDisplayList As Variant 18 | 19 | 20 | Private Sub UserForm_Initialize() 21 | LoadSettings 22 | Me.Top = Application.Top + 110 23 | Me.Left = Application.Left + 25 24 | 25 | End Sub 26 | 27 | Private Sub LoadSettings() 28 | RegPath = "Software\IguanaTex" 29 | LaTexEngineDisplayList = Array("latex (DVI)", "pdflatex", "xelatex", "lualatex", "platex") 30 | ComboBoxLaTexEngine.List = LaTexEngineDisplayList 31 | ComboBoxLaTexEngine.ListIndex = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "LaTeXEngineID", 0) 32 | TextBoxTempFolder.Text = GetTempPath() 33 | 'CheckBoxEMF.Value = CBool(GetRegistryValue(HKEY_CURRENT_USER, RegPath, "EMFoutput", False)) 34 | ComboBoxBitmapVector.List = Array("Bitmap", "Vector") 35 | ComboBoxBitmapVector.ListIndex = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "BitmapVector", 0) 36 | 37 | TextBoxLocalDPI.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "OutputDpi", "1200") 38 | textboxSize.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "PointSize", "20") 39 | checkboxTransp.Value = CBool(GetRegistryValue(HKEY_CURRENT_USER, RegPath, "Transparent", True)) 40 | CheckBoxResetFormat.Value = False 41 | 42 | CheckBoxModifyEngine.Value = False 43 | CheckBoxModifyTempFolder.Value = False 44 | CheckBoxModifyBitmapVector.Value = False 45 | CheckBoxModifyLocalDPI.Value = False 46 | CheckBoxModifySize.Value = False 47 | CheckBoxModifyPreserveSize.Value = False 48 | CheckBoxModifyTransparency.Value = False 49 | CheckBoxModifyResetFormat.Value = False 50 | CheckBoxReplace.Value = False 51 | Apply_CheckBoxModifyEngine 52 | Apply_CheckBoxModifyTempFolder 53 | Apply_CheckBoxModifyBitmapVector 54 | Apply_CheckBoxModifyLocalDPI 55 | Apply_CheckBoxModifySize 56 | Apply_CheckBoxModifyPreserveSize 57 | Apply_CheckBoxModifyTransparency 58 | Apply_CheckBoxModifyResetFormat 59 | Apply_CheckBoxReplace 60 | End Sub 61 | 62 | Sub ButtonRun_Click() 63 | BatchEditForm.Hide 64 | 65 | Call RegenerateSelectedDisplays 66 | 67 | Unload BatchEditForm 68 | End Sub 69 | 70 | Private Sub ButtonCancel_Click() 71 | Unload BatchEditForm 72 | End Sub 73 | 74 | 75 | ' Enable/Disable Modifications 76 | Private Sub CheckBoxModifyEngine_Click() 77 | Apply_CheckBoxModifyEngine 78 | End Sub 79 | 80 | Private Sub CheckBoxModifyTempFolder_Click() 81 | Apply_CheckBoxModifyTempFolder 82 | End Sub 83 | 84 | Private Sub CheckBoxModifyBitmapVector_Click() 85 | Apply_CheckBoxModifyBitmapVector 86 | End Sub 87 | 88 | Private Sub CheckBoxModifyLocalDPI_Click() 89 | Apply_CheckBoxModifyLocalDPI 90 | End Sub 91 | 92 | Private Sub CheckBoxModifySize_Click() 93 | Apply_CheckBoxModifySize 94 | End Sub 95 | 96 | Private Sub CheckBoxModifyPreserveSize_Click() 97 | Apply_CheckBoxModifyPreserveSize 98 | End Sub 99 | 100 | Private Sub CheckBoxModifyTransparency_Click() 101 | Apply_CheckBoxModifyTransparency 102 | End Sub 103 | 104 | Private Sub CheckBoxModifyResetFormat_Click() 105 | Apply_CheckBoxModifyResetFormat 106 | End Sub 107 | 108 | Private Sub CheckBoxReplace_Click() 109 | Apply_CheckBoxReplace 110 | End Sub 111 | 112 | Private Sub Apply_CheckBoxModifyEngine() 113 | LabelEngine.Enabled = CheckBoxModifyEngine.Value 114 | ComboBoxLaTexEngine.Enabled = CheckBoxModifyEngine.Value 115 | End Sub 116 | 117 | Private Sub Apply_CheckBoxModifyTempFolder() 118 | LabelTempFolder.Enabled = CheckBoxModifyTempFolder.Value 119 | TextBoxTempFolder.Enabled = CheckBoxModifyTempFolder.Value 120 | End Sub 121 | 122 | Private Sub Apply_CheckBoxModifyBitmapVector() 123 | LabelOutput.Enabled = CheckBoxModifyBitmapVector.Value 124 | ComboBoxBitmapVector.Enabled = CheckBoxModifyBitmapVector.Value 125 | End Sub 126 | 127 | Private Sub Apply_CheckBoxModifyLocalDPI() 128 | LabelLocalDPI.Enabled = CheckBoxModifyLocalDPI.Value 129 | TextBoxLocalDPI.Enabled = CheckBoxModifyLocalDPI.Value 130 | LabelDPI.Enabled = CheckBoxModifyLocalDPI.Value 131 | End Sub 132 | 133 | Private Sub Apply_CheckBoxModifySize() 134 | LabelSize.Enabled = CheckBoxModifySize.Value 135 | textboxSize.Enabled = CheckBoxModifySize.Value 136 | LabelPTS.Enabled = CheckBoxModifySize.Value 137 | End Sub 138 | 139 | Private Sub Apply_CheckBoxModifyPreserveSize() 140 | CheckBoxForcePreserveSize.Enabled = CheckBoxModifyPreserveSize.Value 141 | End Sub 142 | 143 | Private Sub Apply_CheckBoxModifyTransparency() 144 | checkboxTransp.Enabled = CheckBoxModifyTransparency.Value 145 | End Sub 146 | 147 | Private Sub Apply_CheckBoxModifyResetFormat() 148 | CheckBoxResetFormat.Enabled = CheckBoxModifyResetFormat.Value 149 | End Sub 150 | 151 | Private Sub Apply_CheckBoxReplace() 152 | LabelReplace.Enabled = CheckBoxReplace.Value 153 | TextBoxFind.Enabled = CheckBoxReplace.Value 154 | LabelWith.Enabled = CheckBoxReplace.Value 155 | TextBoxReplacement.Enabled = CheckBoxReplace.Value 156 | End Sub 157 | 158 | 159 | Private Sub ComboBoxBitmapVector_Change() 160 | Apply_BitmapVector_Change 161 | End Sub 162 | 163 | Private Sub Apply_BitmapVector_Change() 164 | If ComboBoxBitmapVector.ListIndex = 1 Then 165 | CheckBoxModifyLocalDPI.Value = False 166 | CheckBoxModifyTransparency.Value = False 167 | CheckBoxModifyLocalDPI.Enabled = False 168 | CheckBoxModifyTransparency.Enabled = False 169 | checkboxTransp.Value = True 170 | Else 171 | CheckBoxModifyLocalDPI.Enabled = True 172 | CheckBoxModifyTransparency.Enabled = False 173 | End If 174 | Apply_CheckBoxModifyLocalDPI 175 | Apply_CheckBoxModifyTransparency 176 | End Sub 177 | 178 | Private Sub CheckBoxForcePreserveSize_Click() 179 | If CheckBoxForcePreserveSize.Value = True Then 180 | CheckBoxModifySize.Enabled = False 181 | CheckBoxModifySize.Value = False 182 | Else 183 | CheckBoxModifySize.Enabled = True 184 | End If 185 | Apply_CheckBoxModifySize 186 | End Sub 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /IguanaTexHelper/IguanaTexHelper/IguanaTexHelper.m: -------------------------------------------------------------------------------- 1 | #import "IguanaTexHelper.h" 2 | 3 | #import 4 | 5 | @interface TextView : NSTextView 6 | -(instancetype)initWithFrame:(NSRect)frameRect; 7 | @end 8 | 9 | @interface ScrollView : NSScrollView 10 | -(instancetype)initWithFrame:(NSRect)frameRect; 11 | @end 12 | 13 | @interface TextWindow : NSWindow 14 | @property (readonly) BOOL canBecomeKeyWindow; 15 | @property (readonly) BOOL canBecomeMainWindow; 16 | @property (readonly) ScrollView* scrollView; 17 | @property (readonly) TextView* textView; 18 | -(instancetype)initWithContentRect:(NSRect)contentRect; 19 | -(void)parentDidBecomeMain:(NSNotification *)notification; 20 | @end 21 | 22 | static NSMutableDictionary* textWindows(void); 23 | static id FindFocused(id root); 24 | 25 | 26 | @implementation TextView 27 | -(instancetype)initWithFrame:(NSRect)frameRect { 28 | if ((self = [super initWithFrame:frameRect])) { 29 | self.verticallyResizable = YES; 30 | self.horizontallyResizable = NO; 31 | self.autoresizingMask = NSViewWidthSizable; 32 | 33 | self.textContainer.widthTracksTextView = YES; 34 | self.textContainer.containerSize = NSMakeSize(frameRect.size.width, FLT_MAX); 35 | 36 | self.font = [NSFont fontWithName:@"Menlo" size:10]; 37 | self.richText = NO; 38 | self.automaticDashSubstitutionEnabled = NO; 39 | self.automaticQuoteSubstitutionEnabled = NO; 40 | } 41 | return self; 42 | } 43 | @end 44 | 45 | @implementation ScrollView 46 | -(instancetype)initWithFrame:(NSRect)frameRect { 47 | if ((self = [super initWithFrame:frameRect])) { 48 | self.borderType = NSNoBorder; 49 | self.hasVerticalScroller = YES; 50 | self.hasHorizontalScroller = NO; 51 | self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; 52 | } 53 | return self; 54 | } 55 | @end 56 | 57 | @implementation TextWindow 58 | @synthesize scrollView; 59 | @synthesize textView; 60 | -(BOOL)canBecomeKeyWindow { return YES; } 61 | -(BOOL)canBecomeMainWindow { return NO; } 62 | -(instancetype)initWithContentRect:(NSRect)contentRect { 63 | if ((self=[super initWithContentRect:contentRect 64 | styleMask:NSWindowStyleMaskBorderless 65 | backing:NSBackingStoreBuffered 66 | defer:NO])) { 67 | scrollView = [[ScrollView alloc] initWithFrame:contentRect]; 68 | textView = [[TextView alloc] initWithFrame:NSMakeRect(0, 0, contentRect.size.width, contentRect.size.height)]; 69 | scrollView.documentView = textView; 70 | self.contentView = scrollView; 71 | self.initialFirstResponder = textView; 72 | } 73 | 74 | return self; 75 | } 76 | -(void)parentDidBecomeMain:(NSNotification *)notification { 77 | dispatch_queue_t queue = dispatch_get_main_queue(); 78 | dispatch_async(queue, ^(void) { 79 | [self makeKeyWindow]; 80 | }); 81 | } 82 | @end 83 | 84 | 85 | NSMutableDictionary* textWindows(void) 86 | { 87 | static NSMutableDictionary* table = nil; 88 | if (table == nil) 89 | table = [[NSMutableDictionary alloc] init]; 90 | return table; 91 | } 92 | 93 | int64_t TWInit(void) 94 | { 95 | static int64_t lastHandle = 0; 96 | 97 | TextWindow* window = [[TextWindow alloc] initWithContentRect:NSMakeRect(0,0,0,0)]; 98 | 99 | int64_t handle = ++lastHandle; 100 | textWindows()[@(handle)] = window; 101 | 102 | return handle; 103 | } 104 | 105 | int TWTerm(int64_t handle, int64_t b, int64_t c, int64_t d) 106 | { 107 | TextWindow* window = textWindows()[@(handle)]; 108 | if (window != nil) { 109 | [window orderOut:nil]; 110 | [textWindows() removeObjectForKey:@(handle)]; 111 | } 112 | return 0; 113 | } 114 | 115 | int TWShow(int64_t handle, int64_t b, int64_t c, int64_t d) 116 | { 117 | TextWindow* window = textWindows()[@(handle)]; 118 | if (window != nil && !window.isVisible) { 119 | NSWindow* parent = NSApp.mainWindow; 120 | 121 | [parent addChildWindow:window ordered:NSWindowAbove]; 122 | 123 | [NSNotificationCenter.defaultCenter addObserver:window 124 | selector:@selector(parentDidBecomeMain:) 125 | name:NSWindowDidBecomeMainNotification 126 | object:parent]; 127 | } 128 | return 0; 129 | } 130 | 131 | int TWHide(int64_t handle, int64_t b, int64_t c, int64_t d) 132 | { 133 | NSWindow* window = textWindows()[@(handle)]; 134 | if (window != nil) { 135 | NSWindow* parent = NSApp.mainWindow; 136 | [NSNotificationCenter.defaultCenter removeObserver:window 137 | name:NSWindowDidBecomeMainNotification 138 | object:parent]; 139 | [window orderOut:nil]; 140 | } 141 | return 0; 142 | } 143 | 144 | id FindFocused(id root) 145 | { 146 | if (root == nil) 147 | return nil; 148 | if ([root respondsToSelector:@selector(isAccessibilityFocused)] && root.isAccessibilityFocused) 149 | return root; 150 | if ([root respondsToSelector:@selector(accessibilityChildren)]) { 151 | for (id child in root.accessibilityChildren) { 152 | id result = FindFocused(child); 153 | if (result != nil) 154 | return result; 155 | } 156 | } 157 | return nil; 158 | } 159 | 160 | int TWResize(int64_t handle, int64_t b, int64_t c, int64_t d) 161 | { 162 | TextWindow* window = textWindows()[@(handle)]; 163 | if (window != nil) { 164 | NSWindow* parent = NSApp.mainWindow; 165 | id textBox = FindFocused(parent); 166 | if (textBox != nil) 167 | [window setFrame:textBox.accessibilityFrame display:YES]; 168 | } 169 | return 0; 170 | } 171 | 172 | int TWSet(int64_t handle, const char* data, int64_t len, int64_t d) 173 | { 174 | TextWindow* window = textWindows()[@(handle)]; 175 | if (window != nil) { 176 | if (data != nil) 177 | window.textView.string = [[NSString alloc] initWithBytes:data length:len encoding:NSUTF8StringEncoding]; 178 | else 179 | window.textView.string = @""; 180 | } 181 | return 0; 182 | } 183 | 184 | int TWGet(int64_t handle, char** data, int64_t* len, int64_t d) 185 | { 186 | TextWindow* window = textWindows()[@(handle)]; 187 | if (window != nil) { 188 | NSData* bytes = [window.textView.string dataUsingEncoding:NSUTF8StringEncoding]; 189 | *data = malloc(bytes.length); 190 | [bytes getBytes:*data length:bytes.length]; 191 | *len = bytes.length; 192 | } else { 193 | *data = NULL; 194 | *len = 0; 195 | } 196 | return 0; 197 | } 198 | 199 | int TWGetSel(int64_t handle, int64_t b, int64_t c, int64_t d) 200 | { 201 | TextWindow* window = textWindows()[@(handle)]; 202 | if (window != nil) 203 | return (int) window.textView.selectedRange.location; 204 | else 205 | return 0; 206 | } 207 | 208 | int TWSetSel(int64_t handle, int64_t sel, int64_t c, int64_t d) 209 | { 210 | TextWindow* window = textWindows()[@(handle)]; 211 | if (window != nil) 212 | window.textView.selectedRange = NSMakeRange(sel, 0); 213 | return 0; 214 | } 215 | 216 | int TWFocus(int64_t handle, int64_t b, int64_t c, int64_t d) 217 | { 218 | TextWindow* window = textWindows()[@(handle)]; 219 | if (window != nil) 220 | [window makeKeyWindow]; 221 | return 0; 222 | } 223 | 224 | int TWGetSZ(int64_t handle, int64_t b, int64_t c, int64_t d) 225 | { 226 | TextWindow* window = textWindows()[@(handle)]; 227 | if (window != nil) 228 | return (int) window.textView.font.pointSize; 229 | else 230 | return 0; 231 | } 232 | 233 | int TWSetSZ(int64_t handle, int64_t size, int64_t c, int64_t d) 234 | { 235 | TextWindow* window = textWindows()[@(handle)]; 236 | if (window != nil) { 237 | NSFontDescriptor* descriptor = window.textView.font.fontDescriptor; 238 | window.textView.font = [NSFont fontWithDescriptor:descriptor size:size]; 239 | } 240 | return 0; 241 | } 242 | -------------------------------------------------------------------------------- /IguanaTexHelper/IguanaTexHelper.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 621BBA742019F0F50018400B /* IguanaTexHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 629629D020151E2600A8E125 /* IguanaTexHelper.m */; }; 11 | 629629CF20151E2600A8E125 /* IguanaTexHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 629629CE20151E2600A8E125 /* IguanaTexHelper.h */; }; 12 | 629629D9201524BE00A8E125 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 629629D8201524BE00A8E125 /* AppKit.framework */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXFileReference section */ 16 | 629629CB20151E2600A8E125 /* libIguanaTexHelper.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libIguanaTexHelper.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; 17 | 629629CE20151E2600A8E125 /* IguanaTexHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IguanaTexHelper.h; sourceTree = ""; }; 18 | 629629D020151E2600A8E125 /* IguanaTexHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IguanaTexHelper.m; sourceTree = ""; }; 19 | 629629D8201524BE00A8E125 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 20 | /* End PBXFileReference section */ 21 | 22 | /* Begin PBXFrameworksBuildPhase section */ 23 | 629629C820151E2600A8E125 /* Frameworks */ = { 24 | isa = PBXFrameworksBuildPhase; 25 | buildActionMask = 2147483647; 26 | files = ( 27 | 629629D9201524BE00A8E125 /* AppKit.framework in Frameworks */, 28 | ); 29 | runOnlyForDeploymentPostprocessing = 0; 30 | }; 31 | /* End PBXFrameworksBuildPhase section */ 32 | 33 | /* Begin PBXGroup section */ 34 | 629629C220151E2600A8E125 = { 35 | isa = PBXGroup; 36 | children = ( 37 | 629629CD20151E2600A8E125 /* IguanaTexHelper */, 38 | 629629CC20151E2600A8E125 /* Products */, 39 | 629629D7201524BE00A8E125 /* Frameworks */, 40 | ); 41 | sourceTree = ""; 42 | }; 43 | 629629CC20151E2600A8E125 /* Products */ = { 44 | isa = PBXGroup; 45 | children = ( 46 | 629629CB20151E2600A8E125 /* libIguanaTexHelper.dylib */, 47 | ); 48 | name = Products; 49 | sourceTree = ""; 50 | }; 51 | 629629CD20151E2600A8E125 /* IguanaTexHelper */ = { 52 | isa = PBXGroup; 53 | children = ( 54 | 629629CE20151E2600A8E125 /* IguanaTexHelper.h */, 55 | 629629D020151E2600A8E125 /* IguanaTexHelper.m */, 56 | ); 57 | path = IguanaTexHelper; 58 | sourceTree = ""; 59 | }; 60 | 629629D7201524BE00A8E125 /* Frameworks */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 629629D8201524BE00A8E125 /* AppKit.framework */, 64 | ); 65 | name = Frameworks; 66 | sourceTree = ""; 67 | }; 68 | /* End PBXGroup section */ 69 | 70 | /* Begin PBXHeadersBuildPhase section */ 71 | 629629C920151E2600A8E125 /* Headers */ = { 72 | isa = PBXHeadersBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | 629629CF20151E2600A8E125 /* IguanaTexHelper.h in Headers */, 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | /* End PBXHeadersBuildPhase section */ 80 | 81 | /* Begin PBXNativeTarget section */ 82 | 629629CA20151E2600A8E125 /* IguanaTexHelper */ = { 83 | isa = PBXNativeTarget; 84 | buildConfigurationList = 629629D420151E2600A8E125 /* Build configuration list for PBXNativeTarget "IguanaTexHelper" */; 85 | buildPhases = ( 86 | 629629C720151E2600A8E125 /* Sources */, 87 | 629629C820151E2600A8E125 /* Frameworks */, 88 | 629629C920151E2600A8E125 /* Headers */, 89 | ); 90 | buildRules = ( 91 | ); 92 | dependencies = ( 93 | ); 94 | name = IguanaTexHelper; 95 | productName = IguanaTexHelper; 96 | productReference = 629629CB20151E2600A8E125 /* libIguanaTexHelper.dylib */; 97 | productType = "com.apple.product-type.library.dynamic"; 98 | }; 99 | /* End PBXNativeTarget section */ 100 | 101 | /* Begin PBXProject section */ 102 | 629629C320151E2600A8E125 /* Project object */ = { 103 | isa = PBXProject; 104 | attributes = { 105 | LastUpgradeCheck = 1240; 106 | ORGANIZATIONNAME = ray851107; 107 | TargetAttributes = { 108 | 629629CA20151E2600A8E125 = { 109 | CreatedOnToolsVersion = 9.2; 110 | ProvisioningStyle = Manual; 111 | }; 112 | }; 113 | }; 114 | buildConfigurationList = 629629C620151E2600A8E125 /* Build configuration list for PBXProject "IguanaTexHelper" */; 115 | compatibilityVersion = "Xcode 8.0"; 116 | developmentRegion = en; 117 | hasScannedForEncodings = 0; 118 | knownRegions = ( 119 | en, 120 | Base, 121 | ); 122 | mainGroup = 629629C220151E2600A8E125; 123 | productRefGroup = 629629CC20151E2600A8E125 /* Products */; 124 | projectDirPath = ""; 125 | projectRoot = ""; 126 | targets = ( 127 | 629629CA20151E2600A8E125 /* IguanaTexHelper */, 128 | ); 129 | }; 130 | /* End PBXProject section */ 131 | 132 | /* Begin PBXSourcesBuildPhase section */ 133 | 629629C720151E2600A8E125 /* Sources */ = { 134 | isa = PBXSourcesBuildPhase; 135 | buildActionMask = 2147483647; 136 | files = ( 137 | 621BBA742019F0F50018400B /* IguanaTexHelper.m in Sources */, 138 | ); 139 | runOnlyForDeploymentPostprocessing = 0; 140 | }; 141 | /* End PBXSourcesBuildPhase section */ 142 | 143 | /* Begin XCBuildConfiguration section */ 144 | 629629D220151E2600A8E125 /* Debug */ = { 145 | isa = XCBuildConfiguration; 146 | buildSettings = { 147 | ALWAYS_SEARCH_USER_PATHS = NO; 148 | CLANG_ANALYZER_NONNULL = YES; 149 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 150 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 151 | CLANG_CXX_LIBRARY = "libc++"; 152 | CLANG_ENABLE_MODULES = YES; 153 | CLANG_ENABLE_OBJC_ARC = YES; 154 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 155 | CLANG_WARN_BOOL_CONVERSION = YES; 156 | CLANG_WARN_COMMA = YES; 157 | CLANG_WARN_CONSTANT_CONVERSION = YES; 158 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 159 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 160 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 161 | CLANG_WARN_EMPTY_BODY = YES; 162 | CLANG_WARN_ENUM_CONVERSION = YES; 163 | CLANG_WARN_INFINITE_RECURSION = YES; 164 | CLANG_WARN_INT_CONVERSION = YES; 165 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 166 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 167 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 168 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 169 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 170 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 171 | CLANG_WARN_STRICT_PROTOTYPES = YES; 172 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 173 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 174 | CLANG_WARN_UNREACHABLE_CODE = YES; 175 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 176 | CODE_SIGN_IDENTITY = "-"; 177 | COPY_PHASE_STRIP = NO; 178 | DEBUG_INFORMATION_FORMAT = dwarf; 179 | ENABLE_STRICT_OBJC_MSGSEND = YES; 180 | ENABLE_TESTABILITY = YES; 181 | GCC_C_LANGUAGE_STANDARD = gnu11; 182 | GCC_DYNAMIC_NO_PIC = NO; 183 | GCC_NO_COMMON_BLOCKS = YES; 184 | GCC_OPTIMIZATION_LEVEL = 0; 185 | GCC_PREPROCESSOR_DEFINITIONS = ( 186 | "DEBUG=1", 187 | "$(inherited)", 188 | ); 189 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 190 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 191 | GCC_WARN_UNDECLARED_SELECTOR = YES; 192 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 193 | GCC_WARN_UNUSED_FUNCTION = YES; 194 | GCC_WARN_UNUSED_VARIABLE = YES; 195 | MACOSX_DEPLOYMENT_TARGET = 10.13; 196 | MTL_ENABLE_DEBUG_INFO = YES; 197 | ONLY_ACTIVE_ARCH = YES; 198 | SDKROOT = macosx; 199 | }; 200 | name = Debug; 201 | }; 202 | 629629D320151E2600A8E125 /* Release */ = { 203 | isa = XCBuildConfiguration; 204 | buildSettings = { 205 | ALWAYS_SEARCH_USER_PATHS = NO; 206 | CLANG_ANALYZER_NONNULL = YES; 207 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 208 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 209 | CLANG_CXX_LIBRARY = "libc++"; 210 | CLANG_ENABLE_MODULES = YES; 211 | CLANG_ENABLE_OBJC_ARC = YES; 212 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 213 | CLANG_WARN_BOOL_CONVERSION = YES; 214 | CLANG_WARN_COMMA = YES; 215 | CLANG_WARN_CONSTANT_CONVERSION = YES; 216 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 217 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 218 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 219 | CLANG_WARN_EMPTY_BODY = YES; 220 | CLANG_WARN_ENUM_CONVERSION = YES; 221 | CLANG_WARN_INFINITE_RECURSION = YES; 222 | CLANG_WARN_INT_CONVERSION = YES; 223 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 224 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 225 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 226 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 227 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 228 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 229 | CLANG_WARN_STRICT_PROTOTYPES = YES; 230 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 231 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 232 | CLANG_WARN_UNREACHABLE_CODE = YES; 233 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 234 | CODE_SIGN_IDENTITY = "-"; 235 | COPY_PHASE_STRIP = NO; 236 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 237 | ENABLE_NS_ASSERTIONS = NO; 238 | ENABLE_STRICT_OBJC_MSGSEND = YES; 239 | GCC_C_LANGUAGE_STANDARD = gnu11; 240 | GCC_NO_COMMON_BLOCKS = YES; 241 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 242 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 243 | GCC_WARN_UNDECLARED_SELECTOR = YES; 244 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 245 | GCC_WARN_UNUSED_FUNCTION = YES; 246 | GCC_WARN_UNUSED_VARIABLE = YES; 247 | MACOSX_DEPLOYMENT_TARGET = 10.13; 248 | MTL_ENABLE_DEBUG_INFO = NO; 249 | SDKROOT = macosx; 250 | }; 251 | name = Release; 252 | }; 253 | 629629D520151E2600A8E125 /* Debug */ = { 254 | isa = XCBuildConfiguration; 255 | buildSettings = { 256 | CODE_SIGN_IDENTITY = ""; 257 | CODE_SIGN_STYLE = Manual; 258 | DEVELOPMENT_TEAM = ""; 259 | DYLIB_COMPATIBILITY_VERSION = 1; 260 | DYLIB_CURRENT_VERSION = 1; 261 | EXECUTABLE_PREFIX = lib; 262 | GCC_SYMBOLS_PRIVATE_EXTERN = YES; 263 | PRODUCT_NAME = "$(TARGET_NAME)"; 264 | PROVISIONING_PROFILE_SPECIFIER = ""; 265 | }; 266 | name = Debug; 267 | }; 268 | 629629D620151E2600A8E125 /* Release */ = { 269 | isa = XCBuildConfiguration; 270 | buildSettings = { 271 | CODE_SIGN_IDENTITY = ""; 272 | CODE_SIGN_STYLE = Manual; 273 | DEVELOPMENT_TEAM = ""; 274 | DYLIB_COMPATIBILITY_VERSION = 1; 275 | DYLIB_CURRENT_VERSION = 1; 276 | EXECUTABLE_PREFIX = lib; 277 | GCC_SYMBOLS_PRIVATE_EXTERN = YES; 278 | PRODUCT_NAME = "$(TARGET_NAME)"; 279 | PROVISIONING_PROFILE_SPECIFIER = ""; 280 | }; 281 | name = Release; 282 | }; 283 | /* End XCBuildConfiguration section */ 284 | 285 | /* Begin XCConfigurationList section */ 286 | 629629C620151E2600A8E125 /* Build configuration list for PBXProject "IguanaTexHelper" */ = { 287 | isa = XCConfigurationList; 288 | buildConfigurations = ( 289 | 629629D220151E2600A8E125 /* Debug */, 290 | 629629D320151E2600A8E125 /* Release */, 291 | ); 292 | defaultConfigurationIsVisible = 0; 293 | defaultConfigurationName = Release; 294 | }; 295 | 629629D420151E2600A8E125 /* Build configuration list for PBXNativeTarget "IguanaTexHelper" */ = { 296 | isa = XCConfigurationList; 297 | buildConfigurations = ( 298 | 629629D520151E2600A8E125 /* Debug */, 299 | 629629D620151E2600A8E125 /* Release */, 300 | ); 301 | defaultConfigurationIsVisible = 0; 302 | defaultConfigurationName = Release; 303 | }; 304 | /* End XCConfigurationList section */ 305 | }; 306 | rootObject = 629629C320151E2600A8E125 /* Project object */; 307 | } 308 | -------------------------------------------------------------------------------- /SetTempForm.frm: -------------------------------------------------------------------------------- 1 | VERSION 5.00 2 | Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} SetTempForm 3 | Caption = "Default Settings and Paths" 4 | ClientHeight = 7230 5 | ClientLeft = 20 6 | ClientTop = 340 7 | ClientWidth = 6280 8 | OleObjectBlob = "SetTempForm.frx":0000 9 | StartUpPosition = 1 'CenterOwner 10 | End 11 | Attribute VB_Name = "SetTempForm" 12 | Attribute VB_GlobalNameSpace = False 13 | Attribute VB_Creatable = False 14 | Attribute VB_PredeclaredId = True 15 | Attribute VB_Exposed = False 16 | Dim LaTexEngineList As Variant 17 | Dim LaTexEngineDisplayList As Variant 18 | Dim UsePDFList As Variant 19 | 20 | Private Sub ButtonAbsTempPath_Click() 21 | AbsPathTextBox.Text = MacChooseFolder(AbsPathTextBox.Text) 22 | End Sub 23 | 24 | Private Sub ButtonCancelTemp_Click() 25 | Unload SetTempForm 26 | End Sub 27 | 28 | Private Sub ButtonEditorPath_Click() 29 | TextBoxExternalEditor.Text = "open -b " & ShellEscape(MacChooseApp(TextBoxExternalEditor.Text)) 30 | TextBoxExternalEditor.SetFocus 31 | End Sub 32 | 33 | Private Sub ButtonGSPath_Click() 34 | TextBoxGS.Text = MacChooseFile(TextBoxGS.Text) 35 | TextBoxGS.SetFocus 36 | End Sub 37 | 38 | Private Sub ButtonIMPath_Click() 39 | TextBoxIMconv.Text = MacChooseFile(TextBoxIMconv.Text) 40 | TextBoxIMconv.SetFocus 41 | End Sub 42 | 43 | 44 | Private Sub ButtonTeX2img_Click() 45 | TextBoxTeX2img.Text = MacChooseFile(TextBoxTeX2img.Text) 46 | TextBoxTeX2img.SetFocus 47 | End Sub 48 | 49 | Private Sub ButtonTeXExePath_Click() 50 | TextBoxTeXExePath.Text = MacChooseFolder(TextBoxTeXExePath.Text) 51 | TextBoxTeXExePath.SetFocus 52 | End Sub 53 | 54 | Private Sub ButtonSetTemp_Click() 55 | Dim RegPath As String 56 | Dim res As String 57 | RegPath = "Software\IguanaTex" 58 | 59 | ' Temp folder 60 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "AbsOrRel", REG_DWORD, BoolToInt(AbsPathButton.Value) 61 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "Abs Temp Dir", REG_SZ, CStr(AbsPathTextBox.Text) 62 | If Left(RelPathTextBox.Text, 2) = "." & PathSeperator Then 63 | RelPathTextBox.Text = Mid(RelPathTextBox.Text, 3, Len(RelPathTextBox.Text) - 2) 64 | End If 65 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "Rel Temp Dir", REG_SZ, CStr(RelPathTextBox.Text) 66 | 67 | If AbsPathButton.Value = True Then 68 | res = AbsPathTextBox.Text 69 | Else 70 | res = "." & PathSeperator & RelPathTextBox.Text 71 | End If 72 | If res <> "" And Right(res, 1) <> PathSeperator Then 73 | res = res & PathSeperator 74 | End If 75 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "Temp Dir", REG_SZ, CStr(res) 76 | 77 | ' UTF8 78 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "UseUTF8", REG_DWORD, BoolToInt(CheckBoxUTF8.Value) 79 | 80 | ' Vector or Bitmap (EMF or PNG) 81 | 'SetRegistryValue HKEY_CURRENT_USER, RegPath, "EMFoutput", REG_DWORD, BoolToInt(CheckBoxEMF.Value) 82 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "BitmapVector", REG_DWORD, ComboBoxBitmapVector.ListIndex 83 | 84 | ' GS command 85 | res = TextBoxGS.Text 86 | ' no need to remove quotes on mac because we use open -b '....' 87 | ' If Left(res, 1) = """" Then res = Mid(res, 2, Len(res) - 1) 88 | ' If Right(res, 1) = """" Then res = Left(res, Len(res) - 1) 89 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "GS Command", REG_SZ, CStr(res) 90 | 91 | ' Path to ImageMagick Convert 92 | res = TextBoxIMconv.Text 93 | If Left(res, 1) = """" Then res = Mid(res, 2, Len(res) - 1) 94 | If Right(res, 1) = """" Then res = Left(res, Len(res) - 1) 95 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "IMconv", REG_SZ, CStr(res) 96 | 97 | ' Path to External Editor 98 | res = TextBoxExternalEditor.Text 99 | If Left(res, 1) = """" Then res = Mid(res, 2, Len(res) - 1) 100 | If Right(res, 1) = """" Then res = Left(res, Len(res) - 1) 101 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "Editor", REG_SZ, CStr(res) 102 | 103 | ' Path to TeX2img (Vector output) 104 | res = TextBoxTeX2img.Text 105 | If Left(res, 1) = """" Then res = Mid(res, 2, Len(res) - 1) 106 | If Right(res, 1) = """" Then res = Left(res, Len(res) - 1) 107 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "TeX2img Command", REG_SZ, CStr(res) 108 | 109 | ' Path to TeX Executables Folder 110 | res = TextBoxTeXExePath.Text 111 | If Left(res, 1) = """" Then res = Mid(res, 2, Len(res) - 1) 112 | If Right(res, 1) = """" Then res = Left(res, Len(res) - 1) 113 | If res <> "" And Right(res, 1) <> PathSeperator Then res = res & PathSeperator 114 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "TeXExePath", REG_SZ, CStr(res) 115 | 116 | ' Magic scaling factor to fine-tune the scaling of Vector displays 117 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "VectorScalingX", REG_SZ, TextBoxVectorScalingX.Text 118 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "VectorScalingY", REG_SZ, TextBoxVectorScalingY.Text 119 | 120 | ' Magic scaling factor to fine-tune the scaling of PNG displays 121 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "BitmapScalingX", REG_SZ, TextBoxBitmapScalingX.Text 122 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "BitmapScalingY", REG_SZ, TextBoxBitmapScalingY.Text 123 | 124 | ' Global dpi setting for latex output 125 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "OutputDpi", REG_DWORD, CLng(val(TextBoxDpi.Text)) 126 | 127 | ' Time Out Interval for Processes 128 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "TimeOutTime", REG_DWORD, CLng(val(TextBoxTimeOut.Text)) 129 | 130 | ' Font size for text in editor/template windows 131 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "EditorFontSize", REG_DWORD, CLng(val(TextBoxFontSize.Text)) 132 | 133 | ' LaTeX Engine 134 | 'SetRegistryValue HKEY_CURRENT_USER, RegPath, "LaTeXEngine", REG_SZ, CStr(ComboBoxEngine.Text) 135 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "LaTeXEngineID", REG_DWORD, ComboBoxEngine.ListIndex 136 | 137 | 138 | Unload SetTempForm 139 | End Sub 140 | 141 | 142 | Private Sub AbsPathButton_Click() 143 | AbsPathButton.Value = True 144 | SetAbsRelDependencies 145 | End Sub 146 | 147 | 148 | Private Sub LabelDLgs_Click() 149 | Link = "http://www.ghostscript.com/download/gsdnld.html" 150 | Dim lSuccess As Long 151 | lSuccess = OpenLink(Link) 152 | If (lSuccess = 0) Then 153 | MsgBox "Cannot open " & Link 154 | End If 155 | End Sub 156 | 157 | Private Sub LabelDLImageMagick_Click() 158 | Link = "http://www.imagemagick.org/script/download.php#windows" 159 | Dim lSuccess As Long 160 | lSuccess = OpenLink(Link) 161 | If (lSuccess = 0) Then 162 | MsgBox "Cannot open " & Link 163 | End If 164 | End Sub 165 | 166 | Private Sub LabelDLTeX2img_Click() 167 | Link = "https://www.ms.u-tokyo.ac.jp/~abenori/soft/bin/TeX2img_2.1.0.zip" 168 | Dim lSuccess As Long 169 | lSuccess = OpenLink(Link) 170 | If (lSuccess = 0) Then 171 | MsgBox "Cannot open " & Link 172 | End If 173 | End Sub 174 | 175 | Private Sub LabelTeX2imgGithub_Click() 176 | Link = "https://github.com/abenori/TeX2img" 177 | Dim lSuccess As Long 178 | lSuccess = OpenLink(Link) 179 | If (lSuccess = 0) Then 180 | MsgBox "Cannot open " & Link 181 | End If 182 | End Sub 183 | 184 | Private Sub LabelDLtexstudio_Click() 185 | Link = "http://www.texstudio.org/" 186 | Dim lSuccess As Long 187 | lSuccess = OpenLink(Link) 188 | If (lSuccess = 0) Then 189 | MsgBox "Cannot open " & Link 190 | End If 191 | End Sub 192 | 193 | Private Sub RelPathButton_Click() 194 | AbsPathButton.Value = False 195 | SetAbsRelDependencies 196 | End Sub 197 | 198 | Private Sub SetAbsRelDependencies() 199 | RelPathButton.Value = Not AbsPathButton.Value 200 | AbsPathTextBox.Enabled = AbsPathButton.Value 201 | RelPathTextBox.Enabled = RelPathButton.Value 202 | End Sub 203 | 204 | 'Private Sub CheckBoxPDF_Click() 205 | ' 206 | ' If CheckBoxPDF.Value = True Then 207 | ' TextBoxGS.Enabled = True 208 | ' TextBoxIMconv.Enabled = True 209 | ' Else 210 | ' TextBoxGS.Enabled = False 211 | ' TextBoxIMconv.Enabled = False 212 | ' End If 213 | 'End Sub 214 | 215 | Private Sub SetPDFdependencies() 216 | If UsePDFList(ComboBoxEngine.ListIndex) = True Then 217 | TextBoxGS.Enabled = True 218 | TextBoxIMconv.Enabled = True 219 | Else 220 | TextBoxGS.Enabled = False 221 | TextBoxIMconv.Enabled = False 222 | End If 223 | End Sub 224 | 225 | Private Sub Reset_Click() 226 | AbsPathButton.Value = True 227 | 228 | CheckBoxUTF8.Value = True 229 | 230 | 'CheckBoxEMF.Value = False 231 | ComboBoxBitmapVector.ListIndex = 0 232 | 233 | TextBoxGS.Text = DEFAULT_GS_COMMAND 234 | 235 | TextBoxIMconv.Text = DEFAULT_IM_CONV 236 | 237 | TextBoxTeX2img.Text = DEFAULT_TEX2IMG_COMMAND 238 | 239 | TextBoxTeXExePath.Text = DEFAULT_TEX_EXE_PATH 240 | 241 | TextBoxDpi.Text = "1200" 242 | 243 | TextBoxVectorScalingX.Text = "1" 244 | TextBoxVectorScalingY.Text = "1" 245 | 246 | TextBoxBitmapScalingX.Text = "1" 247 | TextBoxBitmapScalingY.Text = "1" 248 | 249 | TextBoxTimeOut.Text = "60" 250 | 251 | TextBoxFontSize.Text = "10" 252 | 253 | ComboBoxEngine.ListIndex = 0 254 | 255 | 'SetPDFdependencies 256 | SetAbsRelDependencies 257 | 258 | End Sub 259 | 260 | 261 | 262 | Private Sub UserForm_Initialize() 263 | 264 | Me.Top = Application.Top + 110 265 | Me.Left = Application.Left + 25 266 | 267 | Dim res As String 268 | RegPath = "Software\IguanaTex" 269 | 270 | res = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "Abs Temp Dir", "") 271 | If res <> "" And Right(res, 1) <> PathSeperator Then 272 | res = res & PathSeperator 273 | End If 274 | AbsPathTextBox.Text = res 275 | 276 | res = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "Rel Temp Dir", "") 277 | RelPathTextBox.Text = res 278 | 279 | AbsPathButton.Value = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "AbsOrRel", True) 280 | 281 | CheckBoxUTF8.Value = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "UseUTF8", True) 282 | 283 | TextBoxGS.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "GS Command", DEFAULT_GS_COMMAND) 284 | 285 | TextBoxIMconv.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "IMconv", DEFAULT_IM_CONV) 286 | 287 | TextBoxDpi.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "OutputDpi", "1200") 288 | 289 | TextBoxTimeOut.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "TimeOutTime", "60") 290 | 291 | TextBoxFontSize.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "EditorFontSize", "10") 292 | 293 | TextBoxVectorScalingX.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "VectorScalingX", "1") 294 | TextBoxVectorScalingY.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "VectorScalingY", "1") 295 | 296 | TextBoxBitmapScalingX.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "BitmapScalingX", "1") 297 | TextBoxBitmapScalingY.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "BitmapScalingY", "1") 298 | 299 | TextBoxExternalEditor.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "Editor", DEFAULT_EDITOR) 300 | 301 | TextBoxTeX2img.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "TeX2img Command", DEFAULT_TEX2IMG_COMMAND) 302 | 303 | TextBoxTeXExePath.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "TeXExePath", DEFAULT_TEX_EXE_PATH) 304 | 305 | 'CheckBoxEMF.Value = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "EMFoutput", False) 306 | ComboBoxBitmapVector.List = Array("Bitmap", "Vector") 307 | ComboBoxBitmapVector.ListIndex = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "BitmapVector", 0) 308 | 309 | LaTexEngineDisplayList = Array("latex", "pdflatex", "xelatex", "lualatex", "platex") 310 | UsePDFList = Array(False, True, True, True, True) 311 | 312 | ComboBoxEngine.List = LaTexEngineDisplayList 313 | ComboBoxEngine.ListIndex = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "LaTeXEngineID", 0) 314 | 'CheckBoxPDF.Value = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "UsePDF", False) 315 | 316 | 'SetPDFdependencies 317 | SetAbsRelDependencies 318 | End Sub 319 | 320 | Private Function BoolToInt(val) As Long 321 | If val Then 322 | BoolToInt = 1& 323 | Else 324 | BoolToInt = 0& 325 | End If 326 | End Function 327 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /LoadVectorGraphicsForm.frm: -------------------------------------------------------------------------------- 1 | VERSION 5.00 2 | Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} LoadVectorGraphicsForm 3 | Caption = "Load Vector Graphics File" 4 | ClientHeight = 3135 5 | ClientLeft = 120 6 | ClientTop = 460 7 | ClientWidth = 6880 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 | Dim lastPath As String 17 | 18 | Private Sub CommandButtonSave_Click() 19 | Dim RegPath As String 20 | RegPath = "Software\IguanaTex" 21 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "LoadVectorFileConvertLines", REG_DWORD, BoolToInt(CheckBoxConvertLines.Value) 22 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "LoadVectorFileScaling", REG_SZ, textboxScalor.Text 23 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "LoadVectorFileCalibrationX", REG_SZ, TextBoxCalibrationX.Text 24 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "LoadVectorFileCalibrationY", REG_SZ, TextBoxCalibrationY.Text 25 | End Sub 26 | 27 | Private Function BoolToInt(val) As Long 28 | If val Then 29 | BoolToInt = 1& 30 | Else 31 | BoolToInt = 0& 32 | End If 33 | End Function 34 | 35 | 36 | Private Sub UserForm_Initialize() 37 | Me.Top = Application.Top + 110 38 | Me.Left = Application.Left + 25 39 | Dim RegPath As String 40 | RegPath = "Software\IguanaTex" 41 | textboxScalor.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "LoadVectorFileScaling", "1") 42 | CheckBoxConvertLines.Value = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "LoadVectorFileConvertLines", False) 43 | TextBoxCalibrationX.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "LoadVectorFileCalibrationX", "1") 44 | TextBoxCalibrationY.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "LoadVectorFileCalibrationY", "1") 45 | End Sub 46 | 47 | Private Sub ButtonCancel_Click() 48 | Unload LoadVectorGraphicsForm 49 | End Sub 50 | 51 | Private Function isEpsEmf(file As String) 52 | Ext = LCase(Right$(file, 3)) 53 | If Ext = "eps" Or Ext = "emf" Or Ext = "pdf" Or Ext = ".ps" Then 54 | isEpsEmf = True 55 | Else 56 | isEpsEmf = False 57 | End If 58 | End Function 59 | 60 | Sub ButtonPath_Click() 61 | TextBoxFile.Text = MacChooseFileOfType("pdf,ps,eps,emf") 62 | TextBoxFile.SetFocus 63 | 64 | End Sub 65 | 66 | Private Sub TextBoxFile_Change() 67 | Set fs = New FileSystemObject 68 | ButtonLoadFile.Enabled = fs.FileExists(TextBoxFile.Text) And isEpsEmf(TextBoxFile.Text) 69 | End Sub 70 | 71 | Private Sub ButtonLoadFile_Click() 72 | Call InsertVectorGraphicsFile 73 | Unload LoadVectorGraphicsForm 74 | End Sub 75 | 76 | 77 | Public Sub InsertVectorGraphicsFile() 78 | Dim PosX As Single, PosY As Single, ScalingX As Single, ScalingY As Single 79 | PosX = 200 80 | PosY = 200 81 | Dim newShape As Shape 82 | Dim TimeOutTimeString As String 83 | Dim TimeOutTime As Long 84 | RegPath = "Software\IguanaTex" 85 | TimeOutTimeString = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "TimeOutTime", "20") ' Wait 20 seconds for the processes to complete 86 | TimeOutTime = val(TimeOutTimeString) * 1000 87 | Dim debugMode As Boolean 88 | debugMode = False 89 | Set fs = New FileSystemObject 90 | 91 | Dim StartFolder As String 92 | If ActivePresentation.path <> "" Then 93 | StartFolder = ActivePresentation.path 94 | Else 95 | StartFolder = "C:\" 96 | End If 97 | 98 | ' Get the path and extension of the file to be inserted 99 | Dim path As String, Ext As String, pdfPath As String, psPath As String 100 | path = TextBoxFile.Text 101 | Ext = LCase(Right$(path, 3)) 102 | 103 | Dim DeleteTmpPDF As Boolean 104 | DeleteTmpPDF = False 105 | 106 | ' If .ps file, convert to .pdf first, using ps2pdf 107 | If Ext = ".ps" Then 108 | psPath = path + "_tmp.ps" 109 | pdfPath = path + "_tmp.pdf" 110 | fs.CopyFile path, psPath 111 | If fs.FileExists(pdfPath) Then fs.DeleteFile pdfPath 112 | RetVal& = Execute("ps2pdf " & ShellEscape(psPath) & " " & ShellEscape(pdfPath), StartFolder, debugMode, TimeOutTime) 113 | If (RetVal& <> 0 Or Not fs.FileExists(pdfPath)) Then 114 | MsgBox "PS to PDF conversion failed" _ 115 | & vbNewLine & "Make sure ps2pdf.exe is installed (it comes with, e.g., Tex Live, MikTeX or Ghostscript) and can be run from anywhere via the command line" 116 | Exit Sub 117 | End If 118 | Ext = "pdf" 119 | path = pdfPath 120 | DeleteTmpPDF = True 121 | End If 122 | ' If .eps file, convert to .pdf first, using epspdf 123 | If Ext = "eps" Then 124 | psPath = path + "_tmp.eps" 125 | pdfPath = path + "_tmp.pdf" 126 | fs.CopyFile path, psPath 127 | If fs.FileExists(pdfPath) Then fs.DeleteFile pdfPath 128 | RetVal& = Execute("epspdf " & ShellEscape(psPath) & " " & ShellEscape(pdfPath), StartFolder, debugMode, TimeOutTime) 129 | If (RetVal& <> 0 Or Not fs.FileExists(pdfPath)) Then 130 | MsgBox " EPS to PDF conversion failed" _ 131 | & vbNewLine & "Make sure epspdf.exe is installed (it comes with Tex Live or MikTeX) and can be run from anywhere via the command line" 132 | Exit Sub 133 | End If 134 | Ext = "pdf" 135 | path = pdfPath 136 | DeleteTmpPDF = True 137 | End If 138 | ' Now we're either dealing with a .pdf file or a .emf file 139 | 140 | ' If .pdf file, convert to .emf first, using pdfiumdraw, which is part of TeX2img 141 | If Ext = "pdf" Then 142 | Dim emfPath As String 143 | emfPath = Left$(path, Len(path) - 3) + "emf" 144 | Dim TmpPath As String 145 | TmpPath = path + "_copy.emf" 146 | If fs.FileExists(TmpPath) Then fs.DeleteFile TmpPath 147 | If fs.FileExists(emfPath) Then 148 | fs.CopyFile emfPath, TmpPath 149 | fs.DeleteFile emfPath 150 | End If 151 | tex2img_command = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "TeX2img Command", "%USERPROFILE%\Downloads\TeX2img\TeX2imgc.exe") 152 | pdfiumdraw_command = Left$(tex2img_command, Len(tex2img_command) - Len("TeX2imgc.exe")) + "pdfiumdraw.exe" 153 | RetVal& = Execute("""" & pdfiumdraw_command & """ --extent=50 --emf --transparent --pages=1 """ + path + """", StartFolder, debugMode, TimeOutTime) 154 | If (RetVal& <> 0 Or Not fs.FileExists(emfPath)) Then 155 | MsgBox " PDF to EMF conversion failed" _ 156 | & vbNewLine & "Make sure to correctly set the path to Tex2imgc.exe in Main Settings." _ 157 | & vbNewLine & "IguanaTex uses that path to find pdfiumdraw.exe." 158 | Exit Sub 159 | End If 160 | Ext = "emf" 161 | Set newShape = AddDisplayShape(emfPath, PosX, PosY) 162 | If debugMode Then 163 | If fs.FileExists(TmpPath) Then ' Need to swap _copy.emf and the newly created file 164 | Dim TmpTmpPath As String 165 | TmpTmpPath = TmpPath + "_copy.emf" 166 | fs.CopyFile emfPath, TmpTmpPath 167 | fs.DeleteFile emfPath 168 | fs.CopyFile TmpPath, emfPath 169 | fs.DeleteFile TmpPath 170 | fs.CopyFile TmpTmpPath, TmpPath 171 | fs.DeleteFile TmpTmpPath 172 | End If 173 | Else 'Clean up 174 | If fs.FileExists(emfPath) Then fs.DeleteFile emfPath 175 | If DeleteTmpPDF Then 176 | If fs.FileExists(pdfPath) Then fs.DeleteFile pdfPath 177 | End If 178 | If fs.FileExists(TmpPath) Then 179 | fs.CopyFile TmpPath, emfPath 180 | fs.DeleteFile TmpPath 181 | End If 182 | End If 183 | Else 184 | Set newShape = AddDisplayShape(path, PosX, PosY) 185 | End If 186 | 187 | 188 | ' If Ext = "emf" Then 189 | ' dpi = lDotsPerInch 190 | ' default_screen_dpi = 96 191 | ' If dpi <> default_screen_dpi Then 192 | ' Dim VectorScalingX As Single, VectorScalingY As Single 193 | ' VectorScalingX = 2 * dpi / default_screen_dpi '* val(GetRegistryValue(HKEY_CURRENT_USER, RegPath, "VectorScalingX", "1")) 194 | ' VectorScalingY = 2 * dpi / default_screen_dpi '* val(GetRegistryValue(HKEY_CURRENT_USER, RegPath, "VectorScalingY", "1")) 195 | ' ScalingX = textboxScalor.Value * VectorScalingX 196 | ' ScalingY = textboxScalor.Value * VectorScalingY 197 | ' Else 198 | ' ScalingX = textboxScalor.Value 199 | ' ScalingY = textboxScalor.Value 200 | ' End If 201 | ' 202 | ' Else 203 | ' ScalingX = textboxScalor.Value 204 | ' ScalingY = textboxScalor.Value 205 | ' End If 206 | ScalingX = textboxScalor.Value * TextBoxCalibrationX.Value 207 | ScalingY = textboxScalor.Value * TextBoxCalibrationY.Value 208 | 209 | Dim ConvertLines As Boolean 210 | ConvertLines = CheckBoxConvertLines.Value 211 | Set newShape = ConvertEMF(newShape, ScalingX, ScalingY, Ext, ConvertLines) 212 | newShape.Select 213 | End Sub 214 | 215 | Private Function ConvertEMF(inSh As Shape, ScalingX As Single, ScalingY As Single, _ 216 | Optional FileType As String = "emf", Optional ConvertLines As Boolean = True) As Shape 217 | With inSh 218 | .ScaleHeight 1#, msoTrue 219 | .ScaleWidth 1#, msoTrue 220 | .LockAspectRatio = msoFalse 221 | .ScaleHeight ScalingY, msoTrue 222 | .ScaleWidth ScalingX, msoTrue 223 | .LockAspectRatio = msoTrue 224 | End With 225 | 226 | Dim newShape As Shape 227 | ' Get current slide, it will be used to group ranges 228 | Dim sld As Slide 229 | Dim SlideIndex As Long 230 | SlideIndex = ActiveWindow.View.Slide.SlideIndex 231 | Set sld = ActivePresentation.Slides(SlideIndex) 232 | 233 | ' Convert EMF image to object 234 | Dim Shr As ShapeRange 235 | Set Shr = inSh.Ungroup 236 | If FileType = "emf" Then 237 | Set Shr = Shr.Ungroup 238 | ' Clean up 239 | Shr.Item(1).Delete 240 | Shr.Item(2).Delete 241 | If Shr(3).GroupItems.count > 2 Then 242 | Set newShape = Shr(3) 243 | Else ' only a single freeform, so not a group 244 | Set newShape = Shr(3).GroupItems(2) 245 | End If 246 | Shr(3).GroupItems(1).Delete 247 | ElseIf FileType = "eps" Then 248 | Shr.GroupItems(1).Delete 249 | Shr.GroupItems(1).Delete 250 | Set newShape = Shr.Ungroup.Group 251 | End If 252 | 253 | 254 | If newShape.Type = msoGroup Then 255 | 256 | Dim arr_group() As Variant 257 | arr_group = GetAllShapesInGroup(newShape) 258 | Call FullyUngroupShape(newShape) 259 | Set newShape = sld.Shapes.Range(arr_group).Group 260 | 261 | Dim emf_arr() As Variant ' gather all shapes to be regrouped later on 262 | j_emf = 0 263 | Dim delete_arr() As Variant ' gather all shapes to be deleted later on 264 | j_delete = 0 265 | Dim s As Shape 266 | For Each s In newShape.GroupItems 267 | j_emf = j_emf + 1 268 | ReDim Preserve emf_arr(1 To j_emf) 269 | If s.Type = msoLine Then 270 | If ConvertLines And (s.Height > 0 Or s.Width > 0) Then 271 | emf_arr(j_emf) = LineToFreeform(s).name 272 | j_delete = j_delete + 1 273 | ReDim Preserve delete_arr(1 To j_delete) 274 | delete_arr(j_delete) = s.name 275 | Else 276 | emf_arr(j_emf) = s.name 277 | End If 278 | Else 279 | emf_arr(j_emf) = s.name 280 | If s.Fill.Visible = msoTrue Then 281 | s.Line.Visible = msoFalse 282 | Else 283 | s.Line.Visible = msoTrue 284 | 285 | End If 286 | End If 287 | Next 288 | newShape.Ungroup 289 | If j_delete > 0 Then 290 | sld.Shapes.Range(delete_arr).Delete 291 | End If 292 | Set newShape = sld.Shapes.Range(emf_arr).Group 293 | 294 | Else 295 | If newShape.Type = msoLine Then 296 | newShapeName = LineToFreeform(newShape).name 297 | newShape.Delete 298 | Set newShape = sld.Shapes(newShapeName) 299 | Else 300 | newShape.Line.Visible = msoFalse 301 | End If 302 | End If 303 | newShape.LockAspectRatio = msoTrue 304 | Set ConvertEMF = newShape 305 | End Function 306 | 307 | Private Sub FullyUngroupShape(newShape As Shape) 308 | Dim Shr As ShapeRange 309 | Dim s As Shape 310 | If newShape.Type = msoGroup Then 311 | Set Shr = newShape.Ungroup 312 | For i = 1 To Shr.count 313 | Set s = Shr.Item(i) 314 | If s.Type = msoGroup Then 315 | Call FullyUngroupShape(s) 316 | End If 317 | Next 318 | End If 319 | End Sub 320 | 321 | Private Function GetAllShapesInGroup(newShape As Shape) As Variant 322 | Dim arr() As Variant 323 | Dim j As Long 324 | Dim s As Shape 325 | For Each s In newShape.GroupItems 326 | j = j + 1 327 | ReDim Preserve arr(1 To j) 328 | arr(j) = s.name 329 | Next 330 | GetAllShapesInGroup = arr 331 | End Function 332 | 333 | Private Function LineToFreeform(s As Shape) As Shape 334 | t = s.Line.Weight 335 | Dim ApplyTransform As Boolean 336 | ApplyTransform = True 337 | 338 | Dim bHflip As Boolean 339 | Dim bVflip As Boolean 340 | Dim nBegin As Long 341 | Dim nEnd As Long 342 | Dim aC(1 To 4, 1 To 2) As Double 343 | 344 | With s 345 | aC(1, 1) = .Left: aC(1, 2) = .Top 346 | aC(2, 1) = .Left + .Width: aC(2, 2) = .Top 347 | aC(3, 1) = .Left: aC(3, 2) = .Top + .Height 348 | aC(4, 1) = .Left + .Width: aC(4, 2) = .Top + .Height 349 | 350 | bHflip = .HorizontalFlip 351 | bVflip = .VerticalFlip 352 | End With 353 | 354 | If bHflip = bVflip Then 355 | If bVflip = False Then 356 | ' down to right -- South-East 357 | nBegin = 1: nEnd = 4 358 | Else 359 | ' up to left -- North-West 360 | nBegin = 4: nEnd = 1 361 | End If 362 | ElseIf bHflip = False Then 363 | ' up to right -- North-East 364 | nBegin = 3: nEnd = 2 365 | Else 366 | ' down to left -- South-West 367 | nBegin = 2: nEnd = 3 368 | End If 369 | xs = aC(nBegin, 1) 370 | ys = aC(nBegin, 2) 371 | xe = aC(nEnd, 1) 372 | ye = aC(nEnd, 2) 373 | 374 | ' Get unit vector in orthogonal direction 375 | xd = xe - xs 376 | yd = ye - ys 377 | 378 | s_length = Sqr(xd * xd + yd * yd) 379 | If s_length > 0 Then 380 | n_x = -yd / s_length 381 | n_y = xd / s_length 382 | Else 383 | n_x = 0 384 | n_y = 0 385 | End If 386 | 387 | x1 = xs + n_x * t / 2 388 | y1 = ys + n_y * t / 2 389 | x2 = xe + n_x * t / 2 390 | y2 = ye + n_y * t / 2 391 | x3 = xe - n_x * t / 2 392 | y3 = ye - n_y * t / 2 393 | x4 = xs - n_x * t / 2 394 | y4 = ys - n_y * t / 2 395 | 396 | 'End If 397 | 398 | 399 | If ApplyTransform Then 400 | Dim builder As FreeformBuilder 401 | Set builder = ActiveWindow.Selection.SlideRange(1).Shapes.BuildFreeform(msoEditingCorner, x1, y1) 402 | builder.AddNodes msoSegmentLine, msoEditingAuto, x2, y2 403 | builder.AddNodes msoSegmentLine, msoEditingAuto, x3, y3 404 | builder.AddNodes msoSegmentLine, msoEditingAuto, x4, y4 405 | builder.AddNodes msoSegmentLine, msoEditingAuto, x1, y1 406 | Dim oSh As Shape 407 | Set oSh = builder.ConvertToShape 408 | oSh.Fill.ForeColor = s.Line.ForeColor 409 | oSh.Fill.Visible = msoTrue 410 | oSh.Line.Visible = msoFalse 411 | oSh.Rotation = s.Rotation 412 | Set LineToFreeform = oSh 413 | Else 414 | Set LineToFreeform = s 415 | End If 416 | End Function 417 | 418 | ' Add picture as shape taking care of not inserting it in empty placeholder 419 | Private Function AddDisplayShape(path As String, PosX As Single, PosY As Single) As Shape 420 | ' from http://www.vbaexpress.com/forum/showthread.php?47687-Addpicture-adds-the-picture-to-a-placeholder-rather-as-a-new-shape 421 | ' modified based on http://www.vbaexpress.com/forum/showthread.php?37561-Delete-empty-placeholders 422 | Dim oshp As Shape 423 | Dim osld As Slide 424 | On Error Resume Next 425 | Set osld = ActiveWindow.Selection.SlideRange(1) 426 | If Err <> 0 Then Exit Function 427 | On Error GoTo 0 428 | For Each oshp In osld.Shapes 429 | If oshp.Type = msoPlaceholder Then 430 | If oshp.PlaceholderFormat.ContainedType = msoAutoShape Then 431 | If oshp.HasTextFrame Then 432 | If Not oshp.TextFrame.HasText Then oshp.TextFrame.TextRange = "DUMMY" 433 | End If 434 | End If 435 | End If 436 | Next oshp 437 | Set AddDisplayShape = osld.Shapes.AddPicture(path, msoFalse, msoTrue, PosX, PosY, -1, -1) 438 | For Each oshp In osld.Shapes 439 | If oshp.Type = msoPlaceholder Then 440 | If oshp.PlaceholderFormat.ContainedType = msoAutoShape Then 441 | If oshp.HasTextFrame Then 442 | If oshp.TextFrame.TextRange = "DUMMY" Then oshp.TextFrame.DeleteText 443 | End If 444 | End If 445 | End If 446 | Next oshp 447 | End Function 448 | 449 | 450 | -------------------------------------------------------------------------------- /Macros.bas: -------------------------------------------------------------------------------- 1 | Attribute VB_Name = "Macros" 2 | 'Written: August 02, 2010 3 | 'Author: Leith Ross 4 | 'Summary: Makes the UserForm resizable by dragging one of the sides. Place a call 5 | ' to the macro MakeFormResizable in the UserForm's Activate event. 6 | 'Source: http://www.mrexcel.com/forum/excel-questions/485489-resize-userform.html 7 | 8 | 9 | Public RegenerateContinue As Boolean 10 | 11 | Private Const LOGPIXELSX = 88 'Pixels/inch in X 12 | 13 | 'A point is defined as 1/72 inches 14 | Private Const POINTS_PER_INCH As Long = 72 15 | 16 | Public Sub MakeFormResizable() 17 | ' TODO implement this 18 | End Sub 19 | 20 | Sub NewLatexEquation() 21 | Attribute NewLatexEquation.VB_Description = "Macro created 24.5.2007 by Zvika Ben-Haim" 22 | Load LatexForm 23 | 24 | If IsEmpty(LatexForm.textboxSize.Text) Then 25 | LatexForm.textboxSize.Text = "20" 26 | End If 27 | LatexForm.CheckBoxReset.Visible = False 28 | LatexForm.Label2.Caption = "Set size:" 29 | 30 | LatexForm.ButtonRun.Caption = "Generate" 31 | LatexForm.ButtonRun.Accelerator = "G" 32 | LatexForm.textboxSize.Enabled = True 33 | LatexForm.Show 34 | End Sub 35 | 36 | Sub NewLatexEquationMatchSize(ByVal size) 37 | Load LatexForm 38 | 39 | LatexForm.textboxSize.Text = size 40 | 41 | LatexForm.CheckBoxReset.Visible = False 42 | LatexForm.Label2.Caption = "Set size:" 43 | 44 | LatexForm.ButtonRun.Caption = "Generate" 45 | LatexForm.ButtonRun.Accelerator = "G" 46 | LatexForm.textboxSize.Enabled = True 47 | LatexForm.Show 48 | End Sub 49 | 50 | Sub EditLatexEquation() 51 | ' Check if the user currently has a single Latex equation selected. 52 | ' If so, display the dialog box. If not, dislpay an error message. 53 | ' Called when the user clicks the "Edit Latex Equation" menu item. 54 | 55 | If Not TryEditLatexEquation() Then 56 | MsgBox "You must select a single IguanaTex++ equation to modify it." 57 | End If 58 | End Sub 59 | 60 | Function TryEditLatexEquation() As Boolean 61 | ' Analyze the type of selected object to determine if it can be edited 62 | Dim Sel As Selection 63 | Set Sel = Application.ActiveWindow.Selection 64 | Dim oldshape As Shape 65 | Dim LatexText As String 66 | Dim SourceParts() As String 67 | Dim TeXSource As String 68 | 69 | 70 | If Sel.Type = ppSelectionShapes Then 71 | ' First make sure we don't have any shapes with duplicate names on this slide 72 | Call DeDuplicateShapeNamesInSlide(ActiveWindow.View.Slide.SlideIndex) 73 | If Sel.ShapeRange.count = 1 Then ' if not 1, then multiple objects are selected 74 | ' Group case: either 1 object within a group, or 1 group corresponding to an EMF display 75 | If Sel.ShapeRange.Type = msoGroup Then 76 | If Sel.HasChildShapeRange = False Then ' Maybe an EMF display 77 | Set oldshape = Sel.ShapeRange(1) 78 | TryEditLatexEquation = TryProcessShape(oldshape) 79 | Exit Function 80 | ElseIf Sel.ChildShapeRange.count = 1 Then 81 | ' 1 object inside a group 82 | Set oldshape = Sel.ChildShapeRange(1) 83 | TryEditLatexEquation = TryProcessShape(oldshape) 84 | Exit Function 85 | End If 86 | ' Non-group case: only a single object can be selected 87 | Else 88 | Set oldshape = Sel.ShapeRange(1) 89 | If oldshape.Tags.Item("EMFchild") <> "" Then 90 | TryEditLatexEquation = False ' we should not have an EMF child object by itself 91 | Else 92 | TryEditLatexEquation = TryProcessShape(oldshape) 93 | End If 94 | Exit Function 95 | End If 96 | End If 97 | End If 98 | 99 | TryEditLatexEquation = False 100 | End Function 101 | 102 | Function TryProcessShape(oldshape As Shape) As Boolean 103 | Dim LatexText As String 104 | Dim SourceParts() As String 105 | Dim TeXSource As String 106 | 107 | TryProcessShape = False 108 | With oldshape.Tags 109 | If .Item("LATEXADDIN") <> "" Then ' we're dealing with an IguanaTex display 110 | For j = 1 To .count 111 | Debug.Print .name(j) & vbTab & .Value(j) 112 | Next j 113 | Load LatexForm 114 | 115 | Call LatexForm.RetrieveOldShapeInfo(oldshape, .Item("LATEXADDIN")) 116 | 117 | LatexForm.Show 118 | TryProcessShape = True 119 | Exit Function 120 | ElseIf .Item("SOURCE") <> "" Then ' we're dealing with a Texpoint display 121 | For j = 1 To .count 122 | Debug.Print .name(j) & vbTab & .Value(j) 123 | Next j 124 | ScalingFactor = 1 125 | IsTemplate = False 126 | If .Item("ORIGWIDTH") <> "" Then 127 | ScalingFactor = ScalingFactor * oldshape.Width / val(.Item("ORIGWIDTH")) 128 | End If 129 | If .Item("TEXPOINT") = "template" Then 130 | IsTemplate = True 131 | End If 132 | oldshape.Tags.Add "TEXPOINTSCALING", ScalingFactor 133 | 134 | Load LatexForm 135 | 136 | If IsTemplate = True Then 137 | SourceParts = Split(.Item("SOURCE"), vbTab, , vbTextCompare) 138 | If UBound(SourceParts) > 2 Then 139 | TeXSource = SourceParts(3) 140 | Else 141 | SourceParts = Split(.Item("SOURCE"), "equation", , vbTextCompare) 142 | SourceParts = Split(SourceParts(1), "template TP", , vbTextCompare) 143 | TeXSource = SourceParts(0) 144 | End If 145 | LatexText = DEFAULT_LATEX_CODE 146 | oldshape.Tags.Add "IGUANATEXCURSOR", Len(LatexText) - 16 147 | Else 148 | LatexText = .Item("SOURCE") 149 | End If 150 | Call LatexForm.RetrieveOldShapeInfo(oldshape, LatexText) 151 | LatexForm.Show 152 | TryProcessShape = True 153 | Exit Function 154 | End If 155 | End With 156 | End Function 157 | 158 | 159 | ' Make sure there aren't multiple shapes with the same name prior to processing 160 | Sub DeDuplicateShapeNamesInSlide(SlideIndex As Integer) 161 | Dim vSh As Shape 162 | Dim vSl As Slide 163 | Set vSl = ActivePresentation.Slides(SlideIndex) 164 | 165 | Dim NameList() As String 166 | 167 | Dim dict As New Dictionary 168 | For Each vSh In vSl.Shapes 169 | If vSh.Type = msoGroup Then 170 | NameList = CollectGroupedItemList(vSh, True) 171 | Else 172 | ReDim NameList(0 To 0) As String 173 | NameList(0) = vSh.name 174 | End If 175 | For n = LBound(NameList) To UBound(NameList) 176 | Key = NameList(n) 177 | If Not dict.Exists(Key) Then 178 | dict.Item(Key) = 1 179 | Else 180 | dict.Item(Key) = dict.Item(Key) + 1 181 | End If 182 | Next n 183 | Next vSh 184 | 185 | For Each vSh In vSl.Shapes 186 | Set dict = RenameDuplicateShapes(vSh, dict) 187 | Next vSh 188 | 189 | 190 | Set dict = Nothing 191 | End Sub 192 | 193 | Private Function RenameDuplicateShapes(vSh As Shape, dict As Dictionary) As Dictionary 194 | If vSh.Type = msoGroup Then 195 | Dim n As Long 196 | For n = 1 To vSh.GroupItems.count 197 | Set dict = RenameDuplicateShapes(vSh.GroupItems(n), dict) 198 | Next 199 | Else 200 | K = vSh.name 201 | If dict.Item(K) > 1 Then 202 | shpCount = 1 203 | Do While dict.Exists(K & " " & shpCount) 204 | shpCount = shpCount + 1 205 | Loop 206 | vSh.name = K & " " & shpCount 207 | dict.Add K & " " & shpCount, 1 208 | End If 209 | End If 210 | Set RenameDuplicateShapes = dict 211 | End Function 212 | 213 | 214 | Public Sub RegenerateSelectedDisplays() 215 | Dim Sel As Selection 216 | Set Sel = Application.ActiveWindow.Selection 217 | Dim vSh As Shape 218 | Dim vSl As Slide 219 | Dim SlideIndex As Integer 220 | 221 | RegenerateContinue = True 222 | 223 | Select Case Sel.Type 224 | Case ppSelectionShapes 225 | SlideIndex = ActiveWindow.View.Slide.SlideIndex 226 | Call DeDuplicateShapeNamesInSlide(SlideIndex) 227 | DisplayCount = CountDisplaysInSelection(Sel) 228 | If DisplayCount > 0 Then 229 | RegenerateForm.LabelSlideNumber.Caption = 1 230 | RegenerateForm.LabelTotalSlideNumber.Caption = 1 231 | RegenerateForm.LabelShapeNumber.Caption = 0 232 | RegenerateForm.LabelTotalShapeNumberOnSlide.Caption = DisplayCount 233 | RegenerateForm.Show False 234 | If Sel.HasChildShapeRange Then ' displays within a group 235 | For Each vSh In Sel.ChildShapeRange 236 | Call RegenerateOneDisplay(vSh) 237 | Next vSh 238 | Else 239 | For Each vSh In Sel.ShapeRange 240 | If vSh.Type = msoGroup And Not IsShapeDisplay(vSh) Then ' grouped displays 241 | Call RegenerateGroupedDisplays(vSh, SlideIndex) 242 | Else ' single display 243 | Call RegenerateOneDisplay(vSh) 244 | End If 245 | Next vSh 246 | End If 247 | Else 248 | MsgBox "No displays to be regenerated." 249 | End If 250 | Case ppSelectionSlides 251 | RegenerateForm.LabelSlideNumber.Caption = 0 252 | RegenerateForm.LabelTotalSlideNumber.Caption = Sel.SlideRange.count 253 | RegenerateForm.LabelShapeNumber.Caption = 0 254 | RegenerateForm.LabelTotalShapeNumberOnSlide.Caption = 0 255 | RegenerateForm.Show False 256 | For Each vSl In Sel.SlideRange 257 | RegenerateForm.LabelSlideNumber.Caption = RegenerateForm.LabelSlideNumber.Caption + 1 258 | DisplayCount = CountDisplaysInSlide(vSl) 259 | RegenerateForm.LabelTotalShapeNumberOnSlide.Caption = DisplayCount 260 | DoEvents 261 | If DisplayCount > 0 Then 262 | Call RegenerateDisplaysOnSlide(vSl) 263 | End If 264 | Next vSl 265 | Case Else 266 | MsgBox "You need to select a set of shapes or slides." 267 | End Select 268 | 269 | With RegenerateForm 270 | .Hide 271 | .LabelShapeNumber.Caption = 0 272 | .LabelSlideNumber.Caption = 0 273 | .LabelTotalSlideNumber.Caption = 0 274 | .LabelTotalShapeNumberOnSlide.Caption = 0 275 | End With 276 | Unload RegenerateForm 277 | End Sub 278 | 279 | Sub RegenerateDisplaysOnSlide(vSl As Slide) 280 | vSl.Select 281 | Call DeDuplicateShapeNamesInSlide(vSl.SlideIndex) 282 | Dim vSh As Shape 283 | For Each vSh In vSl.Shapes 284 | If vSh.Type = msoGroup And Not IsShapeDisplay(vSh) Then 285 | Call RegenerateGroupedDisplays(vSh, vSl.SlideIndex) 286 | Else 287 | Call RegenerateOneDisplay(vSh) 288 | End If 289 | Next vSh 290 | End Sub 291 | 292 | Sub RegenerateGroupedDisplays(vGroupSh As Shape, SlideIndex As Integer) 293 | Dim n As Long 294 | Dim vSh As Shape 295 | 296 | Dim ItemToRegenerateList() As String 297 | 298 | ItemToRegenerateList = CollectGroupedItemList(vGroupSh, False) 299 | 300 | For n = LBound(ItemToRegenerateList) To UBound(ItemToRegenerateList) 301 | Set vSh = ActivePresentation.Slides(SlideIndex).Shapes(ItemToRegenerateList(n)) 302 | Call RegenerateOneDisplay(vSh) 303 | Next 304 | 305 | End Sub 306 | 307 | Private Function CollectGroupedItemList(vSh As Shape, AllDisplays As Boolean) As Variant 308 | Dim n As Long 309 | Dim i As Long 310 | Dim prev_length As Long 311 | Dim added_length As Long 312 | Dim TmpList() As String 313 | Dim SubList() As String 314 | prev_length = -1 315 | For n = 1 To vSh.GroupItems.count 316 | ' If n = 1 Then 317 | ' prev_length = -1 318 | ' Else 319 | ' prev_length = UBound(TmpList) 320 | ' End If 321 | If vSh.GroupItems(n).Type = msoGroup Then ' this case should never occur, as PPT disregards subgroups. Consider removing. 322 | SubList = CollectGroupedItemList(vSh.GroupItems(n), AllDisplays) 323 | added_length = UBound(SubList) 324 | ReDim Preserve TmpList(0 To prev_length + added_length) As String 325 | For j = prev_length + 1 To UBound(TmpList) 326 | TmpList(j) = SubList(j - prev_length - 1) 327 | Next j 328 | Else 329 | If AllDisplays Or IsShapeDisplay(vSh.GroupItems(n)) Then 330 | ReDim Preserve TmpList(0 To prev_length + 1) As String 331 | TmpList(UBound(TmpList)) = vSh.GroupItems(n).name 332 | End If 333 | End If 334 | prev_length = UBound(TmpList) 335 | Next 336 | CollectGroupedItemList = TmpList 337 | End Function 338 | 339 | Sub RegenerateOneDisplay(vSh As Shape) 340 | If RegenerateContinue Then 341 | vSh.Select 342 | With vSh.Tags 343 | If .Item("LATEXADDIN") <> "" Then ' we're dealing with an IguanaTex display 344 | RegenerateForm.LabelShapeNumber.Caption = RegenerateForm.LabelShapeNumber.Caption + 1 345 | DoEvents 346 | Load LatexForm 347 | 348 | Call LatexForm.RetrieveOldShapeInfo(vSh, .Item("LATEXADDIN")) 349 | 350 | Apply_BatchEditSettings 351 | 352 | Call LatexForm.ButtonRun_Click 353 | Exit Sub 354 | ElseIf .Item("SOURCE") <> "" Then ' we're dealing with a Texpoint display 355 | RegenerateForm.LabelShapeNumber.Caption = RegenerateForm.LabelShapeNumber.Caption + 1 356 | DoEvents 357 | IsTemplate = False 358 | If .Item("ORIGWIDTH") <> "" Then 359 | vSh.Tags.Add "TEXPOINTSCALING", vSh.Width / val(.Item("ORIGWIDTH")) 360 | End If 361 | If .Item("TEXPOINT") = "template" Then 362 | IsTemplate = True 363 | End If 364 | Load LatexForm 365 | 366 | Dim LatexText As String 367 | If IsTemplate = True Then 368 | Dim TeXSource As String 369 | Dim SourceParts() As String 370 | SourceParts = Split(.Item("SOURCE"), vbTab, , vbTextCompare) 371 | If UBound(SourceParts) > 2 Then 372 | TeXSource = SourceParts(3) 373 | Else 374 | SourceParts = Split(.Item("SOURCE"), "equation", , vbTextCompare) 375 | SourceParts = Split(SourceParts(1), "template TP", , vbTextCompare) 376 | TeXSource = SourceParts(0) 377 | End If 378 | LatexText = DEFAULT_LATEX_CODE 379 | vSh.Tags.Add "IGUANATEXCURSOR", Len(LatexText) - 16 380 | Else 381 | LatexText = .Item("SOURCE") 382 | End If 383 | Call LatexForm.RetrieveOldShapeInfo(vSh, LatexText) 384 | 385 | Apply_BatchEditSettings 386 | 387 | Call LatexForm.ButtonRun_Click 388 | Exit Sub 389 | End If 390 | End With 391 | Else 392 | Debug.Print "Pressed Cancel" 393 | End If 394 | End Sub 395 | 396 | Sub Apply_BatchEditSettings() 397 | If BatchEditForm.CheckBoxModifyEngine.Value Then 398 | LatexForm.ComboBoxLaTexEngine.ListIndex = BatchEditForm.ComboBoxLaTexEngine.ListIndex 399 | End If 400 | If BatchEditForm.CheckBoxModifyTempFolder.Value Then 401 | LatexForm.TextBoxTempFolder.Text = BatchEditForm.TextBoxTempFolder.Text 402 | End If 403 | If BatchEditForm.CheckBoxModifyBitmapVector.Value Then 404 | LatexForm.ComboBoxBitmapVector.ListIndex = BatchEditForm.ComboBoxBitmapVector.ListIndex 405 | End If 406 | If BatchEditForm.CheckBoxModifyLocalDPI.Value Then 407 | LatexForm.TextBoxLocalDPI.Text = BatchEditForm.TextBoxLocalDPI.Text 408 | End If 409 | If BatchEditForm.CheckBoxModifySize.Value Then 410 | LatexForm.CheckBoxReset.Value = True 411 | LatexForm.textboxSize.Text = BatchEditForm.textboxSize.Text 412 | End If 413 | If BatchEditForm.CheckBoxForcePreserveSize.Value Then 414 | LatexForm.CheckBoxForcePreserveSize.Value = True 415 | End If 416 | If BatchEditForm.CheckBoxModifyTransparency.Value Then 417 | LatexForm.checkboxTransp.Value = BatchEditForm.checkboxTransp.Value 418 | End If 419 | If BatchEditForm.CheckBoxModifyResetFormat.Value Then 420 | LatexForm.CheckBoxResetFormat.Value = BatchEditForm.CheckBoxResetFormat.Value 421 | End If 422 | If BatchEditForm.CheckBoxReplace.Value Then 423 | If BatchEditForm.TextBoxFind.Text <> "" Then 424 | LatexForm.TextWindow1.Text = Replace(LatexForm.TextWindow1.Text, BatchEditForm.TextBoxFind.Text, BatchEditForm.TextBoxReplacement.Text) 425 | End If 426 | End If 427 | End Sub 428 | 429 | Function IsShapeDisplay(vSh As Shape) As Boolean 430 | IsShapeDisplay = False 431 | With vSh.Tags 432 | If .Item("LATEXADDIN") <> "" Then ' we're dealing with an IguanaTex display 433 | IsShapeDisplay = True 434 | ElseIf .Item("SOURCE") <> "" Then ' we're dealing with a Texpoint display 435 | IsShapeDisplay = True 436 | End If 437 | End With 438 | End Function 439 | 440 | Function CountDisplaysInShape(vSh As Shape) As Integer 441 | DisplayCount = 0 442 | If vSh.Type = msoGroup Then ' grouped displays 443 | Dim s As Shape 444 | For Each s In vSh.GroupItems 445 | DisplayCount = DisplayCount + CountDisplaysInShape(s) 446 | Next 447 | Else ' single display 448 | If IsShapeDisplay(vSh) Then 449 | DisplayCount = 1 450 | End If 451 | End If 452 | CountDisplaysInShape = DisplayCount 453 | End Function 454 | 455 | Function CountDisplaysInSelection(Sel As Selection) As Integer 456 | Dim vSh As Shape 457 | 458 | DisplayCount = 0 459 | If Sel.HasChildShapeRange Then ' displays within a group 460 | For Each vSh In Sel.ChildShapeRange 461 | DisplayCount = DisplayCount + CountDisplaysInShape(vSh) 462 | Next vSh 463 | Else 464 | For Each vSh In Sel.ShapeRange 465 | DisplayCount = DisplayCount + CountDisplaysInShape(vSh) 466 | Next vSh 467 | End If 468 | CountDisplaysInSelection = DisplayCount 469 | End Function 470 | 471 | Function CountDisplaysInSlide(vSl As Slide) As Integer 472 | Dim vSh As Shape 473 | DisplayCount = 0 474 | For Each vSh In vSl.Shapes 475 | DisplayCount = DisplayCount + CountDisplaysInShape(vSh) 476 | Next vSh 477 | CountDisplaysInSlide = DisplayCount 478 | End Function 479 | 480 | Sub Auto_Open() 481 | ' Runs when the add-in is loaded 482 | LatexForm.InitializeApp 483 | Load LatexForm 484 | Unload LatexForm 485 | End Sub 486 | 487 | Sub Auto_Close() 488 | LatexForm.UnInitializeApp 489 | End Sub 490 | 491 | Sub LoadSetTempForm() 492 | Load SetTempForm 493 | SetTempForm.Show 494 | End Sub 495 | 496 | Public Sub RibbonNewLatexEquation(ByVal control) 497 | Dim Sel As Selection 498 | Set Sel = Application.ActiveWindow.Selection 499 | If (Sel.Type = ppSelectionText) Then 500 | NewLatexEquationMatchSize Sel.TextRange.Font.size 501 | Else 502 | NewLatexEquation 503 | End If 504 | End Sub 505 | 506 | Public Sub RibbonEditLatexEquation(ByVal control) 507 | EditLatexEquation 508 | End Sub 509 | 510 | Public Sub RibbonSetTempFolder(ByVal control) 511 | LoadSetTempForm 512 | End Sub 513 | 514 | Public Sub RibbonRegenerateSelectedDisplays(ByVal control) 515 | Load BatchEditForm 516 | BatchEditForm.Show 517 | End Sub 518 | 519 | Public Sub RibbonConvertToEMF(ByVal control) 520 | Load BatchEditForm 521 | BatchEditForm.CheckBoxModifyBitmapVector.Value = True 522 | BatchEditForm.ComboBoxBitmapVector.Enabled = True 523 | BatchEditForm.ComboBoxBitmapVector.ListIndex = 1 524 | BatchEditForm.CheckBoxModifyPreserveSize.Value = True 525 | BatchEditForm.CheckBoxForcePreserveSize.Enabled = True 526 | BatchEditForm.CheckBoxForcePreserveSize.Value = True 527 | Call BatchEditForm.ButtonRun_Click 528 | End Sub 529 | 530 | Public Sub RibbonConvertToPNG(ByVal control) 531 | Load BatchEditForm 532 | BatchEditForm.CheckBoxModifyBitmapVector.Value = True 533 | BatchEditForm.ComboBoxBitmapVector.Enabled = True 534 | BatchEditForm.ComboBoxBitmapVector.ListIndex = 0 535 | BatchEditForm.CheckBoxModifyPreserveSize.Value = True 536 | BatchEditForm.CheckBoxForcePreserveSize.Enabled = True 537 | BatchEditForm.CheckBoxForcePreserveSize.Value = True 538 | Call BatchEditForm.ButtonRun_Click 539 | End Sub 540 | 541 | 542 | ' Same Subs, but to be called from add-in menu in older versions of PowerPoint 543 | Public Sub RegenerateSelectedDisplaysNoChange() 544 | Load BatchEditForm 545 | BatchEditForm.Show 546 | End Sub 547 | 548 | Public Sub ConvertToEMF() 549 | Load BatchEditForm 550 | BatchEditForm.CheckBoxModifyBitmapVector.Value = True 551 | BatchEditForm.ComboBoxBitmapVector.Enabled = True 552 | BatchEditForm.ComboBoxBitmapVector.ListIndex = 1 553 | BatchEditForm.CheckBoxModifyPreserveSize.Value = True 554 | BatchEditForm.CheckBoxForcePreserveSize.Enabled = True 555 | BatchEditForm.CheckBoxForcePreserveSize.Value = True 556 | Call BatchEditForm.ButtonRun_Click 557 | End Sub 558 | 559 | Public Sub ConvertToPNG() 560 | Load BatchEditForm 561 | BatchEditForm.CheckBoxModifyBitmapVector.Value = True 562 | BatchEditForm.ComboBoxBitmapVector.Enabled = True 563 | BatchEditForm.ComboBoxBitmapVector.ListIndex = 0 564 | BatchEditForm.CheckBoxModifyPreserveSize.Value = True 565 | BatchEditForm.CheckBoxForcePreserveSize.Enabled = True 566 | BatchEditForm.CheckBoxForcePreserveSize.Value = True 567 | Call BatchEditForm.ButtonRun_Click 568 | End Sub 569 | 570 | Public Sub RibbonInsertVectorGraphicsFile() 571 | Load LoadVectorGraphicsForm 572 | Call LoadVectorGraphicsForm.ButtonPath_Click 573 | LoadVectorGraphicsForm.Show 574 | End Sub 575 | 576 | 577 | Public Function GetFilePrefix() As String 578 | GetFilePrefix = "IguanaTex_tmp" 579 | End Function 580 | 581 | Public Function GetTempPath() As String 582 | Dim res As String 583 | RegPath = "Software\IguanaTex" 584 | res = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "Temp Dir", "") 585 | If res = "" Then 586 | res = MacTempPath() 587 | End If 588 | If Right(res, 1) <> PathSeperator Then 589 | res = res & PathSeperator 590 | End If 591 | GetTempPath = res 592 | End Function 593 | 594 | 595 | Public Function GetEditorPath() As String 596 | Dim res As String 597 | RegPath = "Software\IguanaTex" 598 | res = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "Editor", DEFAULT_EDITOR) 599 | GetEditorPath = res 600 | End Function 601 | 602 | -------------------------------------------------------------------------------- /LatexForm.frm: -------------------------------------------------------------------------------- 1 | VERSION 5.00 2 | Begin {C62A69F0-16DC-11CE-9E98-00AA00574A4F} LatexForm 3 | Caption = "IguanaTex" 4 | ClientHeight = 5880 5 | ClientLeft = 20 6 | ClientTop = 320 7 | ClientWidth = 7560 8 | OleObjectBlob = "LatexForm.frx":0000 9 | StartUpPosition = 1 'CenterOwner 10 | End 11 | Attribute VB_Name = "LatexForm" 12 | Attribute VB_GlobalNameSpace = False 13 | Attribute VB_Creatable = False 14 | Attribute VB_PredeclaredId = True 15 | Attribute VB_Exposed = False 16 | Dim RegPath As String 17 | 18 | Dim LaTexEngineList As Variant 19 | Dim LaTexEngineDisplayList As Variant 20 | Dim UsePDFList As Variant 21 | 22 | 'Dim NumberOfTemplates As Long 23 | Dim TemplateSortedListString As String 24 | Dim TemplateSortedList() As String 25 | Dim TemplateNameSortedListString As String 26 | 27 | Dim FormHeightWidthSet As Boolean 28 | 29 | Dim theAppEventHandler As New AppEventHandler 30 | 31 | Public TextWindow1 As New TextWindow 32 | Public TextWindowTemplateCode As New TextWindow 33 | 34 | Sub InitializeApp() 35 | Set theAppEventHandler.App = Application 36 | 37 | AddMenuItem "New Latex display...", "NewLatexEquation", 18 '226 38 | AddMenuItem "Edit Latex display...", "EditLatexEquation", 37 39 | AddMenuItem "Regenerate selection...", "RegenerateSelectedDisplaysNoChange", 19 40 | AddMenuItem "Vectorize selection...", "ConvertToEMF", 153 41 | AddMenuItem "Rasterize selection...", "ConvertToPNG", 931 42 | AddMenuItem "Settings...", "LoadSetTempForm", 548 43 | AddMenuItem "Insert vector file...", "RibbonInsertVectorGraphicsFile", 23 44 | 45 | End Sub 46 | 47 | Sub AddMenuItem(itemText As String, itemCommand As String, itemFaceId As Long) 48 | ' Check if we have already added the menu item 49 | Dim initialized As Boolean 50 | Dim bef As Integer 51 | initialized = False 52 | bef = 1 53 | Dim Menu As CommandBars 54 | Set Menu = Application.CommandBars 55 | For i = 1 To Menu("Insert").Controls.count 56 | With Menu("Insert").Controls(i) 57 | If .Caption = itemText Then 58 | initialized = True 59 | Exit For 60 | ElseIf InStr(.Caption, "Dia&gram") Then 61 | bef = i 62 | End If 63 | End With 64 | Next 65 | 66 | ' Create the menu choice. 67 | If Not initialized Then 68 | Dim NewControl As CommandBarControl 69 | Set NewControl = Menu("Insert").Controls.Add _ 70 | (Type:=msoControlButton, _ 71 | before:=bef, _ 72 | Id:=itemFaceId) 73 | NewControl.Caption = itemText 74 | NewControl.OnAction = itemCommand 75 | NewControl.Style = msoButton 76 | End If 77 | End Sub 78 | 79 | Sub UnInitializeApp() 80 | 81 | RemoveMenuItem "New Latex display..." 82 | RemoveMenuItem "Edit Latex display..." 83 | RemoveMenuItem "Regenerate selection..." 84 | RemoveMenuItem "Vectorize selection..." 85 | RemoveMenuItem "Rasterize selection..." 86 | RemoveMenuItem "Settings..." 87 | RemoveMenuItem "Insert vector file..." 88 | ' Clean up older versions 89 | RemoveMenuItem "Regenerate selected displays..." 90 | RemoveMenuItem "Convert to EMF..." 91 | RemoveMenuItem "Convert to PNG..." 92 | 93 | 94 | End Sub 95 | 96 | Sub RemoveMenuItem(itemText As String) 97 | Dim Menu As CommandBars 98 | Set Menu = Application.CommandBars 99 | For i = 1 To Menu("Insert").Controls.count 100 | If Menu("Insert").Controls(i).Caption = itemText Then 101 | Menu("Insert").Controls(i).Delete 102 | Exit For 103 | End If 104 | Next 105 | 106 | 107 | End Sub 108 | 109 | 110 | Private Sub ButtonCancel_Click() 111 | Unload LatexForm 112 | ' LatexForm.Hide 113 | End Sub 114 | 115 | 116 | Private Function IsPathWritable(TempPath As String) As Boolean 117 | FilePrefix = GetFilePrefix() 118 | 119 | Dim FName As String 120 | Dim FHdl As Integer 121 | FName = TempPath & FilePrefix & ".tmp" 122 | On Error GoTo TempFolderNotWritable 123 | FHdl = FreeFile() 124 | Open FName For Output Access Write As FHdl 125 | Print #FHdl, "TESTWRITE" 126 | Close FHdl 127 | IsPathWritable = True 128 | Kill FName 129 | 130 | On Error GoTo 0 131 | 132 | Exit Function 133 | 134 | TempFolderNotWritable: 135 | IsPathWritable = False 136 | End Function 137 | 138 | Private Sub WriteLaTeX2File(TempPath As String, FilePrefix As String) 139 | Const ForReading = 1, ForWriting = 2, ForAppending = 3 140 | Set fs = New FileSystemObject 141 | If fs.FileExists(TempPath & FilePrefix & ".png") Then 142 | fs.FindDelete TempPath, FilePrefix + "*.*" 'Make sure we don't keep old files 143 | End If 144 | 145 | ' always use utf-8 146 | 147 | Dim fnum As Integer 148 | 149 | ' clear file content 150 | fnum = FreeFile() 151 | Open TempPath + FilePrefix + ".tex" For Output Access Write As fnum 152 | Close #fnum 153 | 154 | ' write data 155 | Dim data() As Byte 156 | data = TextWindow1.Utf8 157 | 158 | fnum = FreeFile() 159 | Open TempPath + FilePrefix + ".tex" For Binary Access Write As fnum 160 | Put #fnum, , data 161 | Close #fnum 162 | 163 | Set fs = Nothing 164 | End Sub 165 | 166 | Sub ButtonRun_Click() 167 | Dim TempPath As String 168 | 'TempPath = GetTempPath() 169 | If Right(TextBoxTempFolder.Text, 1) <> PathSeperator Then 170 | TextBoxTempFolder.Text = TextBoxTempFolder.Text & PathSeperator 171 | End If 172 | TempPath = TextBoxTempFolder.Text 173 | 174 | If Left(TempPath, 1) = "." Then 175 | Dim sPath As String 176 | sPath = ActivePresentation.path 177 | If Len(sPath) > 0 Then 178 | If Right(sPath, 1) <> PathSeperator Then 179 | sPath = sPath & PathSeperator 180 | End If 181 | TempPath = sPath & TempPath 182 | Else 183 | MsgBox "You need to have saved your presentation once to use a relative path." 184 | Exit Sub 185 | End If 186 | End If 187 | 188 | Dim FilePrefix As String 189 | FilePrefix = GetFilePrefix() 190 | 191 | Dim debugMode As Boolean 192 | debugMode = checkboxDebug.Value 193 | 194 | ' Read settings 195 | RegPath = "Software\IguanaTex" 196 | LATEXENGINEID = ComboBoxLaTexEngine.ListIndex 197 | tex2pdf_command = LaTexEngineList(LATEXENGINEID) 198 | Dim TeXExePath As String 199 | TeXExePath = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "TeXExePath", DEFAULT_TEX_EXE_PATH) 200 | TeXExeExt = "" 201 | Dim UsePDF As Boolean 202 | UsePDF = UsePDFList(LATEXENGINEID) 203 | 204 | Dim UseEMF As Boolean 205 | BitmapVector = ComboBoxBitmapVector.ListIndex 206 | If BitmapVector = 0 Then 207 | UseEMF = False 208 | Else 209 | UseEMF = True 210 | End If 211 | 'UseEMF = CheckBoxEMF.Value 212 | Dim OutputType As String 213 | 214 | Dim TimeOutTimeString As String 215 | Dim TimeOutTime As Long 216 | TimeOutTimeString = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "TimeOutTime", "20") ' Wait 20 seconds for the processes to complete 217 | TimeOutTime = val(TimeOutTimeString) * 1000 218 | 219 | Dim OutputDpiString As String 220 | OutputDpiString = TextBoxLocalDPI.Text 221 | Dim OutputDpi As Long 222 | OutputDpi = val(OutputDpiString) 223 | 224 | ' Read current dpi in: this will be used when rescaling 225 | dpi = 96 'lDotsPerInch ' I'm not convinced that this is the right thing to do, so for now I stop trying to take dpi into account 226 | default_screen_dpi = 96 227 | Dim VectorScalingX As Single, VectorScalingY As Single, BitmapScalingX As Single, BitmapScalingY As Single 228 | VectorScalingX = dpi / default_screen_dpi * val(GetRegistryValue(HKEY_CURRENT_USER, RegPath, "VectorScalingX", "1")) 229 | VectorScalingY = dpi / default_screen_dpi * val(GetRegistryValue(HKEY_CURRENT_USER, RegPath, "VectorScalingY", "1")) 230 | BitmapScalingX = val(GetRegistryValue(HKEY_CURRENT_USER, RegPath, "BitmapScalingX", "1")) 231 | BitmapScalingY = val(GetRegistryValue(HKEY_CURRENT_USER, RegPath, "BitmapScalingY", "1")) 232 | 233 | ' Test if path writable 234 | If Not IsPathWritable(TempPath) Then 235 | MsgBox "The temporary folder " & TempPath & " appears not to be writable." 236 | Exit Sub 237 | End If 238 | 239 | 240 | ' Write latex to a temp file 241 | Call WriteLaTeX2File(TempPath, FilePrefix) 242 | 243 | 244 | ' Run latex 245 | Const ForReading = 1, ForWriting = 2, ForAppending = 3 246 | Set fs = New FileSystemObject 247 | Dim LogFile As Object 248 | FrameProcess.Visible = True 249 | 250 | Dim gs_command As String 251 | Dim tex2img_command As String 252 | Dim IMConv As String 253 | 254 | If UseEMF = True Then ' Use TeX2img to generate an EMF file 255 | gs_command = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "GS Command", DEFAULT_GS_COMMAND) 256 | tex2img_command = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "TeX2img Command", DEFAULT_TEX2IMG_COMMAND) 257 | LabelProcess.Caption = "LaTeX to EMF..." 258 | FrameProcess.Repaint 259 | RetVal& = Execute(ShellEscape(tex2img_command) & " --latex " & tex2pdf_command & " --gs " & ShellEscape(gs_command) & " --no-preview " & ShellEscape(FilePrefix & ".tex") & " " & ShellEscape(FilePrefix & ".emf"), TempPath, debugMode, TimeOutTime) 260 | If (RetVal& <> 0 Or Not fs.FileExists(TempPath & FilePrefix & ".emf")) Then 261 | ' Error in Latex code 262 | ' Read log file and show it to the user 263 | If fs.FileExists(TempPath & FilePrefix & ".log") Then 264 | LogFileViewer.TextBox1.Text = ReadAll(TempPath + FilePrefix + ".log") 265 | LogFileViewer.TextBox1.ScrollBars = fmScrollBarsBoth 266 | LogFileViewer.Show 1 267 | Else 268 | MsgBox "TeX2img did not return in " & TimeOutTimeString & " seconds and may have hung." _ 269 | & vbNewLine & "You should have run TeX2img once outside IguanaTex to make sure its path are set correctly." _ 270 | & vbNewLine & "Please make sure your code compiles outside IguanaTex." 271 | End If 272 | FrameProcess.Visible = False 273 | Exit Sub 274 | End If 275 | FinalFilename = FilePrefix & ".emf" 276 | OutputType = "EMF" 277 | Else 278 | If UsePDF = True Then ' pdf to png route 279 | gs_command = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "GS Command", DEFAULT_GS_COMMAND) 280 | IMConv = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "IMconv", DEFAULT_IM_CONV) 281 | 282 | If tex2pdf_command = "platex" Then 283 | OutputExt = ".dvi" 284 | LabelProcess.Caption = "LaTeX to DVI..." 285 | Else 286 | OutputExt = ".pdf" 287 | LabelProcess.Caption = "LaTeX to PDF..." 288 | End If 289 | FrameProcess.Repaint 290 | 291 | RetVal& = Execute(ShellEscape(TeXExePath & tex2pdf_command & TeXExeExt) & " -shell-escape -interaction=batchmode " & ShellEscape(FilePrefix + ".tex"), TempPath, debugMode, TimeOutTime) 292 | 293 | If (RetVal& <> 0 Or Not fs.FileExists(TempPath & FilePrefix & OutputExt)) Then 294 | ' Error in Latex code 295 | ' Read log file and show it to the user 296 | If fs.FileExists(TempPath & FilePrefix & ".log") Then 297 | LogFileViewer.TextBox1.Text = ReadAll(TempPath + FilePrefix + ".log") 298 | LogFileViewer.TextBox1.ScrollBars = fmScrollBarsBoth 299 | LogFileViewer.Show 1 300 | Else 301 | MsgBox tex2pdf_command & " did not return in " & TimeOutTimeString & " seconds and may have hung." _ 302 | & vbNewLine & "Please make sure your code compiles outside IguanaTex." _ 303 | & vbNewLine & "You may also try generating in Debug mode, as it will let you know if any font/package is missing" 304 | End If 305 | FrameProcess.Visible = False 306 | Exit Sub 307 | End If 308 | 309 | If tex2pdf_command = "platex" Then 310 | LabelProcess.Caption = "DVI to PDF..." 311 | FrameProcess.Repaint 312 | ' platex actually outputs a DVI file, which we need to convert to PDF (we could go the EPS route, but this blends easier with IguanaTex's existing code) 313 | RetValConv& = Execute(ShellEscape(TeXExePath & "dvipdfmx" & TeXExeExt) & " -o " & ShellEscape(FilePrefix & ".pdf") & " " & ShellEscape(FilePrefix & ".dvi"), TempPath, debugMode, TimeOutTime) 314 | If (RetValConv& <> 0 Or Not fs.FileExists(TempPath & FilePrefix & ".pdf")) Then 315 | ' Error in DVI to PDF conversion 316 | MsgBox "Error while using dvipdm to convert from DVI to PDF." 317 | FrameProcess.Visible = False 318 | Exit Sub 319 | End If 320 | End If 321 | 322 | LabelProcess.Caption = "PDF to PNG..." 323 | FrameProcess.Repaint 324 | ' Output Bounding Box to file and read back in the appropriate information 325 | RetValConv& = Execute(ShellEscape(gs_command) & " -q -dBATCH -dNOPAUSE -sDEVICE=bbox " & ShellEscape(FilePrefix & ".pdf") & " 2> " & ShellEscape(FilePrefix & ".bbx"), TempPath, debugMode, TimeOutTime) 326 | 327 | If (RetValConv& <> 0 Or Not fs.FileExists(TempPath & FilePrefix & ".bbx")) Then 328 | ' Error in bounding box computation 329 | MsgBox "Error while using Ghostscript to compute the bounding box. Is your path correct?" 330 | FrameProcess.Visible = False 331 | Exit Sub 332 | End If 333 | Dim BBString As String 334 | BBString = BoundingBoxString(TempPath + FilePrefix + ".bbx") 335 | 336 | ' Convert PDF to PNG 337 | If checkboxTransp.Value = True Then 338 | PdfPngDevice = "-sDEVICE=pngalpha" 339 | Else 340 | PdfPngDevice = "-sDEVICE=png16m" 341 | End If 342 | RetValConv& = Execute(ShellEscape(gs_command) & " -q -dBATCH -dNOPAUSE " & PdfPngDevice & " -r" & OutputDpiString & " -sOutputFile=" & ShellEscape(FilePrefix & "_tmp.png") & BBString & " -f " & ShellEscape(TempPath & FilePrefix & ".pdf"), TempPath, debugMode, TimeOutTime) 343 | If (RetValConv& <> 0 Or Not fs.FileExists(TempPath & FilePrefix & "_tmp.png")) Then 344 | ' Error in PDF to PNG conversion 345 | MsgBox "Error while using Ghostscript to convert from PDF to PNG. Is your path correct?" 346 | FrameProcess.Visible = False 347 | Exit Sub 348 | End If 349 | ' Unfortunately, the resulting file has a metadata DPI of OutputDpi (=1200), not the default screen one (usually 96), 350 | ' so there is a discrepancy with the dvipng output, which is always 96 (independent of the screen, actually). 351 | ' The only workaround I have found so far is to use Imagemagick's convert to change the DPI (but not the pixel size!) 352 | ' Execute """" & IMconv & """ -units PixelsPerInch """ & FilePrefix & "_tmp.png"" -density " & CStr(dpi) & " """ & FilePrefix & ".png""", TempPath, debugMode 353 | RetValConv& = Execute(ShellEscape(IMConv) & " -units PixelsPerInch " & ShellEscape(FilePrefix & "_tmp.png") & " -density " & CStr(default_screen_dpi) & " " & ShellEscape(FilePrefix & ".png"), TempPath, debugMode, TimeOutTime) 354 | If (RetValConv& <> 0 Or Not fs.FileExists(TempPath & FilePrefix & ".png")) Then 355 | ' Error in PDF to PNG conversion 356 | MsgBox "Error while using ImageMagick to change the PNG DPI. Is your path correct?" _ 357 | & vbNewLine & "The full path is needed to avoid conflict with Windows's built-in convert.exe." 358 | FrameProcess.Visible = False 359 | Exit Sub 360 | End If 361 | 362 | ' 'I considered using ImageMagick's convert, but it's extremely slow, and uses ghostscript in the backend anyway 363 | 'PdfPngSwitches = "-density 1200 -trim -transparent white -antialias +repage" 364 | 'Execute IMconv & " " & PdfPngSwitches & " """ & FilePrefix & ".pdf"" """ & FilePrefix & ".png""", TempPath, debugMode 365 | 366 | Else 367 | ' dvi to png route 368 | LabelProcess.Caption = "LaTeX to DVI..." 369 | FrameProcess.Repaint 370 | RetVal& = Execute(ShellEscape(TeXExePath & "pdflatex" & TeXExeExt) & " -shell-escape -output-format dvi -interaction=batchmode " & ShellEscape(FilePrefix & ".tex"), TempPath, debugMode, TimeOutTime) 371 | 372 | If (RetVal& <> 0 Or Not fs.FileExists(TempPath & FilePrefix & ".dvi")) Then 373 | ' Error in Latex code 374 | ' Read log file and show it to the user 375 | If fs.FileExists(TempPath & FilePrefix & ".log") Then 376 | LogFileViewer.TextBox1.Text = ReadAll(TempPath + FilePrefix + ".log") 377 | LogFileViewer.TextBox1.ScrollBars = fmScrollBarsBoth 378 | LogFileViewer.Show 1 379 | Else 380 | MsgBox "latex did not return in " & TimeOutTimeString & " seconds and may have hung." _ 381 | & vbNewLine & "Please make sure your code compiles outside IguanaTex." _ 382 | & vbNewLine & "You may also try generating in Debug mode, as it will let you know if any font/package is missing." 383 | End If 384 | FrameProcess.Visible = False 385 | Exit Sub 386 | End If 387 | LabelProcess.Caption = "DVI to PNG..." 388 | FrameProcess.Repaint 389 | DviPngSwitches = "-q -D " & OutputDpiString & " -T tight" ' monitor is 96 dpi or higher; we use OutputDpi (=1200 by default) dpi to get a crisper display, and rescale later on for new displays to match the point size 390 | If checkboxTransp.Value = True Then 391 | DviPngSwitches = DviPngSwitches & " -bg Transparent" 392 | End If 393 | ' If the user created a .png by using the standalone class with convert, we use that, else we use dvipng 394 | If Not fs.FileExists(TempPath & FilePrefix & ".png") Then 395 | RetValConv& = Execute(ShellEscape(TeXExePath & "dvipng" & TeXExeExt) & " " & DviPngSwitches & " -o " & ShellEscape(FilePrefix & ".png") & " " & ShellEscape(FilePrefix & ".dvi"), TempPath, debugMode, TimeOutTime) 396 | If (RetValConv& <> 0 Or Not fs.FileExists(TempPath & FilePrefix & ".png")) Then 397 | MsgBox "dvipng failed, or did not return in " & TimeOutTimeString & " seconds and may have hung." _ 398 | & vbNewLine & "You may want to try compiling using the PDF->PNG option." _ 399 | & vbNewLine & "You may also try generating in Debug mode, as it will let you know if any font is missing." 400 | FrameProcess.Visible = False 401 | Exit Sub 402 | End If 403 | End If 404 | End If 405 | OutputType = "PNG" 406 | FinalFilename = FilePrefix & ".png" 407 | End If 408 | ' Latex run successful. 409 | 410 | 411 | ' Now we prepare the insertion of the image 412 | LabelProcess.Caption = "Insert image..." 413 | FrameProcess.Repaint 414 | 415 | ' If we are in Edit mode, store parameters of old image 416 | Dim PosX As Single 417 | Dim PosY As Single 418 | Dim oldHeight As Single 419 | Dim oldWidth As Single 420 | Dim Sel As Selection 421 | Set Sel = Application.ActiveWindow.Selection 422 | Dim oldshape As Shape 423 | Dim oldshapeIsEMF As Boolean 424 | Dim s As Shape 425 | IsInGroup = False 426 | If ButtonRun.Caption = "ReGenerate" Then 427 | If Sel.ShapeRange.Type = msoGroup And Sel.HasChildShapeRange Then 428 | ' Old image is part of a group 429 | Set oldshape = Sel.ChildShapeRange(1) 430 | IsInGroup = True 431 | Dim arr() As Variant ' gather all shapes to be regrouped later on 432 | j = 0 433 | For Each s In Sel.ShapeRange.GroupItems 434 | If s.name <> oldshape.name Then 435 | j = j + 1 436 | ReDim Preserve arr(1 To j) 437 | arr(j) = s.name 438 | End If 439 | Next 440 | 441 | ' Store the group's animation and Zorder info in a dummy object tmpGroup 442 | Dim oldGroup As Shape 443 | Set oldGroup = Sel.ShapeRange(1) 444 | Dim tmpGroup As Shape 445 | Set tmpGroup = ActiveWindow.Selection.SlideRange.Shapes.AddShape(msoShapeDiamond, 1, 1, 1, 1) 446 | MoveAnimation oldGroup, tmpGroup 447 | MatchZOrder oldGroup, tmpGroup 448 | 449 | ' Tag all elements in the group with their hierarchy level and their name or group name 450 | Dim MaxGroupLevel As Long 451 | MaxGroupLevel = TagGroupHierarchy(arr, oldshape.name) 452 | 453 | Else 454 | Set oldshape = Sel.ShapeRange(1) 455 | End If 456 | PosX = oldshape.Left 457 | PosY = oldshape.Top 458 | oldHeight = oldshape.Height 459 | oldWidth = oldshape.Width 460 | oldshapeIsEMF = False 461 | If oldshape.Tags.Item("BitmapVector") <> "" Then 462 | If oldshape.Tags.Item("BitmapVector") = 1 Then 463 | oldshapeIsEMF = True 464 | End If 465 | End If 466 | Else 467 | PosX = 200 468 | PosY = 200 469 | If Sel.Type = ppSelectionShapes Then ' if something is selected on a slide, use its position for the new display 470 | 'If Sel.ShapeRange.Type = msoGroup And Sel.HasChildShapeRange Then 471 | ' Set oldshape = Sel.ChildShapeRange(1) 472 | 'Else 473 | ' Set oldshape = Sel.ShapeRange(1) 474 | 'End If 475 | PosX = Sel.ShapeRange(1).Left 476 | PosY = Sel.ShapeRange(1).Top 477 | End If 478 | End If 479 | 480 | ' Get scaling factors 481 | Dim isTexpoint As Boolean 482 | Dim tScaleWidth As Single, tScaleHeight As Single 483 | MagicScalingFactorEMF = 1 ' 1 / 100 ' Magical scaling factor for EMF 484 | MagicScalingFactorPNG = default_screen_dpi / OutputDpi 485 | If UseEMF Then 486 | MagicScalingFactor = MagicScalingFactorEMF 487 | Else 488 | MagicScalingFactor = MagicScalingFactorPNG 489 | End If 490 | 491 | If ButtonRun.Caption <> "ReGenerate" Or CheckBoxReset.Value Then 492 | PointSize = val(textboxSize.Text) 493 | tScaleWidth = PointSize / 10 * MagicScalingFactor ' 1/10 is for the default LaTeX point size (10 pt) 494 | tScaleHeight = tScaleWidth 495 | Else 496 | ' Handle the case of Texpoint displays 497 | isTexpoint = False 498 | Dim OldDpi As Long 499 | OldDpi = OutputDpi 500 | With oldshape.Tags 501 | If .Item("TEXPOINTSCALING") <> "" Then 502 | isTexpoint = True 503 | tScaleWidth = val(.Item("TEXPOINTSCALING")) * MagicScalingFactor 504 | tScaleHeight = tScaleWidth 505 | End If 506 | If .Item("OUTPUTDPI") <> "" Then 507 | OldDpi = val(.Item("OUTPUTDPI")) 508 | End If 509 | End With 510 | If Not isTexpoint Then ' modifying a normal display, either PNG or EMF 511 | HeightOld = oldshape.Height 512 | WidthOld = oldshape.Width 513 | tScaleHeight = 1 514 | tScaleWidth = 1 515 | If oldshapeIsEMF = False Then ' this deals with displays from very old versions of IguanaTex that lack proper size tags 516 | oldshape.ScaleHeight 1#, msoTrue 517 | oldshape.ScaleWidth 1#, msoTrue 518 | tScaleHeight = HeightOld / oldshape.Height * 960 / OutputDpi ' 0.8=960/1200 is there to preserve scaling of displays created with old versions of IguanaTex 519 | tScaleWidth = WidthOld / oldshape.Width * 960 / OutputDpi 520 | End If 521 | With oldshape.Tags 522 | If .Item("ORIGINALHEIGHT") <> "" Then 523 | tmpHeight = val(.Item("ORIGINALHEIGHT")) 524 | tScaleHeight = HeightOld / tmpHeight * OldDpi / OutputDpi 525 | End If 526 | If .Item("ORIGINALWIDTH") <> "" Then 527 | tmpWidth = val(.Item("ORIGINALWIDTH")) 528 | tScaleWidth = WidthOld / tmpWidth * OldDpi / OutputDpi 529 | End If 530 | End With 531 | If UseEMF = True And oldshapeIsEMF = False Then 532 | tScaleHeight = tScaleHeight * MagicScalingFactorEMF / MagicScalingFactorPNG 533 | tScaleWidth = tScaleWidth * MagicScalingFactorEMF / MagicScalingFactorPNG 534 | ElseIf UseEMF = False And oldshapeIsEMF = True Then 535 | tScaleHeight = tScaleHeight / MagicScalingFactorEMF * MagicScalingFactorPNG 536 | tScaleWidth = tScaleWidth / MagicScalingFactorEMF * MagicScalingFactorPNG 537 | End If 538 | End If 539 | End If 540 | 541 | 542 | ' Insert image and rescale it 543 | Dim newShape As Shape 544 | Set newShape = AddDisplayShape(TempPath + FinalFilename, PosX, PosY) 545 | 546 | If UseEMF Then 547 | ' Rescale the EMF picture before converting into PPT object 548 | Set newShape = ConvertEMF(newShape, VectorScalingX * tScaleWidth, VectorScalingY * tScaleHeight) 549 | ' Tag shape and its components with their "original" sizes, 550 | ' which we get by dividing their current height/width by the scaling factors applied above 551 | newShape.Tags.Add "ORIGINALHEIGHT", newShape.Height / tScaleHeight 552 | newShape.Tags.Add "ORIGINALWIDTH", newShape.Width / tScaleWidth 553 | If newShape.Type = msoGroup Then 554 | For Each s In newShape.GroupItems 555 | s.Tags.Add "ORIGINALHEIGHT", s.Height / tScaleHeight 556 | s.Tags.Add "ORIGINALWIDTH", s.Width / tScaleWidth 557 | Next 558 | End If 559 | 560 | Else 561 | ' Resize to the true size of the png file and adjust using the manual scaling factors set in Main Settings 562 | With newShape 563 | .ScaleHeight 1#, msoTrue 564 | .ScaleWidth 1#, msoTrue 565 | .LockAspectRatio = msoFalse 566 | .ScaleHeight BitmapScalingY, msoFalse 567 | .ScaleWidth BitmapScalingX, msoFalse 568 | .Tags.Add "OUTPUTDPI", OutputDpi ' Stores this display's resolution 569 | ' Add tags storing the original height and width, used next time to keep resizing ratio. 570 | .Tags.Add "ORIGINALHEIGHT", newShape.Height 571 | .Tags.Add "ORIGINALWIDTH", newShape.Width 572 | ' Apply scaling factors 573 | .ScaleHeight tScaleHeight, msoFalse 574 | .ScaleWidth tScaleWidth, msoFalse 575 | .LockAspectRatio = msoTrue 576 | End With 577 | End If 578 | 579 | If CheckBoxForcePreserveSize.Value Then 580 | ' We are forcing the new shape to have the same size as the old shape 581 | ' This is useful when converting between Bitmap and Vector 582 | With newShape 583 | .LockAspectRatio = msoFalse 584 | .Height = oldHeight 585 | .Width = oldWidth 586 | .LockAspectRatio = msoTrue 587 | End With 588 | End If 589 | 590 | If ButtonRun.Caption = "ReGenerate" Then ' We are editing+resetting size of an old display, we keep rotation 591 | newShape.Rotation = oldshape.Rotation 592 | If Not CheckBoxReset.Value Then 593 | newShape.LockAspectRatio = oldshape.LockAspectRatio ' Unlock aspect ratio if old display had it unlocked 594 | End If 595 | End If 596 | 597 | ' Add tags 598 | Call AddTagsToShape(newShape) 599 | If UseEMF = True And newShape.Type = msoGroup Then 600 | Set s = newShape.GroupItems(1) 601 | Call AddTagsToShape(s) 'only left most for now, to make things simple 602 | For Each s In newShape.GroupItems 603 | ' Call AddTagsToShape(s) 604 | s.Tags.Add "EMFchild", True 605 | Next 606 | End If 607 | 608 | ' Copy animation settings and formatting from old image, then delete it 609 | If ButtonRun.Caption = "ReGenerate" Then 610 | Dim TransferDesign As Boolean 611 | TransferDesign = True 612 | If UseEMF <> oldshapeIsEMF Or CheckBoxResetFormat.Value Then 613 | TransferDesign = False 614 | End If 615 | If IsInGroup Then 616 | ' Transfer format to new shape 617 | MatchZOrder oldshape, newShape 618 | If TransferDesign Then 619 | oldshape.PickUp 620 | newShape.Apply 621 | End If 622 | ' Handle the case of shape within EMF group. 623 | Dim DeleteLowestLayer As Boolean 624 | DeleteLowestLayer = False 625 | If oldshape.Tags.Item("EMFchild") <> "" Then 626 | DeleteLowestLayer = True 627 | End If 628 | oldshape.Delete 629 | 630 | Dim newGroup As Shape 631 | ' Get current slide, it will be used to group ranges 632 | Dim sld As Slide 633 | Dim SlideIndex As Long 634 | SlideIndex = ActiveWindow.View.Slide.SlideIndex 635 | Set sld = ActivePresentation.Slides(SlideIndex) 636 | 637 | ' Group all non-modified elements from old group, plus modified element 638 | j = j + 1 639 | ReDim Preserve arr(1 To j) 640 | arr(j) = newShape.name 641 | If DeleteLowestLayer Then 642 | Dim arr_remain() As Variant 643 | j_remain = 0 644 | For Each n In arr 645 | Set s = ActiveWindow.Selection.SlideRange.Shapes(n) 646 | ThisShapeLevel = 0 647 | For i_tag = 1 To s.Tags.count 648 | If (s.Tags.name(i_tag) = "LAYER") Then 649 | ThisShapeLevel = val(s.Tags.Value(i_tag)) 650 | End If 651 | Next 652 | If ThisShapeLevel = 1 Then 653 | s.Delete 654 | Else 655 | j_remain = j_remain + 1 656 | ReDim Preserve arr_remain(1 To j_remain) 657 | arr_remain(j_remain) = s.name 658 | End If 659 | Next 660 | newShape.Tags.Add "LAYER", 2 661 | arr = arr_remain 662 | Else 663 | newShape.Tags.Add "LAYER", 1 664 | End If 665 | newShape.Tags.Add "SELECTIONNAME", newShape.name 666 | 667 | ' Hierarchically re-group elements 668 | For Level = 1 To MaxGroupLevel 669 | Dim CurrentLevelArr() As Variant 670 | j_current = 0 671 | For Each n In arr 672 | ThisShapeLevel = 0 673 | Dim ThisShapeSelectionName As String 674 | ThisShapeSelectionName = "" 675 | On Error Resume Next 676 | With ActiveWindow.Selection.SlideRange.Shapes(n).Tags 677 | For i_tag = 1 To .count 678 | If (.name(i_tag) = "LAYER") Then 679 | ThisShapeLevel = val(.Value(i_tag)) 680 | End If 681 | If (.name(i_tag) = "SELECTIONNAME") Then 682 | ThisShapeSelectionName = .Value(i_tag) 683 | End If 684 | Next 685 | End With 686 | 687 | 688 | If ThisShapeLevel = Level Then 689 | If j_current > 0 Then 690 | If Not IsInArray(CurrentLevelArr, ThisShapeSelectionName) Then 691 | j_current = j_current + 1 692 | ReDim Preserve CurrentLevelArr(1 To j_current) 693 | CurrentLevelArr(j_current) = ThisShapeSelectionName 694 | End If 695 | Else 696 | j_current = j_current + 1 697 | ReDim Preserve CurrentLevelArr(1 To j_current) 698 | CurrentLevelArr(j_current) = ThisShapeSelectionName 699 | End If 700 | End If 701 | Next 702 | 703 | If j_current > 1 Then 704 | Set newGroup = sld.Shapes.Range(CurrentLevelArr).Group 705 | j = j + 1 706 | ReDim Preserve arr(1 To j) 707 | arr(j) = newGroup.name 708 | newGroup.Tags.Add "SELECTIONNAME", newGroup.name 709 | newGroup.Tags.Add "LAYER", Level + 1 710 | End If 711 | 712 | Next 713 | 714 | ' Delete the tags to avoid conflict with future runs 715 | For Each n In arr 716 | On Error Resume Next 717 | ActiveWindow.Selection.SlideRange.Shapes(n).Tags.Delete ("SELECTIONNAME") 718 | ActiveWindow.Selection.SlideRange.Shapes(n).Tags.Delete ("LAYER") 719 | Next 720 | 721 | ' Use temporary group to retrieve the group's original animation and Zorder 722 | MoveAnimation tmpGroup, newGroup 723 | MatchZOrder tmpGroup, newGroup 724 | tmpGroup.Delete 725 | Else 726 | MoveAnimation oldshape, newShape 727 | MatchZOrder oldshape, newShape 728 | If TransferDesign Then 729 | If oldshapeIsEMF And oldshape.Type = msoGroup Then 730 | 731 | ' First transfer group format to temporary shape 732 | ' (we use a duplicate of the old EMF shape) 733 | Dim tmpGroupEMF As Shape 734 | Set tmpGroupEMF = oldshape.Duplicate(1) 735 | 'TransferGroupFormat oldshape, tmpGroupEMF 736 | 737 | ' Transfer shape formatting 738 | ' First need to delete all but one shape in the group to unlock the format pickup 739 | Dim tmpshp As Shape 740 | Set tmpshp = oldshape.GroupItems(1) 741 | For j = oldshape.GroupItems.count To 2 Step -1 742 | ' Delete backwards because Powerpoint renumbers 743 | ' We could also always delete .GroupItems(2) ... 744 | oldshape.GroupItems(j).Delete 745 | Next 746 | tmpshp.PickUp 747 | 748 | ' Transfer shape formatting to each shape within the group 749 | For Each s In newShape.GroupItems 750 | s.Apply 751 | Next 752 | tmpshp.Delete 753 | 754 | ' Now we can transfer the group formatting from the temporary shape 755 | TransferGroupFormat tmpGroupEMF, newShape 756 | tmpGroupEMF.Delete 757 | Else 758 | oldshape.PickUp 759 | newShape.Apply 760 | oldshape.Delete 761 | End If 762 | Else 763 | oldshape.Delete 764 | End If 765 | End If 766 | End If 767 | 768 | 769 | ' Select the new shape 770 | newShape.Select 771 | 772 | 773 | ' Delete temp files if not in debug mode 774 | If debugMode = False Then fs.FindDelete TempPath, FilePrefix + "*.*" 775 | 776 | 777 | 778 | FrameProcess.Visible = False 779 | Unload LatexForm 780 | Exit Sub 781 | 782 | End Sub 783 | 784 | Private Sub AddTagsToShape(vSh As Shape) 785 | With vSh.Tags 786 | .Add "LATEXADDIN", TextWindow1.Text 787 | .Add "IguanaTexSize", val(textboxSize.Text) 788 | .Add "IGUANATEXCURSOR", TextWindow1.SelStart 789 | .Add "TRANSPARENCY", checkboxTransp.Value 790 | .Add "FILENAME", TextBoxFile.Text 791 | .Add "LATEXENGINEID", ComboBoxLaTexEngine.ListIndex 792 | .Add "TEMPFOLDER", TextBoxTempFolder.Text 793 | .Add "LATEXFORMHEIGHT", LatexForm.Height 794 | .Add "LATEXFORMWIDTH", LatexForm.Width 795 | .Add "LATEXFORMWRAP", TextBox1.WordWrap 796 | .Add "BitmapVector", ComboBoxBitmapVector.ListIndex 797 | End With 798 | End Sub 799 | 800 | 801 | 802 | Private Function ConvertEMF(inSh As Shape, ScalingX As Single, ScalingY As Single, _ 803 | Optional FileType As String = "emf", Optional ConvertLines As Boolean = True) As Shape 804 | With inSh 805 | .ScaleHeight 1#, msoTrue 806 | .ScaleWidth 1#, msoTrue 807 | .LockAspectRatio = msoFalse 808 | .ScaleHeight ScalingY, msoTrue 809 | .ScaleWidth ScalingX, msoTrue 810 | .LockAspectRatio = msoTrue 811 | End With 812 | 813 | Dim newShape As Shape 814 | ' Get current slide, it will be used to group ranges 815 | Dim sld As Slide 816 | Dim SlideIndex As Long 817 | SlideIndex = ActiveWindow.View.Slide.SlideIndex 818 | Set sld = ActivePresentation.Slides(SlideIndex) 819 | 820 | ' Convert EMF image to object 821 | Dim Shr As ShapeRange 822 | Set Shr = inSh.Ungroup 823 | If FileType = "emf" Then 824 | Set Shr = Shr.Ungroup 825 | ' Clean up 826 | Shr.Item(1).Delete 827 | Shr.Item(2).Delete 828 | If Shr(3).GroupItems.count > 2 Then 829 | Set newShape = Shr(3) 830 | Else ' only a single freeform, so not a group 831 | Set newShape = Shr(3).GroupItems(2) 832 | End If 833 | Shr(3).GroupItems(1).Delete 834 | ElseIf FileType = "eps" Then 835 | Shr.GroupItems(1).Delete 836 | Shr.GroupItems(1).Delete 837 | Set newShape = Shr.Ungroup.Group 838 | End If 839 | 840 | 841 | If newShape.Type = msoGroup Then 842 | 843 | Dim arr_group() As Variant 844 | arr_group = GetAllShapesInGroup(newShape) 845 | Call FullyUngroupShape(newShape) 846 | Set newShape = sld.Shapes.Range(arr_group).Group 847 | 848 | Dim emf_arr() As Variant ' gather all shapes to be regrouped later on 849 | j_emf = 0 850 | Dim delete_arr() As Variant ' gather all shapes to be deleted later on 851 | j_delete = 0 852 | Dim s As Shape 853 | For Each s In newShape.GroupItems 854 | j_emf = j_emf + 1 855 | ReDim Preserve emf_arr(1 To j_emf) 856 | If s.Type = msoLine Then 857 | If ConvertLines And (s.Height > 0 Or s.Width > 0) Then 858 | emf_arr(j_emf) = LineToFreeform(s).name 859 | j_delete = j_delete + 1 860 | ReDim Preserve delete_arr(1 To j_delete) 861 | delete_arr(j_delete) = s.name 862 | Else 863 | emf_arr(j_emf) = s.name 864 | End If 865 | Else 866 | emf_arr(j_emf) = s.name 867 | If s.Fill.Visible = msoTrue Then 868 | s.Line.Visible = msoFalse 869 | Else 870 | s.Line.Visible = msoTrue 871 | 872 | End If 873 | End If 874 | Next 875 | newShape.Ungroup 876 | If j_delete > 0 Then 877 | sld.Shapes.Range(delete_arr).Delete 878 | End If 879 | Set newShape = sld.Shapes.Range(emf_arr).Group 880 | 881 | Else 882 | If newShape.Type = msoLine Then 883 | newShapeName = LineToFreeform(newShape).name 884 | newShape.Delete 885 | Set newShape = sld.Shapes(newShapeName) 886 | Else 887 | newShape.Line.Visible = msoFalse 888 | End If 889 | End If 890 | newShape.LockAspectRatio = msoTrue 891 | Set ConvertEMF = newShape 892 | End Function 893 | 894 | Private Sub FullyUngroupShape(newShape As Shape) 895 | Dim Shr As ShapeRange 896 | Dim s As Shape 897 | If newShape.Type = msoGroup Then 898 | Set Shr = newShape.Ungroup 899 | For i = 1 To Shr.count 900 | Set s = Shr.Item(i) 901 | If s.Type = msoGroup Then 902 | Call FullyUngroupShape(s) 903 | End If 904 | Next 905 | End If 906 | End Sub 907 | 908 | Private Function GetAllShapesInGroup(newShape As Shape) As Variant 909 | Dim arr() As Variant 910 | Dim j As Long 911 | Dim s As Shape 912 | For Each s In newShape.GroupItems 913 | j = j + 1 914 | ReDim Preserve arr(1 To j) 915 | arr(j) = s.name 916 | Next 917 | GetAllShapesInGroup = arr 918 | End Function 919 | 920 | Private Function LineToFreeform(s As Shape) As Shape 921 | t = s.Line.Weight 922 | Dim ApplyTransform As Boolean 923 | ApplyTransform = True 924 | 925 | Dim bHflip As Boolean 926 | Dim bVflip As Boolean 927 | Dim nBegin As Long 928 | Dim nEnd As Long 929 | Dim aC(1 To 4, 1 To 2) As Double 930 | 931 | With s 932 | aC(1, 1) = .Left: aC(1, 2) = .Top 933 | aC(2, 1) = .Left + .Width: aC(2, 2) = .Top 934 | aC(3, 1) = .Left: aC(3, 2) = .Top + .Height 935 | aC(4, 1) = .Left + .Width: aC(4, 2) = .Top + .Height 936 | 937 | bHflip = .HorizontalFlip 938 | bVflip = .VerticalFlip 939 | End With 940 | 941 | If bHflip = bVflip Then 942 | If bVflip = False Then 943 | ' down to right -- South-East 944 | nBegin = 1: nEnd = 4 945 | Else 946 | ' up to left -- North-West 947 | nBegin = 4: nEnd = 1 948 | End If 949 | ElseIf bHflip = False Then 950 | ' up to right -- North-East 951 | nBegin = 3: nEnd = 2 952 | Else 953 | ' down to left -- South-West 954 | nBegin = 2: nEnd = 3 955 | End If 956 | xs = aC(nBegin, 1) 957 | ys = aC(nBegin, 2) 958 | xe = aC(nEnd, 1) 959 | ye = aC(nEnd, 2) 960 | 961 | ' Get unit vector in orthogonal direction 962 | xd = xe - xs 963 | yd = ye - ys 964 | 965 | s_length = Sqr(xd * xd + yd * yd) 966 | If s_length > 0 Then 967 | n_x = -yd / s_length 968 | n_y = xd / s_length 969 | Else 970 | n_x = 0 971 | n_y = 0 972 | End If 973 | 974 | x1 = xs + n_x * t / 2 975 | y1 = ys + n_y * t / 2 976 | x2 = xe + n_x * t / 2 977 | y2 = ye + n_y * t / 2 978 | x3 = xe - n_x * t / 2 979 | y3 = ye - n_y * t / 2 980 | x4 = xs - n_x * t / 2 981 | y4 = ys - n_y * t / 2 982 | 983 | 'End If 984 | 985 | 986 | If ApplyTransform Then 987 | Dim builder As FreeformBuilder 988 | Set builder = ActiveWindow.Selection.SlideRange(1).Shapes.BuildFreeform(msoEditingCorner, x1, y1) 989 | builder.AddNodes msoSegmentLine, msoEditingAuto, x2, y2 990 | builder.AddNodes msoSegmentLine, msoEditingAuto, x3, y3 991 | builder.AddNodes msoSegmentLine, msoEditingAuto, x4, y4 992 | builder.AddNodes msoSegmentLine, msoEditingAuto, x1, y1 993 | Dim oSh As Shape 994 | Set oSh = builder.ConvertToShape 995 | oSh.Fill.ForeColor = s.Line.ForeColor 996 | oSh.Fill.Visible = msoTrue 997 | oSh.Line.Visible = msoFalse 998 | oSh.Rotation = s.Rotation 999 | Set LineToFreeform = oSh 1000 | Else 1001 | Set LineToFreeform = s 1002 | End If 1003 | End Function 1004 | 1005 | Private Function IsInArray(arr As Variant, valueToCheck As String) As Boolean 1006 | IsInArray = False 1007 | For Each n In arr 1008 | If n = valueToCheck Then 1009 | IsInArray = True 1010 | Exit For 1011 | End If 1012 | Next 1013 | 1014 | End Function 1015 | 1016 | Private Function TagGroupHierarchy(arr As Variant, TargetName As String) As Long 1017 | ' Arr is the list of names of (leaf) elements in this group 1018 | ' TargetName is the display which is being modified. We're going down the branch containing it. 1019 | Dim Sel As Selection 1020 | ActiveWindow.Selection.SlideRange.Shapes(TargetName).Select 1021 | Set Sel = Application.ActiveWindow.Selection 1022 | 1023 | ' This function expects to receive a grouped ShapeRange 1024 | ' We ungroup to reveal the structure at the layer below 1025 | Sel.ShapeRange.Ungroup 1026 | ActiveWindow.Selection.SlideRange.Shapes(TargetName).Select 1027 | 1028 | If Sel.ShapeRange.Type = msoGroup Then 1029 | ' We need to go further down, the element being edited is still within a group 1030 | ' Get the name of the Target group in which it is 1031 | TargetGroupName = Sel.ShapeRange(1).name 1032 | 1033 | Dim Arr_In() As Variant ' shapes in the same group 1034 | Dim Arr_Out() As Variant ' shapes not in the same group 1035 | 1036 | ' Split range according to whether elements are in the same group or not 1037 | j_in = 0 1038 | j_out = 0 1039 | For Each n In arr 1040 | ActiveWindow.Selection.SlideRange.Shapes(n).Select 1041 | If Sel.ShapeRange.Type = msoGroup Then 1042 | ' object is in group 1043 | If Sel.ShapeRange(1).name = TargetGroupName Then 1044 | j_in = j_in + 1 1045 | ReDim Preserve Arr_In(1 To j_in) 1046 | Arr_In(j_in) = n 1047 | Else 1048 | j_out = j_out + 1 1049 | ReDim Preserve Arr_Out(1 To j_out) 1050 | Arr_Out(j_out) = n 1051 | End If 1052 | Else ' object not in group, so it can't be in the same group as Target 1053 | j_out = j_out + 1 1054 | ReDim Preserve Arr_Out(1 To j_out) 1055 | Arr_Out(j_out) = n 1056 | End If 1057 | Next 1058 | 1059 | ' Build shape range with all elements in that group, go one level down 1060 | Tmp = TagGroupHierarchy(Arr_In, TargetName) 1061 | TagGroupHierarchy = Tmp + 1 1062 | 1063 | ' For all elements not in that group, tag them 1064 | For Each n In Arr_Out 1065 | ActiveWindow.Selection.SlideRange.Shapes(n).Select 1066 | ActiveWindow.Selection.SlideRange.Shapes(n).Tags.Add "LAYER", TagGroupHierarchy 1067 | If Sel.ShapeRange.Type = msoGroup Then 1068 | ActiveWindow.Selection.SlideRange.Shapes(n).Tags.Add "SELECTIONNAME", Sel.ShapeRange(1).name 1069 | Else 1070 | ActiveWindow.Selection.SlideRange.Shapes(n).Tags.Add "SELECTIONNAME", n 1071 | End If 1072 | Next 1073 | 1074 | Else ' we reached the final layer: the element being edited is by itself, 1075 | ' all other elements will need to be handled either through their group 1076 | ' name if in a group, or their name if not 1077 | TagGroupHierarchy = 1 1078 | For Each n In arr 1079 | ActiveWindow.Selection.SlideRange.Shapes(n).Tags.Add "LAYER", TagGroupHierarchy 1080 | ActiveWindow.Selection.SlideRange.Shapes(n).Tags.Add "SELECTIONNAME", n 1081 | Next 1082 | End If 1083 | 1084 | 1085 | End Function 1086 | 1087 | ' Add picture as shape taking care of not inserting it in empty placeholder 1088 | Private Function AddDisplayShape(path As String, PosX As Single, PosY As Single) As Shape 1089 | ' from http://www.vbaexpress.com/forum/showthread.php?47687-Addpicture-adds-the-picture-to-a-placeholder-rather-as-a-new-shape 1090 | ' modified based on http://www.vbaexpress.com/forum/showthread.php?37561-Delete-empty-placeholders 1091 | Dim oshp As Shape 1092 | Dim osld As Slide 1093 | On Error Resume Next 1094 | Set osld = ActiveWindow.Selection.SlideRange(1) 1095 | If Err <> 0 Then Exit Function 1096 | On Error GoTo 0 1097 | For Each oshp In osld.Shapes 1098 | If oshp.Type = msoPlaceholder Then 1099 | If oshp.PlaceholderFormat.ContainedType = msoAutoShape Then 1100 | If oshp.HasTextFrame Then 1101 | If Not oshp.TextFrame.HasText Then oshp.TextFrame.TextRange = "DUMMY" 1102 | End If 1103 | End If 1104 | End If 1105 | Next oshp 1106 | Set AddDisplayShape = osld.Shapes.AddPicture(path, msoFalse, msoTrue, PosX, PosY, -1, -1) 1107 | For Each oshp In osld.Shapes 1108 | If oshp.Type = msoPlaceholder Then 1109 | If oshp.PlaceholderFormat.ContainedType = msoAutoShape Then 1110 | If oshp.HasTextFrame Then 1111 | If oshp.TextFrame.TextRange = "DUMMY" Then oshp.TextFrame.DeleteText 1112 | End If 1113 | End If 1114 | End If 1115 | Next oshp 1116 | End Function 1117 | 1118 | 1119 | Private Function BoundingBoxString(BBXFile As String) As String 1120 | Dim fnum As Integer 1121 | fnum = FreeFile() 1122 | Open BBXFile For Input As #fnum 1123 | Dim TextSplit As Variant 1124 | Dim OutputDpiString As String 1125 | OutputDpiString = TextBoxLocalDPI.Text 1126 | Dim OutputDpi As Long 1127 | OutputDpi = val(OutputDpiString) 1128 | While Not EOF(fnum) 1129 | Line Input #fnum, tmptext 1130 | TextSplit = Split(tmptext, " ") 1131 | If TextSplit(0) = "%%HiResBoundingBox:" Then 1132 | llx = val(TextSplit(1)) 1133 | lly = val(TextSplit(2)) 1134 | urx = val(TextSplit(3)) 1135 | ury = val(TextSplit(4)) 1136 | 'compute size and offset 1137 | sx = CStr(Round((urx - llx) / 72 * OutputDpi)) 1138 | sy = CStr(Round((ury - lly) / 72 * OutputDpi)) 1139 | cx = Str(-llx) 1140 | cy = Str(-lly) 1141 | End If 1142 | Wend 1143 | Close #fnum 1144 | BoundingBoxString = " -g" & sx & "x" & sy & " -c ""<> setpagedevice""" 1145 | End Function 1146 | 1147 | Private Sub SaveSettings() 1148 | RegPath = "Software\IguanaTex" 1149 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "Transparent", REG_DWORD, BoolToInt(checkboxTransp.Value) 1150 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "Debug", REG_DWORD, BoolToInt(checkboxDebug.Value) 1151 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "PointSize", REG_DWORD, CLng(val(textboxSize.Text)) 1152 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "LatexCode", REG_SZ, CStr(TextWindow1.Text) 1153 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "LatexCodeCursor", REG_DWORD, CLng(TextWindow1.SelStart) 1154 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "LatexFormHeight", REG_DWORD, CLng(LatexForm.Height) 1155 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "LatexFormWidth", REG_DWORD, CLng(LatexForm.Width) 1156 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "Multipage", REG_SZ, MultiPage1.Value 1157 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "LatexFormWrap", REG_DWORD, BoolToInt(TextBox1.WordWrap) 1158 | 'SetRegistryValue HKEY_CURRENT_USER, RegPath, "EMFoutput", REG_DWORD, BoolToInt(CheckBoxEMF.Value) 1159 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "BitmapVector", REG_DWORD, ComboBoxBitmapVector.ListIndex 1160 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "OutputDpi", REG_DWORD, CLng(val(TextBoxLocalDPI.Text)) 1161 | 1162 | 1163 | End Sub 1164 | 1165 | Private Sub LoadSettings() 1166 | RegPath = "Software\IguanaTex" 1167 | checkboxTransp.Value = CBool(GetRegistryValue(HKEY_CURRENT_USER, RegPath, "Transparent", True)) 1168 | checkboxDebug.Value = CBool(GetRegistryValue(HKEY_CURRENT_USER, RegPath, "Debug", False)) 1169 | textboxSize.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "PointSize", "20") 1170 | TextWindow1.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "LatexCode", DEFAULT_LATEX_CODE) 1171 | TextWindow1.SelStart = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "LatexCodeCursor", 0) 1172 | MultiPage1.Value = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "Multipage", 0) 1173 | TextWindow1.FontSize = val(GetRegistryValue(HKEY_CURRENT_USER, RegPath, "EditorFontSize", "10")) 1174 | TextBoxTempFolder.Text = GetTempPath() 1175 | TextBox1.WordWrap = CBool(GetRegistryValue(HKEY_CURRENT_USER, RegPath, "LatexFormWrap", True)) 1176 | ToggleButtonWrap.Value = TextBox1.WordWrap 1177 | 1178 | LaTexEngineList = Array("pdflatex", "pdflatex", "xelatex", "lualatex", "platex") 1179 | LaTexEngineDisplayList = Array("latex (DVI)", "pdflatex", "xelatex", "lualatex", "platex") 1180 | UsePDFList = Array(False, True, True, True, True) 1181 | ComboBoxLaTexEngine.List = LaTexEngineDisplayList 1182 | ComboBoxLaTexEngine.ListIndex = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "LaTeXEngineID", 0) 1183 | TextBoxLocalDPI.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "OutputDpi", "1200") 1184 | ComboBoxBitmapVector.List = Array("Bitmap", "Vector") 1185 | ComboBoxBitmapVector.ListIndex = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "BitmapVector", 0) 1186 | 1187 | TemplateSortedListString = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "TemplateSortedList", "0") 1188 | TemplateSortedList = UnpackStringToArray(TemplateSortedListString) 1189 | TemplateNameSortedListString = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "TemplateNameSortedList", "New Template") 1190 | ComboBoxTemplate.List = UnpackStringToArray(TemplateNameSortedListString) 1191 | End Sub 1192 | 1193 | Private Function BoolToInt(val) As Long 1194 | If val Then 1195 | BoolToInt = 1& 1196 | Else 1197 | BoolToInt = 0& 1198 | End If 1199 | End Function 1200 | 1201 | Private Sub ButtonTeXPath_Click() 1202 | TextBoxFile.Text = MacChooseFileOfType("tex") 1203 | TextBoxFile.SetFocus 1204 | End Sub 1205 | 1206 | 1207 | Private Sub ComboBoxBitmapVector_Change() 1208 | Apply_BitmapVector_Change 1209 | End Sub 1210 | 1211 | Private Sub Apply_BitmapVector_Change() 1212 | If ComboBoxBitmapVector.ListIndex = 1 Then 1213 | checkboxTransp.Enabled = False 1214 | checkboxTransp.Value = True 1215 | TextBoxLocalDPI.Enabled = False 1216 | LabelDPI.Enabled = False 1217 | Else 1218 | checkboxTransp.Enabled = True 1219 | TextBoxLocalDPI.Enabled = True 1220 | LabelDPI.Enabled = True 1221 | End If 1222 | 1223 | End Sub 1224 | 1225 | Private Sub CheckBoxReset_Click() 1226 | Apply_CheckBoxReset 1227 | End Sub 1228 | 1229 | Private Sub Apply_CheckBoxReset() 1230 | If CheckBoxReset.Value = True Then 1231 | textboxSize.Enabled = True 1232 | Else 1233 | textboxSize.Enabled = False 1234 | End If 1235 | End Sub 1236 | 1237 | Private Sub CheckBoxForcePreserveSize_Click() 1238 | If CheckBoxForcePreserveSize.Value = True Then 1239 | CheckBoxReset.Enabled = False 1240 | CheckBoxReset.Value = False 1241 | Else 1242 | CheckBoxReset.Enabled = True 1243 | End If 1244 | Apply_CheckBoxReset 1245 | End Sub 1246 | 1247 | Private Sub ButtonAbout_Click() 1248 | AboutBox.Show 1 1249 | End Sub 1250 | 1251 | 1252 | Private Sub ButtonMakeDefault_Click() 1253 | SaveSettings 1254 | Select Case MultiPage1.Value 1255 | Case 0 ' Direct input 1256 | TextWindow1.SetFocus 1257 | Case 1 ' Read from file 1258 | TextBoxFile.SetFocus 1259 | Case Else ' Templates 1260 | TextWindowTemplateCode.SetFocus 1261 | End Select 1262 | End Sub 1263 | 1264 | Private Sub CmdButtonExternalEditor_Click() 1265 | 1266 | ' Put the temporary path in the right format 1267 | If Right(TextBoxTempFolder.Text, 1) <> PathSeperator Then 1268 | TextBoxTempFolder.Text = TextBoxTempFolder.Text & PathSeperator 1269 | End If 1270 | Dim TempPath As String 1271 | TempPath = TextBoxTempFolder.Text 1272 | If Left(TempPath, 1) = "." Then 1273 | Dim sPath As String 1274 | sPath = ActivePresentation.path 1275 | If Len(sPath) > 0 Then 1276 | If Right(sPath, 1) <> PathSeperator Then 1277 | sPath = sPath & PathSeperator 1278 | End If 1279 | TempPath = sPath & TempPath 1280 | Else 1281 | MsgBox "You need to have saved your presentation once to use a relative path." 1282 | Exit Sub 1283 | End If 1284 | End If 1285 | 1286 | Dim FilePrefix As String 1287 | FilePrefix = GetFilePrefix() 1288 | 1289 | ' Test if path writable 1290 | If Not IsPathWritable(TempPath) Then 1291 | MsgBox "The temporary folder " & TempPath & " appears not to be writable." 1292 | Exit Sub 1293 | End If 1294 | 1295 | ' Write latex to a temp file 1296 | Call WriteLaTeX2File(TempPath, FilePrefix) 1297 | 1298 | ' Launch external editor 1299 | On Error GoTo ShellError 1300 | AppleScriptTask "IguanaTex.scpt", "MacExecute", GetEditorPath() & " " & ShellEscape(TempPath & FilePrefix & ".tex") 1301 | 1302 | ' Show dialog form to reload from file or cancel 1303 | ExternalEditorForm.Show 1304 | Exit Sub 1305 | 1306 | ShellError: 1307 | MsgBox "Error Launching External Editor." & vbCrLf & _ 1308 | Err.Description, vbOKOnly Or vbExclamation, _ 1309 | "Error" 1310 | Exit Sub 1311 | End Sub 1312 | 1313 | Private Sub CmdButtonImportCode_Click() 1314 | TextWindowTemplateCode.Utf8 = TextWindow1.Utf8 1315 | TextWindowTemplateCode.SelStart = TextWindow1.SelStart 1316 | TextWindowTemplateCode.SetFocus 1317 | End Sub 1318 | 1319 | Private Sub CmdButtonLoadTemplate_Click() 1320 | If TextWindowTemplateCode.Text = "" Then 1321 | MsgBox "Please select a template to be loaded" 1322 | Else 1323 | TextWindow1.Utf8 = TextWindowTemplateCode.Utf8 1324 | TextWindow1.SelStart = TextWindowTemplateCode.SelStart 1325 | MultiPage1.Value = 0 1326 | Call ToggleInputMode 1327 | End If 1328 | End Sub 1329 | 1330 | Private Sub CmdButtonRemoveTemplate_Click() 1331 | Dim RemovedIndex As Long 1332 | RemovedIndex = ComboBoxTemplate.ListIndex 1333 | If ComboBoxTemplate.ListCount > 1 Then 1334 | ' We should also be deleting the registry entry, but well, it does not take much space and will likely get reused anyway 1335 | ComboBoxTemplate.RemoveItem RemovedIndex 1336 | 1337 | ' update the array that contains the sorted list of template IDs 1338 | tmpID = TemplateSortedList(RemovedIndex) 1339 | Dim i As Long 1340 | For i = RemovedIndex To UBound(TemplateSortedList) - 1 1341 | TemplateSortedList(i) = TemplateSortedList(i + 1) 1342 | Next i 1343 | TemplateSortedList(UBound(TemplateSortedList)) = tmpID 1344 | 'NumberOfTemplates = NumberOfTemplates - 1 1345 | Else 1346 | ComboBoxTemplate.Clear 1347 | ComboBoxTemplate.AddItem "New Template" 'prepare spot for new template 1348 | ComboBoxTemplate.Text = "" 1349 | 'NumberOfTemplates = 1 1350 | End If 1351 | Call UpdateTemplateRegistry 1352 | ComboBoxTemplate.ListIndex = RemovedIndex 1353 | TextWindowTemplateCode.SetFocus 1354 | End Sub 1355 | 1356 | Private Sub CmdButtonSaveTemplate_Click() 1357 | ' get the right ID from the array of sorted template IDs 1358 | templateID = TemplateSortedList(ComboBoxTemplate.ListIndex) 1359 | ' add trailing new line if there isn't one: this helps with a bug where text with multi-byte characters gets chopped 1360 | If Not Right(TextWindowTemplateCode.Text, 1) = vbLf Then 1361 | TextWindowTemplateCode.Text = TextWindowTemplateCode.Text & vbLf 1362 | End If 1363 | ' build the corresponding registry key string 1364 | ' Save name, code, and LaTeXEngineID 1365 | RegPath = "Software\IguanaTex" 1366 | Dim RegStr As String 1367 | RegStr = "TemplateCode" & templateID 1368 | SetRegistryValue HKEY_CURRENT_USER, RegPath, RegStr, REG_SZ, CStr(TextWindowTemplateCode.Text) 1369 | RegStr = "TemplateCodeSelStart" & templateID 1370 | SetRegistryValue HKEY_CURRENT_USER, RegPath, RegStr, REG_DWORD, CLng(TextWindowTemplateCode.SelStart) 1371 | RegStr = "TemplateLaTeXEngineID" & templateID 1372 | SetRegistryValue HKEY_CURRENT_USER, RegPath, RegStr, REG_DWORD, ComboBoxLaTexEngine.ListIndex 1373 | RegStr = "TemplateBitmapVector" & templateID 1374 | SetRegistryValue HKEY_CURRENT_USER, RegPath, RegStr, REG_DWORD, ComboBoxBitmapVector.ListIndex 1375 | RegStr = "TemplateTempFolder" & templateID 1376 | SetRegistryValue HKEY_CURRENT_USER, RegPath, RegStr, REG_SZ, CStr(TextBoxTempFolder.Text) 1377 | RegStr = "TemplateDPI" & templateID 1378 | SetRegistryValue HKEY_CURRENT_USER, RegPath, RegStr, REG_SZ, CStr(TextBoxLocalDPI.Text) 1379 | ' if saved template was the "New Template", prepare new spot for next new template 1380 | If ComboBoxTemplate.ListIndex = ComboBoxTemplate.ListCount - 1 Then 1381 | ComboBoxTemplate.AddItem "New Template" 1382 | 'NumberOfTemplates = NumberOfTemplates + 1 1383 | If ComboBoxTemplate.ListCount - 1 > UBound(TemplateSortedList) Then 1384 | ReDim Preserve TemplateSortedList(0 To UBound(TemplateSortedList) + 1) As String 1385 | TemplateSortedList(UBound(TemplateSortedList)) = CStr(ComboBoxTemplate.ListCount - 1) 1386 | End If 1387 | End If 1388 | ComboBoxTemplate.List(ComboBoxTemplate.ListIndex) = TextBoxTemplateName.Text 1389 | Call UpdateTemplateRegistry 1390 | TextWindowTemplateCode.SetFocus 1391 | End Sub 1392 | 1393 | 1394 | 1395 | Private Sub ComboBoxTemplate_Click() 1396 | TextBoxTemplateName.Text = ComboBoxTemplate.Text 1397 | ' Except for the empty "New Template" slot, get the code and LaTeXEngineID setting from registry 1398 | If ComboBoxTemplate.ListIndex = ComboBoxTemplate.ListCount - 1 Then 1399 | TextWindowTemplateCode.Text = "" 1400 | ComboBoxLaTexEngine.ListIndex = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "LaTeXEngineID", 0) 1401 | TextBoxTempFolder.Text = GetTempPath() 1402 | Else 1403 | ' get the right ID from the array of sorted template IDs 1404 | templateID = TemplateSortedList(ComboBoxTemplate.ListIndex) 1405 | ' build the corresponding registry key string 1406 | RegPath = "Software\IguanaTex" 1407 | Dim RegStr As String 1408 | RegStr = "TemplateCode" & templateID 1409 | TextWindowTemplateCode.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, RegStr, "") 1410 | RegStr = "TemplateCodeSelStart" & templateID 1411 | TextWindowTemplateCode.SelStart = GetRegistryValue(HKEY_CURRENT_USER, RegPath, RegStr, 0) 1412 | RegStr = "TemplateLaTeXEngineID" & templateID 1413 | ComboBoxLaTexEngine.ListIndex = GetRegistryValue(HKEY_CURRENT_USER, RegPath, RegStr, GetRegistryValue(HKEY_CURRENT_USER, RegPath, "LaTeXEngineID", 0)) 1414 | RegStr = "TemplateBitmapVector" & templateID 1415 | ComboBoxBitmapVector.ListIndex = GetRegistryValue(HKEY_CURRENT_USER, RegPath, RegStr, GetRegistryValue(HKEY_CURRENT_USER, RegPath, "BitmapVector", False)) 1416 | RegStr = "TemplateTempFolder" & templateID 1417 | TextBoxTempFolder.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, RegStr, GetTempPath()) 1418 | RegStr = "TemplateDPI" & templateID 1419 | TextBoxLocalDPI.Text = GetRegistryValue(HKEY_CURRENT_USER, RegPath, RegStr, "") 1420 | Apply_BitmapVector_Change 1421 | End If 1422 | TextWindowTemplateCode.SetFocus 1423 | End Sub 1424 | 1425 | Private Sub UpdateTemplateRegistry() 1426 | ' update the list of saved templates names in the registry (will be used to initialize combo box content) 1427 | TemplateSortedListString = PackArrayToString(TemplateSortedList) 1428 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "TemplateSortedList", REG_SZ, CStr(TemplateSortedListString) 1429 | ' save list of template names to registry 1430 | Dim myArray() As String 1431 | ReDim myArray(0 To ComboBoxTemplate.ListCount - 1) As String 1432 | Dim i As Long 1433 | For i = LBound(myArray) To UBound(myArray) 1434 | myArray(i) = ComboBoxTemplate.List(i) 1435 | Next i 1436 | TemplateNameSortedListString = PackArrayToString(myArray) 1437 | SetRegistryValue HKEY_CURRENT_USER, RegPath, "TemplateNameSortedList", REG_SZ, CStr(TemplateNameSortedListString) 1438 | End Sub 1439 | 1440 | Private Sub CmdButtonTemplateFontDown_Click() 1441 | If TextWindowTemplateCode.FontSize > 4 Then 1442 | TextWindowTemplateCode.FontSize = TextWindowTemplateCode.FontSize - 1 1443 | End If 1444 | End Sub 1445 | 1446 | Private Sub CmdButtonTemplateFontUp_Click() 1447 | If TextWindowTemplateCode.FontSize < 72 Then 1448 | TextWindowTemplateCode.FontSize = TextWindowTemplateCode.FontSize + 1 1449 | End If 1450 | End Sub 1451 | 1452 | Private Sub CmdButtonEditorFontDown_Click() 1453 | If TextWindow1.FontSize > 4 Then 1454 | TextWindow1.FontSize = TextWindow1.FontSize - 1 1455 | End If 1456 | End Sub 1457 | 1458 | Private Sub CmdButtonEditorFontUp_Click() 1459 | If TextWindow1.FontSize < 72 Then 1460 | TextWindow1.FontSize = TextWindow1.FontSize + 1 1461 | End If 1462 | End Sub 1463 | 1464 | Private Sub ToggleButtonWrap_Click() 1465 | If ToggleButtonWrap.Value = True Then 1466 | TextBox1.WordWrap = True 1467 | Else 1468 | TextBox1.WordWrap = False 1469 | End If 1470 | End Sub 1471 | 1472 | Private Sub UserForm_Initialize() 1473 | LoadSettings 1474 | 1475 | ' With multiple monitors, the "CenterOwner" option to open the UserForm in the center of the parent window 1476 | ' does not seem to work, at least in Office 2010. 1477 | ' The following code to manually place the UserForm somehow makes the "CenterOwner" option work. 1478 | ' Remark: if used with the Manual placement option, it would place the window to the left, under the ribbon. 1479 | Me.Top = Application.Top + 110 1480 | Me.Left = Application.Left + 25 1481 | 1482 | LatexForm.textboxSize.Visible = True 1483 | LatexForm.Label2.Visible = True 1484 | LatexForm.Label3.Visible = True 1485 | 1486 | FrameProcess.Visible = False 1487 | 1488 | 1489 | End Sub 1490 | 1491 | Private Sub UserForm_Activate() 1492 | 'Execute macro to enable resizeability 1493 | MakeFormResizable 1494 | 1495 | RegPath = "Software\IguanaTex" 1496 | If Not FormHeightWidthSet Then 1497 | LatexForm.Height = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "LatexFormHeight", 312) 1498 | LatexForm.Width = GetRegistryValue(HKEY_CURRENT_USER, RegPath, "LatexFormWidth", 380) 1499 | End If 1500 | ' ResizeForm 1501 | ToggleInputMode 1502 | 1503 | End Sub 1504 | 1505 | Sub RetrieveOldShapeInfo(oldshape As Shape, mainText As String) 1506 | CheckBoxReset.Visible = True 1507 | CheckBoxReset.Value = False 1508 | CheckBoxResetFormat.Visible = True 1509 | CheckBoxResetFormat.Value = False 1510 | CheckBoxForcePreserveSize.Visible = True 1511 | CheckBoxForcePreserveSize.Value = False 1512 | Label2.Caption = "Reset size:" 1513 | ButtonRun.Caption = "ReGenerate" 1514 | ButtonRun.Accelerator = "G" 1515 | 1516 | TextWindow1.Text = mainText 1517 | CursorPosition = Len(mainText) 1518 | 1519 | Dim FormHeightSet As Boolean 1520 | Dim FormWidthSet As Boolean 1521 | FormHeightSet = False 1522 | FormWidthSet = False 1523 | 1524 | With oldshape.Tags 1525 | If .Item("IGUANATEXSIZE") <> "" Then 1526 | textboxSize.Text = .Item("IGUANATEXSIZE") 1527 | End If 1528 | If .Item("OUTPUTDPI") <> "" Then 1529 | TextBoxLocalDPI.Text = .Item("OUTPUTDPI") 1530 | End If 1531 | If .Item("BitmapVector") <> "" Then 1532 | ComboBoxBitmapVector.ListIndex = .Item("BitmapVector") 1533 | End If 1534 | If .Item("TRANSPARENCY") <> "" Then 1535 | checkboxTransp.Value = SanitizeBoolean(.Item("TRANSPARENCY"), True) 1536 | ElseIf .Item("TRANSPARENT") <> "" Then 1537 | checkboxTransp.Value = SanitizeBoolean(.Item("TRANSPARENT"), True) 1538 | End If 1539 | If .Item("IGUANATEXCURSOR") <> "" Then 1540 | CursorPosition = .Item("IGUANATEXCURSOR") 1541 | End If 1542 | If .Item("LATEXENGINEID") <> "" Then 1543 | ComboBoxLaTexEngine.ListIndex = .Item("LATEXENGINEID") 1544 | End If 1545 | If .Item("LATEXFORMHEIGHT") <> "" Then 1546 | LatexForm.Height = .Item("LATEXFORMHEIGHT") 1547 | FormHeightSet = True 1548 | End If 1549 | If .Item("LATEXFORMWIDTH") <> "" Then 1550 | LatexForm.Width = .Item("LATEXFORMWIDTH") 1551 | FormWidthSet = True 1552 | End If 1553 | If .Item("LATEXFORMWRAP") <> "" Then 1554 | TextBox1.WordWrap = SanitizeBoolean(.Item("LATEXFORMWRAP"), True) 1555 | ToggleButtonWrap.Value = TextBox1.WordWrap 1556 | End If 1557 | End With 1558 | Apply_BitmapVector_Change 1559 | FormHeightWidthSet = FormHeightSet And FormWidthSet 1560 | TextWindow1.SelStart = CursorPosition 1561 | textboxSize.Enabled = False 1562 | End Sub 1563 | 1564 | 1565 | Private Function SanitizeBoolean(Str As String, Def As Boolean) As Boolean 1566 | On Error GoTo ErrWrongBoolean: 1567 | SanitizeBoolean = CBool(Str) 1568 | Exit Function 1569 | ErrWrongBoolean: 1570 | SanitizeBoolean = Def 1571 | Resume Next 1572 | End Function 1573 | 1574 | Private Sub UserForm_Resize() 1575 | ' Minimal size 1576 | Select Case MultiPage1.Value 1577 | Case 0 ' Direct input 1578 | minLatexFormHeight = MultiPage1.Top + 18 + 50 + 6 * ButtonAbout.Height 1579 | Case 1 ' Read from file 1580 | minLatexFormHeight = MultiPage1.Top + 18 + 50 + 6 * ButtonAbout.Height 1581 | Case Else ' Templates 1582 | minLatexFormHeight = MultiPage1.Top + 18 + 50 + 9 * ButtonAbout.Height 1583 | End Select 1584 | minLatexFormWidth = ButtonCancel.Left + ButtonCancel.Width + ButtonAbout.Width + 24 1585 | 1586 | If LatexForm.Height < minLatexFormHeight Then 1587 | LatexForm.Height = minLatexFormHeight 1588 | End If 1589 | If LatexForm.Width < minLatexFormWidth Then 1590 | LatexForm.Width = minLatexFormWidth 1591 | End If 1592 | 1593 | ResizeForm 1594 | End Sub 1595 | 1596 | Private Sub ResizeForm() 1597 | Dim bordersize As Integer 1598 | bordersize = 6 1599 | 1600 | MultiPage1.Left = bordersize 1601 | MultiPage1.Top = bordersize 1602 | MultiPage1.Width = LatexForm.Width - bordersize * 2 1603 | MultiPage1.Height = LatexForm.Height - MultiPage1.Top - ButtonAbout.Height * 4 1604 | TextBox1.Width = MultiPage1.Width - 12 1605 | TextBox1.Height = MultiPage1.Height - TextBox1.Top - 20 1606 | 1607 | 'Other elements are moved as needed 1608 | ButtonAbout.Top = MultiPage1.Top + MultiPage1.Height + bordersize 1609 | ButtonAbout.Left = ButtonCancel.Left + ButtonCancel.Width + bordersize 1610 | ButtonRun.Top = ButtonAbout.Top 1611 | ButtonCancel.Top = ButtonRun.Top 1612 | ButtonMakeDefault.Top = ButtonAbout.Top + ButtonAbout.Height + bordersize 1613 | ButtonMakeDefault.Left = ButtonAbout.Left 1614 | FrameProcess.Top = ButtonMakeDefault.Top 1615 | FrameProcess.Left = ButtonRun.Left 1616 | LabelProcess.Width = FrameProcess.Width 1617 | LabelProcess.Top = 4 1618 | 1619 | CmdButtonImportCode.Left = TextBox1.Width - CmdButtonImportCode.Width 1620 | CmdButtonLoadTemplate.Left = CmdButtonImportCode.Left 1621 | CmdButtonSaveTemplate.Left = CmdButtonImportCode.Left 1622 | CmdButtonRemoveTemplate.Left = CmdButtonImportCode.Left 1623 | TextBoxTemplateCode.Width = CmdButtonImportCode.Left - bordersize 1624 | TextBoxTemplateCode.Height = MultiPage1.Height - TextBoxTemplateCode.Top - 20 1625 | 1626 | textboxSize.Top = ButtonAbout.Top 1627 | Label2.Top = textboxSize.Top + Round(textboxSize.Height - Label2.Height) / 2 1628 | CheckBoxReset.Top = textboxSize.Top 1629 | Label3.Top = Label2.Top 1630 | checkboxTransp.Top = CheckBoxReset.Top + 21 'checkboxTransp.Height + 2 1631 | CheckBoxForcePreserveSize.Top = checkboxTransp.Top 1632 | CheckBoxForcePreserveSize.Left = checkboxTransp.Left + 66 1633 | checkboxDebug.Top = checkboxTransp.Top + 21 ' checkboxTransp.Height + 2 1634 | CheckBoxResetFormat.Top = checkboxDebug.Top 1635 | CheckBoxResetFormat.Left = checkboxDebug.Left + checkboxDebug.Width + 10 1636 | 1637 | End Sub 1638 | 1639 | Private Sub MoveAnimation(oldshape As Shape, newShape As Shape) 1640 | ' Move the animation settings of oldShape to newShape 1641 | With ActiveWindow.Selection.SlideRange(1).TimeLine 1642 | Dim eff As Effect 1643 | For Each eff In .MainSequence 1644 | If eff.Shape.name = oldshape.name Then eff.Shape = newShape 1645 | Next 1646 | End With 1647 | End Sub 1648 | 1649 | Private Sub MatchZOrder(oldshape As Shape, newShape As Shape) 1650 | ' Make the Z order of newShape equal to 1 higher than that of oldShape 1651 | newShape.ZOrder msoBringToFront 1652 | While (newShape.ZOrderPosition > oldshape.ZOrderPosition + 1) 1653 | newShape.ZOrder msoSendBackward 1654 | Wend 1655 | End Sub 1656 | 1657 | Private Sub DeleteAnimation(oldshape As Shape) 1658 | ' Delete the animation settings of oldShape 1659 | With ActiveWindow.Selection.SlideRange(1).TimeLine 1660 | For i = .MainSequence.count To 1 Step -1 1661 | Dim eff As Effect 1662 | Set eff = .MainSequence(i) 1663 | If eff.Shape.name = oldshape.name Then eff.Delete 1664 | Next 1665 | End With 1666 | End Sub 1667 | 1668 | Private Sub TransferGroupFormat(oldshape As Shape, newShape As Shape) 1669 | On Error Resume Next 1670 | ' Transfer group formatting 1671 | If oldshape.Glow.Radius > 0 Then 1672 | newShape.Glow.Color = oldshape.Glow.Color 1673 | newShape.Glow.Radius = oldshape.Glow.Radius 1674 | newShape.Glow.Transparency = oldshape.Glow.Transparency 1675 | End If 1676 | If oldshape.Reflection.Type <> msoReflectionTypeNone Then 1677 | newShape.Reflection.Blur = oldshape.Reflection.Blur 1678 | newShape.Reflection.Offset = oldshape.Reflection.Offset 1679 | newShape.Reflection.size = oldshape.Reflection.size 1680 | newShape.Reflection.Transparency = oldshape.Reflection.Transparency 1681 | newShape.Reflection.Type = oldshape.Reflection.Type 1682 | End If 1683 | 1684 | If oldshape.SoftEdge.Type <> msoSoftEdgeTypeNone Then 1685 | newShape.SoftEdge.Radius = oldshape.SoftEdge.Radius 1686 | End If 1687 | 1688 | If oldshape.Shadow.Visible Then 1689 | newShape.Shadow.Visible = oldshape.Shadow.Visible 1690 | newShape.Shadow.Blur = oldshape.Shadow.Blur 1691 | newShape.Shadow.ForeColor = oldshape.Shadow.ForeColor 1692 | newShape.Shadow.OffsetX = oldshape.Shadow.OffsetX 1693 | newShape.Shadow.OffsetY = oldshape.Shadow.OffsetY 1694 | newShape.Shadow.RotateWithShape = oldshape.Shadow.RotateWithShape 1695 | newShape.Shadow.size = oldshape.Shadow.size 1696 | newShape.Shadow.Style = oldshape.Shadow.Style 1697 | newShape.Shadow.Transparency = oldshape.Shadow.Transparency 1698 | newShape.Shadow.Type = oldshape.Shadow.Type 1699 | End If 1700 | 1701 | If oldshape.ThreeD.Visible Then 1702 | 'newShape.ThreeD.BevelBottomDepth = oldshape.ThreeD.BevelBottomDepth 1703 | 'newShape.ThreeD.BevelBottomInset = oldshape.ThreeD.BevelBottomInset 1704 | 'newShape.ThreeD.BevelBottomType = oldshape.ThreeD.BevelBottomType 1705 | 'newShape.ThreeD.BevelTopDepth = oldshape.ThreeD.BevelTopDepth 1706 | 'newShape.ThreeD.BevelTopInset = oldshape.ThreeD.BevelTopInset 1707 | 'newShape.ThreeD.BevelTopType = oldshape.ThreeD.BevelTopType 1708 | 'newShape.ThreeD.ContourColor = oldshape.ThreeD.ContourColor 1709 | 'newShape.ThreeD.ContourWidth = oldshape.ThreeD.ContourWidth 1710 | 'newShape.ThreeD.Depth = oldshape.ThreeD.Depth 1711 | 'newShape.ThreeD.ExtrusionColor = oldshape.ThreeD.ExtrusionColor 1712 | 'newShape.ThreeD.ExtrusionColorType = oldshape.ThreeD.ExtrusionColorType 1713 | newShape.ThreeD.Visible = oldshape.ThreeD.Visible 1714 | newShape.ThreeD.Perspective = oldshape.ThreeD.Perspective 1715 | newShape.ThreeD.FieldOfView = oldshape.ThreeD.FieldOfView 1716 | newShape.ThreeD.LightAngle = oldshape.ThreeD.LightAngle 1717 | 'newShape.ThreeD.ProjectText = oldshape.ThreeD.ProjectText 1718 | 'If oldshape.ThreeD.PresetExtrusionDirection <> msoPresetExtrusionDirectionMixed Then 1719 | ' newShape.ThreeD.SetExtrusionDirection oldshape.ThreeD.PresetExtrusionDirection 1720 | 'End If 1721 | newShape.ThreeD.PresetLighting = oldshape.ThreeD.PresetLighting 1722 | If oldshape.ThreeD.PresetLightingDirection <> msoPresetLightingDirectionMixed Then 1723 | newShape.ThreeD.PresetLightingDirection = oldshape.ThreeD.PresetLightingDirection 1724 | End If 1725 | If oldshape.ThreeD.PresetLightingSoftness <> msoPresetLightingSoftnessMixed Then 1726 | newShape.ThreeD.PresetLightingSoftness = oldshape.ThreeD.PresetLightingSoftness 1727 | End If 1728 | If oldshape.ThreeD.PresetMaterial <> msoPresetMaterialMixed Then 1729 | newShape.ThreeD.PresetMaterial = oldshape.ThreeD.PresetMaterial 1730 | End If 1731 | If oldshape.ThreeD.PresetCamera <> msoPresetCameraMixed Then 1732 | newShape.ThreeD.SetPresetCamera oldshape.ThreeD.PresetCamera 1733 | End If 1734 | newShape.ThreeD.RotationX = oldshape.ThreeD.RotationX 1735 | newShape.ThreeD.RotationY = oldshape.ThreeD.RotationY 1736 | newShape.ThreeD.RotationZ = oldshape.ThreeD.RotationZ 1737 | 'newShape.ThreeD.Z = oldshape.ThreeD.Z 1738 | End If 1739 | End Sub 1740 | 1741 | 'Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) 1742 | ' ' If CloseMode = vbFormControlMenu Then 1743 | ' ' Cancel = True 1744 | ' ' ButtonCancel_Click 1745 | ' ' End If 1746 | 'End Sub 1747 | 1748 | 1749 | Private Function isTex(file As String) 1750 | Ext = Right$(file, Len(file) - InStrRev(file, ".")) 1751 | If Ext = "tex" Then 1752 | isTex = True 1753 | Else 1754 | isTex = False 1755 | End If 1756 | End Function 1757 | 1758 | 1759 | Private Sub MultiPage1_Change() 1760 | Call ToggleInputMode 1761 | End Sub 1762 | 1763 | 1764 | Private Sub TextBoxFile_Change() 1765 | Set fs = New FileSystemObject 1766 | ButtonLoadFile.Enabled = fs.FileExists(TextBoxFile.Text) And isTex(TextBoxFile.Text) 1767 | End Sub 1768 | 1769 | Private Sub ButtonLoadFile_Click() 1770 | MultiPage1.Value = 0 1771 | Call LoadTexFile 1772 | Call ToggleInputMode 1773 | End Sub 1774 | 1775 | Private Sub LoadTexFile() 1776 | 1777 | Dim fs 1778 | Dim TexFile As Object 1779 | Const ForReading = 1, ForWriting = 2, ForAppending = 3 1780 | 1781 | Set fs = New FileSystemObject 1782 | If fs.FileExists(TextBoxFile.Text) Then 1783 | TextWindow1.Text = ReadAllExternal(TextBoxFile.Text) 1784 | End If 1785 | 1786 | End Sub 1787 | 1788 | 1789 | Private Sub ToggleInputMode() 1790 | Call UserForm_Resize 1791 | 1792 | If MultiPage1.Value = 0 Then 1793 | TextWindow1.Show 1794 | TextWindow1.ResizeAs TextBox1, Me 1795 | Else 1796 | TextWindow1.Hide 1797 | End If 1798 | 1799 | If MultiPage1.Value = 2 Then 1800 | TextWindowTemplateCode.Show 1801 | TextWindowTemplateCode.ResizeAs TextBoxTemplateCode, Me 1802 | Else 1803 | TextWindowTemplateCode.Hide 1804 | End If 1805 | 1806 | Set fs = New FileSystemObject 1807 | Const ForReading = 1, ForWriting = 2, ForAppending = 3 1808 | 1809 | Select Case MultiPage1.Value 1810 | Case 0 ' Direct input 1811 | TextWindow1.SetFocus 1812 | Case 1 ' Read from file 1813 | TextBoxFile.SetFocus 1814 | ButtonLoadFile.Enabled = fs.FileExists(TextBoxFile.Text) And isTex(TextBoxFile.Text) 1815 | Case Else ' Templates 1816 | If TextBoxTemplateName.Text = "" Then 1817 | TextBoxTemplateName.Text = ComboBoxTemplate.Text 1818 | End If 1819 | TextWindowTemplateCode.SetFocus 1820 | End Select 1821 | 1822 | End Sub 1823 | 1824 | Private Function PackArrayToString(vArray As Variant) As String 1825 | Dim strDelimiter As String 1826 | strDelimiter = "|" 1827 | PackArrayToString = Join(vArray, strDelimiter) 1828 | End Function 1829 | 1830 | Private Function UnpackStringToArray(Str As String) As Variant 1831 | Dim strDelimiter As String 1832 | strDelimiter = "|" 1833 | UnpackStringToArray = Split(Str, strDelimiter, , vbTextCompare) 1834 | End Function 1835 | 1836 | 1837 | ' Attempt at getting DPI of previous display, but I cannot find a way to retrieve 1838 | ' that info for an embedded display, as there does not seem to be a way to load 1839 | ' the display as an ImageFile Object 1840 | ' Requires Microsoft Windows Image Acquisition Library 1841 | 'Private Function GetImageFileDPI(fileNm As String) As Long 1842 | ' Dim imgFile As Object 1843 | ' Set imgFile = CreateObject("WIA.ImageFile") 1844 | ' imgFile.LoadFile (fileNm) 1845 | ' GetImageFileDPI = 96 1846 | ' If imgFile.HorizontalResolution <> "" Then 1847 | ' GetImageFileDPI = Round(imgFile.HorizontalResolution) 1848 | ' End If 1849 | 'End Function 1850 | --------------------------------------------------------------------------------