Imports SolidEdgeFileProperties
Imports System.Runtime.InteropServices

Module Module1

    Public objSheets As SolidEdgeDraft.Sheets
    Public objSheet As SolidEdgeDraft.Sheet
    Public objTextboxes As SolidEdgeFrameworkSupport.TextBoxes
    Public objTextBox As SolidEdgeFrameworkSupport.TextBox
    Public objBalloons As SolidEdgeFrameworkSupport.Balloons
    Public objBalloon As SolidEdgeFrameworkSupport.Balloon
    Public objDimensions As SolidEdgeFrameworkSupport.Dimensions
    Public objDimension As SolidEdgeFrameworkSupport.Dimension
    Public objSEApp As SolidEdgeFramework.Application
    Public objDraftDoc As SolidEdgeDraft.DraftDocument
    Public strTextStringToBeChecked As String
    Public strTextStringCorrected As String
    Public MSWord As New Microsoft.Office.Interop.Word.Application
    Public WordType As Type
    Public suggestions As System.Collections.ArrayList, w As Object
    Public SpellCheckForm As Form
    Public strParsedString As String
    Public strLinkedFileName As String
    Public SEFilePropertiesType As Type
    Public strVerWord As Double
    Public bolFlag As Boolean

    Public propertySets As PropertySetsClass
    Public BlnNewSEUI As Boolean = False

    Sub main()
        Dim ii As Integer
        Dim intLinkDocsCount As Integer

        '******* Added because of .NET
        Try
            MessageFilter.Register()
        Catch ex As Exception
            MsgBox("Error registering message filter.", MsgBoxStyle.OkOnly)
        End Try
        '******* Added because of .NET

        Try
            objSEApp = Marshal.GetActiveObject("SolidEdge.Application")
        Catch ex As Exception
            MsgBox("Solid Edge does not appear to be running.  Please start Solid Edge", MsgBoxStyle.OkOnly)
            GoTo Finished
        End Try

        objSEApp.StatusBar = "Processing Spell Checker.....  Please wait."

        Try
            objDraftDoc = objSEApp.ActiveDocument
            intLinkDocsCount = objDraftDoc.ModelLinks.Count
        Catch ex As Exception
            MsgBox("Open a SOlid Edge Draft Document", MsgBoxStyle.OkOnly)
            GoTo Finished
        End Try

        Try
            objSEApp = Marshal.GetActiveObject("SolidEdge.Application")
            strLinkedFileName = objSEApp.ActiveDocument.activesheet.drawingviews.item(1).modellink.filename
        Catch ex As Exception

        End Try

        ' See if we can get word up and running
        Try
            WordType = Type.GetTypeFromProgID("Word.Application")
            MSWord = Marshal.GetActiveObject("Word.Application")
            strVerWord = MSWord.Version

        Catch ex As System.Exception

            MSWord = Activator.CreateInstance(WordType)
            MSWord.Visible = False

            If MSWord Is Nothing Then
                MsgBox("Could not create Word process", MsgBoxStyle.OkOnly)
                GoTo Finished
            End If
        End Try

        If strVerWord < 12.0 Then
            MsgBox("Draft Spell Checker requires Office 2007 or later")
        End If


        'need to set up big loop to process each sheet in the current draft file
        objSheets = objDraftDoc.Sheets

        For ii = 1 To objSheets.Count
            Call ProcessDraftSheet(objSheets.Item(ii))
        Next


        'spell check current draft file property values in case they are used in linked property text
        PullSEPropertyFromOpenedFile()

        'spell check linked file property values in case they are used in linked property text
        For ii = 1 To intLinkDocsCount
            strLinkedFileName = objDraftDoc.ModelLinks.Item(ii).FileName
            PullSEPropertyFromFile(strLinkedFileName)
        Next


        objSEApp.StartCommand(32901)

        ' one remaining hole is parts list for an assembly

Finished:
        objDraftDoc.UpdatePropertyTextDisplay()

        If Not objSEApp Is Nothing Then objSEApp.StatusBar = " "

        If Not (MSWord Is Nothing) Then
            MSWord.Quit()
            Marshal.ReleaseComObject(MSWord)
            MSWord = Nothing
        End If

        If Not (objSheets Is Nothing) Then
            Marshal.ReleaseComObject(objSheets)
            objSheets = Nothing
        End If

        If Not (objSEApp Is Nothing) Then
            Marshal.ReleaseComObject(objSEApp)
            objSEApp = Nothing
        End If

        If Not (objDraftDoc Is Nothing) Then
            Marshal.ReleaseComObject(objDraftDoc)
            objDraftDoc = Nothing
        End If

        Garbage_Collect(MSWord)
        Garbage_Collect(objSheets)
        Garbage_Collect(objDraftDoc)
        Garbage_Collect(objSEApp)

        '******* Added because of .NET
        Try
            MessageFilter.Revoke()
        Catch ex As Exception
            MsgBox("Error revoking message filter.", MsgBoxStyle.OkOnly)
        End Try
        '******* Added because of .NET

        MsgBox("Finished spell check", MsgBoxStyle.OkOnly)

        End
    End Sub



    Public Function ProcessDraftSheet(ByVal objSheet As SolidEdgeDraft.Sheet) As Boolean

        'Dim i As Integer
        'Dim strChar As String
        'Dim intChar As Integer
        Dim jj As Integer
        Dim intHorzJust As Integer
        Dim intVertJust As Integer
        Dim strCR As String = Chr(13)
        Dim offset As Integer = 1

        suggestions = New System.Collections.ArrayList

        Try
            objTextboxes = objSheet.TextBoxes
            For jj = 1 To objTextboxes.Count
                intHorzJust = objTextboxes.Item(jj).HorizontalAlignment
                intVertJust = objTextboxes.Item(jj).VerticalAlignment
                strTextStringToBeChecked = objTextboxes.Item(jj).Text

                ' debug section to see what the end terminator looks like for multi-line textbox.
                'For i = 0 To strTextStringToBeChecked.Length - 1
                '    strChar = strTextStringToBeChecked.Substring(i, 1)
                '    intChar = Asc(strChar)
                'Next

                ' Insert subroutine to do repetitive processing
                ParseString()

                If bolFlag Then
                    objTextboxes.Item(jj).Text = strTextStringToBeChecked
                    objTextboxes.Item(jj).VerticalAlignment = intVertJust
                    objTextboxes.Item(jj).HorizontalAlignment = intHorzJust
                End If
            Next

            objBalloons = objSheet.Balloons

            For jj = 1 To objBalloons.Count
                If objBalloons.Item(jj).BalloonText <> "" Then
                    If Mid(objBalloons.Item(jj).BalloonText, 1, 1) = "%" Then
                        GoTo skip
                    End If
                    strTextStringToBeChecked = objBalloons.Item(jj).BalloonText

                    ParseString()


                    If bolFlag Then
                        objBalloons.Item(jj).BalloonText = strTextStringToBeChecked
                    End If

                End If
skip:
                If objBalloons.Item(jj).BalloonTextLower <> "" Then
                    strTextStringToBeChecked = objBalloons.Item(jj).BalloonTextLower

                    ParseString()


                    If bolFlag Then
                        objBalloons.Item(jj).BalloonTextLower = strTextStringToBeChecked
                    End If

                End If

                If objBalloons.Item(jj).BalloonTextPrefix <> "" Then
                    strTextStringToBeChecked = objBalloons.Item(jj).BalloonTextPrefix

                    ParseString()


                    If bolFlag Then
                        objBalloons.Item(jj).BalloonTextPrefix = strTextStringToBeChecked
                    End If

                End If

                If objBalloons.Item(jj).BalloonTextSuffix <> "" Then
                    strTextStringToBeChecked = objBalloons.Item(jj).BalloonTextSuffix

                    ParseString()


                    If bolFlag Then
                        objBalloons.Item(jj).BalloonTextSuffix = strTextStringToBeChecked
                    End If

                End If

            Next

            objDimensions = objSheet.Dimensions
            For jj = 1 To objDimensions.Count
                If objDimensions.Item(jj).OverrideString <> "" Then

                    strTextStringToBeChecked = objDimensions.Item(jj).OverrideString
                    ParseString()


                    If bolFlag Then
                        objBalloons.Item(jj).OverrideString = strTextStringToBeChecked

                    End If


                End If

                If objDimensions.Item(jj).PrefixString <> "" Then

                    strTextStringToBeChecked = objDimensions.Item(jj).PrefixString

                    ParseString()


                    If bolFlag Then
                        objDimensions.Item(jj).PrefixString = strTextStringToBeChecked
                    End If

                End If


                If objDimensions.Item(jj).SubfixString <> "" Then

                    strTextStringToBeChecked = objDimensions.Item(jj).SubfixString
                    intHorzJust = objDimensions.Item(jj).SubfixAlignment

                    ParseString()


                    If bolFlag Then
                        objDimensions.Item(jj).SubfixString = strTextStringToBeChecked
                        objDimensions.Item(jj).SubfixAlignment = intHorzJust

                    End If

                End If


                If objDimensions.Item(jj).SuffixString <> "" Then

                    strTextStringToBeChecked = objDimensions.Item(jj).SuffixString

                    ParseString()


                    If bolFlag Then
                        objDimensions.Item(jj).SuffixString = strTextStringToBeChecked
                    End If

                End If


                If objDimensions.Item(jj).SuperfixString <> "" Then

                    strTextStringToBeChecked = objDimensions.Item(jj).SuperfixString

                    ParseString()

                    If bolFlag Then
                        objDimensions.Item(jj).SuperfixString = strTextStringToBeChecked
                    End If

                End If

                If objDimensions.Item(jj).SubfixString2 <> "" Then

                    strTextStringToBeChecked = objDimensions.Item(jj).SubfixString2
                    intHorzJust = objDimensions.Item(jj).SubfixAlignment

                    ParseString()

                    If bolFlag Then
                        objDimensions.Item(jj).SubfixString2 = strTextStringToBeChecked
                        objDimensions.Item(jj).SubfixAlignment = intHorzJust
                    End If

                End If

            Next

        Catch ex As Exception

        End Try

        If Not (objTextboxes Is Nothing) Then
            Marshal.ReleaseComObject(objTextboxes)
            objTextboxes = Nothing
        End If


        If Not (objBalloons Is Nothing) Then
            Marshal.ReleaseComObject(objBalloons)
            objBalloons = Nothing
        End If


        If Not (objDimensions Is Nothing) Then
            Marshal.ReleaseComObject(objDimensions)
            objDimensions = Nothing
        End If

        Garbage_Collect(objTextboxes)
        Garbage_Collect(objBalloons)
        Garbage_Collect(objDimensions)

    End Function





    ' check the spelling of a word
    '
    ' returns True if the word is correct
    ' returns False if the word is not correct, and in this case it optionally
    ' returns a collection that contains all the suggested alternate words
    '
    ' NOTE: requires a reference to the Microsoft Word Object Library



    Function CheckSpelling(ByVal Word As String, ByRef suggestions As System.Collections.ArrayList) As Boolean
        Dim splSuggestion As Microsoft.Office.Interop.Word.SpellingSuggestion
        Dim splSuggestions As Microsoft.Office.Interop.Word.SpellingSuggestions

        ' Add a document, if there aren't any
        ' this is needed to get suggestions
        If MSWord.Documents.Count = 0 Then MSWord.Documents.Add()

        ' ensure there are no extra spaces
        Word = Trim$(Word)
        If MSWord.CheckSpelling(Word) Then

            ' the word is correct
            CheckSpelling = True
        Else
            ' the word is incorrect
            ' get the list of suggested words
            splSuggestions = MSWord.GetSpellingSuggestions(Word)
            For Each splSuggestion In splSuggestions
                suggestions.Add(splSuggestion.Name)
            Next
        End If

    End Function


    Public Function TextStringToSpellCheck(ByVal thing As String) As Boolean


        If Not CheckSpelling(strParsedString, suggestions) Then
            If SpellCheckForm Is Nothing Then
                SpellCheckForm = New DraftSpellChecker
                SpellCheckForm.ShowDialog()
            Else
                SpellCheckForm.ShowDialog()
            End If
        Else

        End If

    End Function



    Public Function PullSEPropertyFromFile(ByVal name As String) As String
        Dim objProperties As SolidEdgeFileProperties.Properties
        Dim objProperty As SolidEdgeFileProperties.Property
        Dim nstart As Integer
        Dim replacestart As Integer
        Dim replaceend As Integer
        Dim strTmpString As String
        Dim strFirstString As String
        Dim strSecondString As String
        Dim strMergedString As String

        CleanUpMemory()
        CleanUpMemory()
        PullSEPropertyFromFile = ""
        On Error Resume Next

        'Try

        propertySets = New SolidEdgeFileProperties.PropertySets
        propertySets.Open(name, False)
        For Each objProperties In propertySets
            objProperties.Name.ToString()
            For Each objProperty In objProperties
                If Trim(objProperty.Value) <> "" Then
                    strTextStringToBeChecked = CStr(objProperty.Value)
                    If Err.Number <> 0 Then
                        Err.Clear()
                        GoTo skip
                    End If

                    ' Insert subroutine to do repetitive processing
                    ParseString()

                    If bolFlag Then
                        objProperty.Value = strTextStringToBeChecked
                    End If

                End If
skip:
            Next
        Next

        propertySets.Save()

err:

        If Not (propertySets Is Nothing) Then
            Marshal.ReleaseComObject(propertySets)
            propertySets = Nothing
        End If

        Garbage_Collect(propertySets)

        strMergedString = ""
        strSecondString = ""
        strFirstString = ""
        replacestart = 0
        strParsedString = ""
        nstart = 0
        strTextStringCorrected = ""

        CleanUpMemory()

    End Function

    Public Function PullSEPropertyFromOpenedFile() As String
        Dim objProperties As Object
        Dim objProperty As Object
        Dim ii As Integer

        Dim nstart As Integer
        Dim replacestart As Integer
        Dim replaceend As Integer
        Dim strTmpString As String
        Dim strFirstString As String
        Dim strSecondString As String
        Dim strMergedString As String

        On Error Resume Next

        objProperties = objSEApp.ActiveDocument.Properties

        For Each objProperty In objProperties
            For ii = 1 To objProperty.count
                objProperty.item(ii).name.ToString()
                If Trim(objProperty.item(ii).value) <> "" Then
                    strTextStringToBeChecked = CStr(objProperty.item(ii).Value)
                    If Err.Number <> 0 Then
                        Err.Clear()
                        GoTo skip
                    End If

                    ' Insert subroutine to do repetitive processing
                    ParseString()


                    If bolFlag Then
                        objProperty.item(ii).Value = strTextStringToBeChecked
                    End If

                End If
skip:


            Next

        Next


        PullSEPropertyFromOpenedFile = ""


        If Not (objProperties Is Nothing) Then
            Marshal.ReleaseComObject(objProperties)
            objProperties = Nothing
        End If

        'objDraftDoc.UpdatePropertyTextDisplay()

        Garbage_Collect(objProperties)

        CleanUpMemory()

    End Function

    Sub Garbage_Collect(ByVal obj As Object)

        '******* Added because of .NET
        If Not (obj Is Nothing) Then
            Marshal.ReleaseComObject(obj)
        End If

        GC.Collect(GC.MaxGeneration)
        GC.WaitForPendingFinalizers()
        GC.Collect(GC.MaxGeneration)
        GC.WaitForPendingFinalizers()
        '******* Added because of .NET


    End Sub

    Public Function CleanUpMemory() As Boolean

        GC.Collect(GC.MaxGeneration)
        GC.WaitForPendingFinalizers()
        GC.Collect(GC.MaxGeneration)
        GC.WaitForPendingFinalizers()


    End Function


    Public Function GetAppPath() As String
        Dim mstrPath As String
        mstrPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetModules()(0).FullyQualifiedName)
        If Microsoft.VisualBasic.Right(mstrPath, 1) <> "\" Then
            mstrPath += "\"
        End If
        Return mstrPath
    End Function

    Public Sub ParseString()

        Dim nstart As Integer
        Dim replacestart As Integer
        Dim strTmpString As String
        Dim strFirstString As String
        Dim strSecondString As String
        Dim strMergedString As String
        Dim strChar As String
        Dim intChar As Integer
        Dim eol As Integer = 0
        Dim eolLF As Integer = 0
        Dim eolCR As Integer = 0
        Dim offset As Integer = 1
        Dim intWordLength As Integer
        Dim i As Integer
        Dim haveLF As Boolean = False
        Dim haveCR As Boolean = False
        Dim haveCRLF As Boolean = False
        Dim haveEOL As Boolean = False
        bolFlag = False

        ' Need to figure out how to handle CR LF combination like seen in file properties Comments.

        nstart = InStr(1, strTextStringToBeChecked, " ", CompareMethod.Text)
        ' if nstart = 0, then there are no "space" characters.  
        ' But there may still be a multi-line so have to check for eol

        EOLCheck(1, strTextStringToBeChecked, haveCR, haveLF, haveCRLF, haveEOL, eol, eolCR, eolLF)

        If nstart = 0 And haveEOL = False Then
            strParsedString = strTextStringToBeChecked
            strTextStringCorrected = ""
            TextStringToSpellCheck(strTextStringToBeChecked)

            'replace the misspelled word
            If strTextStringCorrected <> "" Then
                replacestart = InStr(strTextStringToBeChecked, strParsedString, CompareMethod.Text)
                strFirstString = Mid(strTextStringToBeChecked, offset, replacestart - 1)
                strSecondString = Mid(strTextStringToBeChecked, replacestart + Len(strParsedString), Len(strTextStringToBeChecked))
                strMergedString = strFirstString + strTextStringCorrected + strSecondString
                bolFlag = True
                strTextStringToBeChecked = strMergedString

            End If

        Else
            If nstart = 0 Then
                nstart = eol
                If eolLF = 1 Then nstart = nstart + 1
            End If
            strTmpString = strTextStringToBeChecked
            intWordLength = nstart - offset
            Do While nstart <> 0
                strParsedString = Mid(strTmpString, offset, nstart - offset)
                strParsedString = Mid(strTmpString, offset, intWordLength)
                strTmpString = Mid(strTmpString, nstart + 1, Len(strTextStringToBeChecked))
                strTextStringCorrected = ""
                TextStringToSpellCheck(strParsedString)
                'replace the misspelled word
                If strTextStringCorrected <> "" Then
                    replacestart = InStr(strTextStringToBeChecked, strParsedString, CompareMethod.Text)
                    strFirstString = Mid(strTextStringToBeChecked, 1, replacestart - 1)
                    strSecondString = Mid(strTextStringToBeChecked, replacestart + Len(strParsedString), Len(strTextStringToBeChecked))
                    strMergedString = strFirstString + strTextStringCorrected + strSecondString
                    strTextStringToBeChecked = strMergedString
                    bolFlag = True
                    For i = 0 To strSecondString.Length - 1
                        strChar = strSecondString.Substring(i, 1)
                        intChar = Asc(strChar)
                    Next
                    For i = 0 To strMergedString.Length - 1
                        strChar = strMergedString.Substring(i, 1)
                        intChar = Asc(strChar)
                    Next

                End If
                nstart = InStr(1, strTmpString, " ", CompareMethod.Text)
                If haveEOL = True Then EOLCheck(1, strTmpString, haveCR, haveLF, haveCRLF, haveEOL, eol, eolCR, eolLF)

                If nstart = 0 And haveEOL = False Then
                    strParsedString = strTmpString
                    strTextStringCorrected = ""
                    TextStringToSpellCheck(strParsedString)

                    'replace the misspelled word
                    If strTextStringCorrected <> "" Then
                        replacestart = InStr(strTextStringToBeChecked, strParsedString, CompareMethod.Text)
                        strFirstString = Mid(strTextStringToBeChecked, 1, replacestart - 1)
                        strSecondString = Mid(strTextStringToBeChecked, replacestart + Len(strParsedString), Len(strTextStringToBeChecked))
                        strMergedString = strFirstString + strTextStringCorrected + strSecondString
                        strTextStringToBeChecked = strMergedString
                        bolFlag = True
                    End If
                Else
                    ' need to figure out if the next char is an eol or if there is another word terminated by an eof
                    If nstart = 0 Or (nstart > eol And haveEOL = True) Then
                        If eol = 1 Then
                            nstart = InStr(2, strTmpString, " ", CompareMethod.Text)
                            EOLCheck(2, strTmpString, haveCR, haveLF, haveCRLF, haveEOL, eol, eolCR, eolLF)
                            offset = 2
                            nstart = eol
                            intWordLength = eol - offset
                        Else
                            nstart = eol
                            offset = 1
                            intWordLength = eol - 1
                        End If
                        If eolLF = 1 Then
                            nstart = nstart + 1
                        End If
                    Else
                        offset = 1
                        intWordLength = nstart - offset
                    End If
                End If
                strTextStringCorrected = ""
            Loop
        End If

        strMergedString = ""
        strSecondString = ""
        strFirstString = ""
        replacestart = 0
        strParsedString = ""
        nstart = 0
        strTextStringCorrected = ""

    End Sub

    Sub EOLCheck(ByVal ptrStart, ByVal strCheck, ByRef havecr, ByRef havelf, ByRef havecrlf, ByRef haveeol, ByRef eol, ByRef eolcr, ByRef eollf)
        Dim strCR As String = Chr(13)
        Dim strLF As String = Chr(10)
        Dim strCRLF As String
        'Dim strChar As String
        'Dim intChar As Integer

        strCRLF = strCR & strLF
        eol = 0
        haveeol = False

        ' used strictly for debuggibg when required.
        'For i = 0 To strCheck.Length - 1
        '    strChar = strCheck.Substring(i, 1)
        '    intChar = Asc(strChar)
        'Next

        If InStr(ptrStart, strCheck, strCR, CompareMethod.Text) < strCheck.Length And InStr(ptrStart, strCheck, strCR, CompareMethod.Text) > 0 Then
            havecr = True
            eolcr = InStr(ptrStart, strCheck, strCR, CompareMethod.Text)
        Else
            havecr = False
            eolcr = 0
        End If
        If InStr(ptrStart, strCheck, strLF, CompareMethod.Text) < strCheck.Length And InStr(ptrStart, strCheck, strLF, CompareMethod.Text) > 0 Then
            havelf = True
            eollf = InStr(ptrStart, strCheck, strLF, CompareMethod.Text)
        Else
            havelf = False
            eollf = 0
        End If
        If havecr = True And havelf = True Then
            If eolcr + 1 = eollf Then
                havecrlf = True
            Else
                havecrlf = False
            End If
        Else
            havecrlf = False
        End If

        If havecr = True Or havelf = True Or havecrlf = True Then
            haveeol = True
            If havecr = True And havelf = False Then eol = eolcr
            If havecr = False And havelf = True Then eol = eollf
            If havecrlf = True Then
                eol = eolcr
                eollf = 1
            ElseIf havecr = True And havelf = True Then
                If eolcr < eollf Then
                    eol = eolcr
                Else
                    eol = eollf
                End If
            End If
        End If

    End Sub
End Module
