Text-Editor

Veröffentliche deine funktionierenden Skripte und Funktionen

Moderator: jNizM

User avatar
Holle
Posts: 187
Joined: 01 Oct 2013, 23:19

Text-Editor

09 Apr 2014, 11:16

Hallo,
ich habe einen Text-Editor geschrieben. Es ist nichts besonderes, aber zumindest kann er folgendes:

-Suchen
-Ersetzen
-RegEx-Suchen
-Case Sensitive-Unterstützung
-Rückgängig machen
-Datei-Kodierung ändern
-Anzeige von Zeile/Spalte/Zeichen

Special thanks to "just me", deine Funktionen waren mir dabei eine große Hilfe!

Bitte postet Lob/Kritik/BugReport/Verbesserungsvorschläge. Vielen Dank.

Eine Verbesserung fällt mir selber schon spontan ein (bin aber zu faul das umzusetzen ;) ...diese habe ich direkt am Anfang als Kommentar mit eingefügt.

So, hier ist das Script:

Code: Select all

; Was man verbessern könnte...
;
; Statt das ganze Script zu speichern (für Rückgängig) reicht es aus die geänderten Zeichen zu speichern (
; Beispiel: 10. Änderung: Ersetze zeichen 300-302 ("bei") durch "in der Nähe von"  
;           --> Inhalt.10 := "300|15|bei" (von Zeichen "300" an "15" Zeichen durch "bei" ersetzen)
;           --> Inhalt.10 := CursorPos "|" StrLen(Ersetzen) "|" gefunden1 (CaseSensitive beachten!)
;

#Include Holles_Lib.ahk
OnExit, Exit
Bildbreite := A_ScreenWidth/(A_ScreenDPI/96)-14
Bildhoehe := A_ScreenHeight/(A_ScreenDPI/96)-74

CreateGui:
{
    FontSize := Round(BildHoehe/65.83)
    Gui,Main:Font,S%FontSize% cDefault,arial
    x := Round(Bildbreite/152.2),y:= Round(Bildhoehe/52.67),w := Round(Bildbreite/30.44),h := Round(Bildhoehe/26.33)
    Gui,Main:add,Text,x%x% y%y% w%w% h%h%,Datei:
    x := Round(Bildbreite/25.37),y:= Round(Bildhoehe/79),breite := Bildbreite-Round(Bildbreite/21.74)
    Gui,Main:add,Button,x%x% y%y% w%breite% hp gSelectFile vSelectFile,Bitte eine Textdatei auswählen...
    x := Round(Bildbreite/152.2),y:= Round(Bildhoehe/13.17),w := Round(Bildbreite/15.22),h := Round(Bildhoehe/39.5)
    Gui,Main:add,Text,x%x% y%y% w%w% h%h%,Suchen nach:
    y:= Round(Bildhoehe/8.78)
    Gui,Main:add,Text,xp y%y% wp hp,Ersetzen mit:   
    x := Round(Bildbreite/13.84),y:= Round(Bildhoehe/13.86),w := Round(Bildbreite/5.07)
    Gui,Main:add,Edit,x%x% y%y% w%w% vSuchen gEditSuchen Disabled
    y:= Round(Bildhoehe/9.08)
    Gui,Main:add,Edit,xp y%y% wp vErsetzen gEditErsetzen Disabled
    x := Round(Bildbreite/3.624),y:= Round(Bildhoehe/13.86),w := Round(Bildbreite/15.22),h := Round(Bildhoehe/14.11)
    ,xp := Round(Bildbreite/13.836)
    Gui,Main:add,Button,x%x% y%y% w%w% h%h% vButtonSuchen Disabled,Suchen
    Gui,Main:add,Button,xp+%xp% yp wp hp vButtonErsetzen Disabled,Ersetzen
    Gui,Main:add,Button,xp+%xp% yp wp hp vButtonAllesErsetzen Disabled,Alles Ersetzen
    Gui,Main:add,Button,xp+%xp% yp wp hp vUndo Disabled,Rückgängig
    Gui,Main:add,Button,xp+%xp% yp wp hp vSave Disabled,Speichern
    Gui,Main:add,Button,xp+%xp% yp wp hp vSaveTo Disabled,Speichern unter
    Gui,Main:add,Button,xp+%xp% yp wp hp vCodePage gKodierung Disabled, Kodierung
    x := Round(Bildbreite/13.84) , xp := 50+round((Bildbreite-600)/18.44)
    Gui,Main:add,Checkbox,x%x% y+8  vCS gCheckboxen,A != a
    Gui,Main:add,Checkbox,xp+%xp% yp  vRegexSuche gCheckboxen TabStop,RegEx
    Gui,Main:add,Checkbox,xp+%xp% yp  vRueckwaerts gCheckboxen,Rückwärts
    x := Round(Bildbreite/25.37),y:= Round(Bildhoehe/5.267) 
    , ZeilenAnzahl := floor((Bildhoehe-(Bildhoehe/4.247))/(FontSize*1.542)),hoehe := Round(ZeilenAnzahl*(FontSize*1.542)+6)
    Gui,Main:add,Edit,x%x% y%y% w%breite% h%hoehe% vEdit gEdit hwndhEdit +0x100 WantTab -Tabstop Disabled
    y := Round(Bildhoehe/5.032+hoehe),w := Round(Bildbreite/10.15),xp := Round(Bildbreite/10.147)
    Gui,Main:add,Text,xp y%y% w%w% vEditZeile,Zeile:
    Gui,Main:add,Text,xp+%xp% yp wp vEditSpalte,Spalte:
    Gui,Main:add,Text,xp+%xp% yp wp vEditZeichen,Zeichen:
    Gui,Main:Font,S%FontSize% cGray,arial    
    x:= Round(Bildbreite/152.2),y := Round(Bildhoehe/5.163),w := Round(Bildbreite/33.82),hoehe -= 6
    Gui,Main:Add,Text,x%x% y%y% w%w% Right h%hoehe% vShowRow -VScroll
    Gui,Main:show,w%Bildbreite% h%Bildhoehe%,Simple Text-Editor
}
CreateGuiKodierung:
{
    Gui,Kodierung:+OwnerMain +AlwaysOnTop
    Gui,Kodierung:Font,S12 cDefault,arial
    Gui,Kodierung:add,GroupBox, x10 y10 w180 h115,Kodierung
    Gui,Kodierung:add,Radio, x20 y40 vRadioUTF8 gKodierungRadio Group,UTF-8
    Gui,Kodierung:add,Radio, x20 y65 vRadioUTF16 gKodierungRadio,UTF-16
    Gui,Kodierung:add,Radio, x20 y90 vRadioCP gKodierungRadio,CP
    Gui,Kodierung:add,Edit, x65 y87 w100 vCpNummer Disabled,
    Gui,Kodierung:add,Button,x80 w40,OK
}

EditSubClassCallback := RegisterCallback("EditSubclassProc") ; für eine Event-Message wenn gescrollt wird
DllCall("Comctl32.dll\SetWindowSubclass", "Ptr", hEdit, "Ptr", EditSubClassCallback, "Ptr", eHedit, "Ptr", 0)
return
;################################## Autostart Ende ##################################

MainGuiClose:
ExitApp

WindowsMessage:
    WindowsMessage()
return

WindowsMessage() {
    global ZeilenAnzahl,hEdit,FileName
    if !FileName ; Keine Text-Datei ausgewählt
        return
    sleep 1
    ControlGet,CursorZeile,CurrentLine,,Edit3,A    
    ControlGet,CursorSpalte,CurrentCol,,Edit3,A
    GuiControlGet,EditZeile,Main:
    EditZeile := RegExReplace(EditZeile,"\D*")
    if (EditZeile != CursorZeile)
        GuiControl,Main:,EditZeile,Zeile: %CursorZeile%
    GuiControlGet,EditSpalte,Main:
    EditSpalte := RegExReplace(EditSpalte,"\D*")
    if (EditSpalte != CursorSpalte)
        GuiControl,Main:,EditSpalte,Spalte: %CursorSpalte%
    GuiControlGet,EditZeichen,Main:
    EditZeichen := RegExReplace(EditZeichen,"\D*")
    CursorPos := 0
    Loop,%CursorZeile% {
        ControlGet,Zeile,Line,%A_Index%,Edit3,A
        CursorPos += (A_Index!=CursorZeile)?StrLen(Zeile)+!RegExMatch(zeile,"\s$"):CursorSpalte
    }
    if (EditZeichen != CursorPos)
        GuiControl,Main:,EditZeichen,Zeichen: %CursorPos%
    gosub RefreshShowRow
return
}

RefreshShowRow:
{
    ShowRowBegin := RegExReplace(ShowRow,"`n.*")
    if (ShowRowbegin = EM_GETFIRSTVISIBLELINE(hEdit))
        return
    ShowRow := ""
    loop,%ZeilenAnzahl%
        ShowRow .= "`n" a_index + EM_GETFIRSTVISIBLELINE(hEdit) -1
    StringTrimLeft,ShowRow,ShowRow,1
    GuiControl,Main:,ShowRow,%ShowRow%  
return
}

Edit:
{
    GuiControlGet, Edit, Main:
    if !(StrReplace(Edit,"`r`n,`n") == Inhalt[Inhalt.Index]) {
        Inhalt.Index += 1,Inhalt[Inhalt.Index] := StrReplace(Edit,"`r`n,`n")
        GuiControl, Main:-Disabled, Undo
        GuiControl, Main:-Disabled, Save
    }
    ControlGet,CursorZeile,CurrentLine,,Edit3,A   
    if (EditZeile != CursorZeile) {
        GuiControl,Main:,EditZeile,Zeile: %CursorZeile%
        gosub RefreshShowRow
    }
    ControlGet,CursorSpalte,CurrentCol,,Edit3,A
    if (EditSpalte != CursorSpalte)
        GuiControl,Main:,EditSpalte,Spalte: %CursorSpalte%
    CursorPos := 0
    Loop,%CursorZeile% {
        ControlGet,Zeile,Line,%A_Index%,Edit3,A
        CursorPos += (A_Index!=CursorZeile)?StrLen(Zeile)+!RegExMatch(zeile,"\s$"):CursorSpalte
    }
    if (EditZeichen != CursorPos)
        GuiControl,Main:,EditZeichen,Zeichen: %CursorPos%
    if (Inhalt.index = 0) {
        GuiControl,Main:Disable,Undo
        if (Kodierung_Original == Kodierung)
            GuiControl,Main:Disable,Save
    }
return
}

Checkboxen:
EditSuchen:
EditErsetzen:
{
    GuiControlGet,Suchen,Main:
    If Suchen||(Suchen="0") {
        GuiControl,Main:-Disabled,ButtonSuchen
        GuiControl,Main:-Disabled,ButtonErsetzen
        GuiControl,Main:-Disabled,ButtonAllesErsetzen
    }
    else {
        GuiControl,Main:Disable,ButtonSuchen
        GuiControl,Main:Disable,ButtonErsetzen
        GuiControl,Main:Disable,ButtonAllesErsetzen
    }
    StartPos := CursorPos?(FundPos:=CursorPos):(FundPos:=FundPosVorher)+1
    gosub MainButtonSuchen ; Live-Suche
return
}

MainButtonSuchen:
MainButtonErsetzen:
MainButtonAllesErsetzen:
{
    FundPosVorher := FundPos,gefunden := ""
    ControlGet,CursorZeile,CurrentLine,,Edit3,A
    ControlGet,CursorSpalte,CurrentCol,,Edit3,A
    if !StartPos
        Loop,%CursorZeile% {
            ControlGet,Zeile,Line,%A_Index%,Edit3,A
            StartPos := (A_Index!=CursorZeile)?StrLen(Zeile)+!RegExMatch(zeile,"\s$"):CursorSpalte
        }        
    GuiControlGet,Suchen,Main:
    if !Suchen&&(Suchen!="0") {
        markiert := ""
        EM_SETSEL(hEdit,CursorPos,CursorPos)
        ControlGet,CursorZeile,CurrentLine,,Edit3,A
        ControlGet,CursorSpalte,CurrentCol,,Edit3,A
        EM_LINESCROLL(hEdit,CursorZeile-EM_GETFIRSTVISIBLELINE(hEdit)-ZeilenAnzahl/2)
        return
    }
    GuiControlGet,Edit,Main:
    StringReplace,Edit,Edit,`n,`r`n,All
    GuiControlGet,Ersetzen,Main:
    GuiControlGet,CS,Main:
    GuiControlGet,RegexSuche,Main:
    GuiControlGet,Rueckwaerts,Main:
    Rueckwaerts := (A_ThisHotkey="+F3")?!Rueckwaerts:Rueckwaerts
    if RegexSuche {
        if Rueckwaerts {
            FundPos := StartPos-1-StrLen(RegExReplace(SubStr(Edit,1,StartPos-2),CS?"s).*(" suchen ")":"is).*(" suchen ")","$1"))
            RegExMatch(Edit,CS?"s)(" suchen ")":"is)(" suchen ")",gefunden,FundPos)
            FundPos := FundPos=1?RegExMatch(Edit,CS?"^(" suchen ")":"i)^(" suchen ")"):FundPos
            If !FundPos||(StartPos<=2)
                StartPos := StrLen(Edit)+1
                , FundPos := StartPos-1-StrLen(RegExReplace(SubStr(Edit,1,StartPos-2),CS?"s).*(" suchen ")":"is).*(" suchen ")","$1"))
                , FundPos := FundPos=1?RegExMatch(Edit,CS?"^(" suchen ")":"i)^(" suchen ")"):FundPos
                , RegExMatch(Edit,CS?"s)(" suchen ")":"is)(" suchen ")",gefunden,FundPos)
        }
        else {
            FundPos := RegExMatch(Edit,CS?"s)(" suchen ")":"is)(" suchen ")",gefunden,StartPos)
            If !FundPos
                StartPos := 1 , FundPos := RegExMatch(Edit,CS?"s)(" suchen ")":"is)(" suchen ")",gefunden,StartPos)
        }
    }
    else {
        FundPos := InStr(Edit,Suchen,CS,Rueckwaerts?StartPos-2-StrLen(Edit):StartPos)
        If !FundPos
            StartPos := Rueckwaerts?StrLen(Edit):1 
            , FundPos := InStr(Edit,Suchen,CS,Rueckwaerts?StartPos-2-StrLen(Edit):StartPos)
    }
    if (A_GuiControl="Suchen")||(A_GuiControl="ButtonSuchen")||(A_GuiControl="CS")||(A_GuiControl="RegexSuche")||(A_ThisHotkey="F3")||(A_ThisHotkey="+F3") {
        EM_SETSEL(hEdit,FundPos,FundPos+(RegexSuche?StrLen(gefunden1):StrLen(Suchen)))
        ControlGet,CursorZeile,CurrentLine,,Edit3,A
        ControlGet,CursorSpalte,CurrentCol,,Edit3,A
        EM_LINESCROLL(hEdit,CursorZeile-EM_GETFIRSTVISIBLELINE(hEdit)-ZeilenAnzahl/2)
        StartPos := FundPos+1,markiert := FundPos ; um beim ersetzen zuerst den markierten Eintrag zu ersetzen
    }
    else if FundPos&&((A_GuiControl="ButtonErsetzen")||(A_GuiControl="ButtonAllesErsetzen")) {
        Inhalt.Index += 1,Inhalt[Inhalt.Index] := Inhalt[Inhalt.Index-1]
        if markiert
            FundPos := markiert,markiert := ""
        if (A_GuiControl="ButtonErsetzen")
            Inhalt[Inhalt.Index] := StrLeft(Edit,FundPos-1) Ersetzen StrTrimLeft(Edit,FundPos+StrLen(Suchen)-1)
        else if (A_GuiControl="ButtonAllesErsetzen") {
            if !RegexSuche
                Inhalt[Inhalt.Index] := StrReplace(Edit,RegExReplace(Suchen,",","\,") "," RegExReplace(Ersetzen,",","\,"),CS?1:0)
                , FundPos := StrLen(Inhalt[Inhalt.Index])-(StrLen(Edit)-InStr(Edit,Suchen,CS,0))+StrLen(suchen)-StrLen(Ersetzen)
            else
                Inhalt[Inhalt.Index] := RegExReplace(Edit,CS?Suchen:"i)" suchen,Ersetzen) ; Ersetzen
                , RegExMatch(Edit,CS?"s).*(" suchen ")":"is).*(" suchen ")",gefunden) ; letzten Treffer im "Klartext"
                , FundPos := gefunden1?StrLen(Inhalt[Inhalt.Index])-(StrLen(Edit)-InStr(Edit,gefunden1,CS,0))+StrLen(gefunden1)-StrLen(Ersetzen):0 ; ...um den den letzten Treffer zu markieren
        }
        if (Inhalt[Inhalt.Index] == Inhalt[Inhalt.Index-1]) {
            Inhalt[Inhalt.Index] := "",Inhalt.Index -= 1
            return
        }
        StartPos := FundPos+StrLen(Ersetzen)
        GuiControl,Main:-Disabled,Undo
        GuiControl,Main:,Edit,% Inhalt[Inhalt.Index]
        GuiControl,Main:-Disabled,Save
        EM_SETSEL(hEdit,FundPos,FundPos+StrLen(Ersetzen))
        ControlGet,CursorZeile,CurrentLine,,Edit3,A
        ControlGet,CursorSpalte,CurrentCol,,Edit3,A
        EM_LINESCROLL(hEdit,CursorZeile-EM_GETFIRSTVISIBLELINE(hEdit)-ZeilenAnzahl/2)
    }
    Gosub RefreshShowRow
return
}

MainButtonRückgängig:
{
    Inhalt[Inahlt.index] := "",Inhalt.index -= 1
    GuiControl,Main:,Edit,% Inhalt[Inhalt.Index]
    if (Inhalt.index = 0) {
        GuiControl,Main:Disable,Undo
        if (Kodierung_Original==Kodierung)
            GuiControl,Main:Disable,Save
    }
    StartPos := 0
    GuiControlGet,Edit,Main:
    Inhalt.0 := gespeichert?StrReplace(Inhalt[gespeichert],"`r`n,`n"):Inhalt.0
    if Inhalt.0&&!(Inhalt.0==Edit)
        GuiControl, Main:-Disabled,Save
return
}

MainButtonSpeichern:
MainButtonSpeichernUnter:
{
    Ueberschreiben := False
    if ((A_GuiControl="SelectFile")||!A_GuiControl)&&MsgBox("Sollen die Datei " FileName " überschrieben werden?","Überschreiben?",262180) = "YES" ; Neue Datei gewählt, oder Exit
        Ueberschreiben := True
    if (A_GuiControl="Save")||(Ueberschreiben=True) { ; Überschreiben
        FileDelete,%FileName%
        FileAppend,% Inhalt[Inhalt.Index],%FileName%,%Kodierung%
    }
    else { ; Speichern unter
        FileSelectFile,NewFileName,S24,,Speichern unter...
        If !NewFileName
            return
        SplitPath,NewFileName,FileName
        FileAppend,% Inhalt[Inhalt.Index],%FileName%,%Kodierung%
        GuiControl,Main:,SelectFile,%FileName%
    }
    gespeichert := Inhalt.Index
    GuiControl,Main:Disable,Save
    FadeText("Erfolgreich gespeichert!")
return
}

SelectFile:
{
    Gui +OwnDialogs 
    GuiControlGet,Edit,Main:
    Inhalt.0 := gespeichert?StrReplace(Inhalt[gespeichert],"`r`n,`n"):Inhalt.0
    if Inhalt.0&&!(Inhalt.0==Edit)
        if MsgBox("Sollen die Änderung in " FileName " gespeichert werden?","Änderungen speichern?",262180)="YES"
            Gosub MainButtonSpeichern
    Inhalt := Object()
    GuiControl,Main:Disable,Suchen
    GuiControl,Main:,Suchen,
    GuiControl,Main:Disable,Ersetzen
    GuiControl,Main:,Ersetzen,
    GuiControl,Main:Disable,ButtonSuchen
    GuiControl,Main:Disable,ButtonErsetzen
    GuiControl,Main:Disable,ButtonAllesErsetzen
    GuiControl,Main:Disable,Undo
    GuiControl,Main:Disable,Save
    GuiControl,Main:Disable,SaveTo
    GuiControl,Main:Disable,CodePage
    GuiControl,Main:,CodePage,Kodierung
    GuiControl,Kodierung:,CpNummer  
    GuiControl,Main:,Edit,
    GuiControl,Main:,ShowRow,
    GuiControl,Main:Disable,Edit
    IniRead, LastFile,SimpleEditor.ini,Options,LastFile,%A_Space%
    FileSelectFile,FileName,3,%LastFile%,Textdatei auswählen
    If !(Kodierung := IsTextFile(FileName)) {
        GuiControl,Main:,SelectFile,Bitte eine Textdatei auswählen...        
        if FileName
            MsgBox("Die gewählte Datei ist keine Textdatei!","Fehler",262160)
        FileName = ""
        return
    }
    IniWrite,%FileName%,SimpleEditor.ini,Options,LastFile
    Kodierung_Original := Kodierung := (Kodierung="CP65001")?"UTF-8":(Kodierung="CP1200")?"UTF-16":Kodierung
    GuiControl,Main:,CodePage,% Kodierung
    GuiControl,Main:-Disabled, CodePage
    SplitPath,FileName,FileName
    GuiControl,Main:,SelectFile,%FileName%
    FileRead,temp,%FileName%
    CursorPos:=1,ShowRow:="",Inhalt.0:=StrReplace(temp,"`r`n,`n"),temp:="",Inhalt.Index:=0 ; Inhalt.0 ist der Originalzustand
    GuiControl,Main:,Edit,% Inhalt.0
    GuiControl,Main:-Disabled,Suchen
    GuiControl,Main:,Suchen,
    GuiControl,Main:-Disabled,Ersetzen
    GuiControl,Main:,Ersetzen,
    GuiControl,Main:-Disabled,SaveTo
    GuiControl,Main:-Disabled,Edit
    GuiControl,Main:+Default,ButtonSuchen
    Loop,%ZeilenAnzahl%
        ShowRow .= "`n" a_index
    StringTrimLeft,ShowRow,ShowRow,1
    GuiControl,Main:,ShowRow,%ShowRow%
return
}

Kodierung:
{
    RadioAuswahl := "Radio" StrReplace(Kodierung,"-,")
    if (SubStr(Kodierung,1,2)="CP") {
        RadioAuswahl := "RadioCP"
        GuiControl,Kodierung:-Disabled,CpNummer
        GuiControl,Kodierung:,CpNummer,% StrTrimLeft(Kodierung,2)
    }
    else
        GuiControl,Kodierung:Disable,CpNummer
    GuiControl,Kodierung:,%RadioAuswahl%,1
    Gui,Main:+Disabled
    Gui,Kodierung:show,w200,Kodierung   
return
}

KodierungRadio:
{
    GuiControlGet,RadioCP,Kodierung:
    if RadioCP
        GuiControl,Kodierung:-Disabled,CpNummer
    else
        GuiControl,Kodierung:Disable,CpNummer
return 
}

KodierungGuiClose:
{
    Gui,Main:-Disabled
    Gui,Kodierung:Hide
return
}

KodierungButtonOK:
{
    Gui,Main:-Disabled
    GuiControlGet,RadioCP,Kodierung:
    if RadioCP {
        GuiControlGet,RadioCP,Kodierung:
        GuiControlGet,CpNummer,Kodierung:
        if !IsIn(CpNummer, "037,437,500,708,709,710,720,737,775,850,852,855,857,858,860,861,862,863,864,865,866,869,870,874,875,932,936,949,950,1026,1047,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1200,1201,1250,1251,1252,1253,1254,1255,1256,1257,1258,1361,10000,10001,10002,10003,10004,10005,10006,10007,10008,10010,10017,10021,10029,10079,10081,10082,12000,12001,20000,20001,20002,20003,20004,20005,20105,20106,20107,20108,20127,20261,20269,20273,20277,20280,20284,20285,20290,20297,20420,20423,20424,20833,20838,20866,20871,20880,20905,20924,20932,20936,20949,21025,21027,28591,28591,28593,28594,28595,28596,28597,28598,28599,28603,28605,29001,38598,50220,50221,50222,50225,50227,50930,50931,50933,50935,50936,50937,50939,51932,51936,51949,51950,52936,54936,57002,57003,57004,57005,57006,57007,57008,57009,57010,57011,65000,65001")
            Exit MsgBox("Unbekannte Code-Page!`nDie Kodierung " Kodierung " bleibt bestehen.","Fehler",262160)
        Kodierung := "CP" CpNummer
    }
    else {
        GuiControlGet,RadioUTF8,Kodierung:
        Kodierung := RadioUTF8?"UTF-8":"UTF-16"
    }
    GuiControl,Main:,CodePage,% Kodierung
    if (Kodierung != Kodierung_Original)
        GuiControl,Main:-Disabled,Save
    else {
        GuiControlGet, Edit,Main:
        if (StrReplace(Edit,"`r`n,`n")==Inhalt[Inhalt.Index])
            GuiControl,Main:Disable,Save
    }
    Gui,Kodierung:Hide
return
}

Exit:
{
    if FinalExit
        ExitApp
    Gui +OwnDialogs 
    GuiControlGet,Edit,Main:
    Inhalt.0 := gespeichert?StrReplace(Inhalt[gespeichert],"`r`n,`n"):Inhalt.0
    if Inhalt.0&&!(Inhalt.0==Edit)
        if MsgBox("Sollen die Änderung in " FileName " gespeichert werden?","Änderungen speichern?",262180)="YES" {
            Gosub MainButtonSpeichern
            FinalExit := true            
            SetTimer,Exit,-2000
            return
        }
    Inhalt := ""
ExitApp
}

F3::
+F3::
{
    gosub MainButtonSuchen
return
}
~PGUP::
~PGDN::
{
    ControlGetFocus, focus, A
    if (focus = "Edit3") {
        ControlGet,CursorZeile,CurrentLine,,Edit3,A
        EM_LINESCROLL(hEdit,CursorZeile-EM_GETFIRSTVISIBLELINE(hEdit))
        WindowsMessage()
    }
return
}
Up::
Down::
Left::
Right::
{
    ControlGetFocus,focus,A
    if (focus = "Edit3") {
        ControlGet,CursorZeile,CurrentLine,,Edit3,A
        EM_LINESCROLL(hEdit,CursorZeile-EM_GETFIRSTVISIBLELINE(hEdit))
        send {%A_ThisHotkey%}
        WindowsMessage()
    }
    else if ((focus="Edit1")||(focus="Edit2"))&&((A_ThisHotkey="Left")||(A_ThisHotkey="Right"))
        send {%A_ThisHotkey%}
return
}
~LButton::
{
    if !FileName ; Keine Text-Datei ausgewählt
        return
    ControlGetFocus,focus,A ; vorheriges Focus
    MouseGetPos,,,id,control ; angeklicktes control
    if (Control="Edit3") {
        sleep 1
        if (focus!="Edit3")&&markiert
            SendMessage,0xB1,FundPos-1,FundPos+StrLen(Suchen)-1,,ahk_id %hEdit% ; 0xB1 ist EM_SETSEL
        ControlGet,CursorZeile,CurrentLine,,Edit3,A    
        ControlGet,CursorSpalte,CurrentCol,,Edit3,A
        GuiControl,Main:,EditZeile,Zeile: %CursorZeile%
        GuiControl,Main:,EditSpalte,Spalte: %CursorSpalte%
        gosub RefreshShowRow  
        CursorPos := 0
        Loop,%CursorZeile% {
            ControlGet,Zeile,Line,%A_Index%,Edit3,A
            CursorPos += (A_Index!=CursorZeile)?StrLen(Zeile)+!RegExMatch(zeile,"\s$"):CursorSpalte
        }
        StartPos := CursorPos := CursorPos?CursorPos:1      
        GuiControl,Main:,EditZeichen,Zeichen: %CursorPos%
    }
    else {
        GuiControl,Main:,EditZeile,Zeile: 
        GuiControl,Main:,EditSpalte,Spalte: 
        GuiControl,Main:,EditZeichen,Zeichen:
    }
return
}

; functions from "just me" ...
EM_GETFIRSTVISIBLELINE(HWND) {
   ; EM_GETFIRSTVISIBLELINE = 0x00CE -> msdn.microsoft.com/en-us/library/bb761574(v=vs.85).aspx
   Return (DllCall("User32.dll\SendMessage", "Ptr", HWND, "UInt", 0x00CE, "Ptr", 0, "Ptr", 0, "Ptr") + 1)
}
EM_LINESCROLL(HWND, Lines, Chars := 0) {
   ; EM_LINESCROLL = 0x00B6 -> msdn.microsoft.com/en-us/library/bb761615(v=vs.85).aspx
   Return DllCall("User32.dll\SendMessage", "Ptr", HWND, "UInt", 0x00B6, "Ptr", Chars, "Ptr", Lines, "Ptr")
}
EM_SETSEL(HWND, Start, End) {
   ; EM_SETSEL = 0x00B1 -> msdn.microsoft.com/en-us/library/bb761661(v=vs.85).aspx
   Return DllCall("User32.dll\SendMessage", "Ptr", HWND, "UInt", 0x00B1, "Ptr", Start - 1, "Ptr", End - 1, "Ptr")
}
EditSubclassProc(hWnd, uMsg, wParam, lParam, uIDSubclass, dwRefData) {
   Static SB := {4: "THUMBPOSITON", 5: "THUMBTRACK"}
   If (uMsg = 522) || ((uMsg = 277) & SB.HasKey(wParam & 0xFFFF))
        SetTimer, WindowsMessage, -1
    Return DllCall("Comctl32.dll\DefSubclassProc", "Ptr", hWnd, "UInt", uMsg, "Ptr", wParam, "Ptr", lParam)
}
Die benötigte Lib findet ihr hier: Holles_Lib.ahk

Letzte Änderung: Die zuletzt geöffnete Datei wird bei der Dateiauswahl "voreingestellt"
Last edited by Holle on 10 Apr 2014, 04:10, edited 3 times in total.
Johnny R
Posts: 348
Joined: 03 Oct 2013, 02:07

Re: Text-Editor

09 Apr 2014, 15:01

Und wo hat der Osterhase Holles_Lib.ahk versteckt?
User avatar
Holle
Posts: 187
Joined: 01 Oct 2013, 23:19

Re: Text-Editor

09 Apr 2014, 15:57

Verdammt, ich wusste doch dass ich was vergessen habe ;-)
Bin gerade per Handy on, lade die Lib dann morgen hoch. Sorry!

Edit: So, habe die Lib in einen eigenen Thread gepostet. Der Link ist im ersten Beitrag (ganz unten) hinzugefügt.
Johnny R
Posts: 348
Joined: 03 Oct 2013, 02:07

Re: Text-Editor

10 Apr 2014, 06:05

Haut bei mir (AHK 1.1.14.03 A32; Win7 SP1) leider nicht hin. Wenn ich eine Datei lade, bleibt der Editor leer. Die Datei wird zwar in der Ladeleiste aber nicht im Editor angezeigt.

#NoEnv wurde im Skript ergänzt.
User avatar
Holle
Posts: 187
Joined: 01 Oct 2013, 23:19

Re: Text-Editor

10 Apr 2014, 08:06

Komisch, ich nutze Version 1.1.13.01 (über Scite4AutoHotkey) auf einem Win7 (64 Bit SP1)-Notebook und bekomme keinen Fehler.

Kommt irgendeine Fehlermeldung?

Edit: Habe gerade ein Update auf 1.1.14.04 (32 Bit Unicode) gemacht, klappt immer noch wunderbar.
aaffe
Posts: 192
Joined: 16 Jan 2014, 04:23

Re: Text-Editor

27 Oct 2014, 01:58

Johnny R wrote:Haut bei mir (AHK 1.1.14.03 A32; Win7 SP1) leider nicht hin. Wenn ich eine Datei lade, bleibt der Editor leer. Die Datei wird zwar in der Ladeleiste aber nicht im Editor angezeigt.

#NoEnv wurde im Skript ergänzt.
Bei mir das gleiche. AHK 1.1.16.05, UTF-8, Windows 8.1
Öffne ich eine DAtei im Editor, steht in der ersten Zeile des Inhalts immer nur:
C:\Users\<MeinName>\AppData\Local\Temp
garry
Posts: 3750
Joined: 22 Dec 2013, 12:50

Re: Text-Editor

04 Jul 2015, 01:34

Hallo Holle , gefällt mir gut
eine Frage betr. Cursor :
- ich möchte in ini-file letzte Text-Datei speichern mit Position von Cursor ( Zeile / Spalte bzw. Zeichen ( ist im script schon vorhanden ) )
und der Cursor sollte bei Start ( if file exist ) hierher springen / scrollen .
garry
Posts: 3750
Joined: 22 Dec 2013, 12:50

Re: Text-Editor

30 Jul 2015, 07:04

habe jetzt das gleiche Problem wie user aaffe
und möchte noch beim Oeffnen dass der cursor auf die position springt wo ich zuletzt war ( speichert File und Cursor-Position )
User avatar
Gerdi
Posts: 185
Joined: 03 Aug 2015, 18:48
Location: Germany
Contact:

Re: Text-Editor

03 Aug 2015, 19:02

wenn ich Dateien auserhalb von A_ScriptDir öffne ist es wie bei aaffe
Bei mir das gleiche. AHK 1.1.16.05, UTF-8, Windows 8.1
Öffne ich eine DAtei im Editor, steht in der ersten Zeile des Inhalts immer nur:
C:\Users\<MeinName>\AppData\Local\Temp
Wenn ich Dateien im Skriptverzeichnis öffne sieht alles OK aus

Gerdi
Win 10 Home (x64) and Win 11 Pro N
https://github.com/Grrdi/ZackZackOrdner/archive/master.zip --> get folders on the quick
User avatar
Gerdi
Posts: 185
Joined: 03 Aug 2015, 18:48
Location: Germany
Contact:

Re: Text-Editor

04 Aug 2015, 01:23

einmal ersetzen von

Code: Select all

        SplitPath,FileName,FileName
durch

Code: Select all

        SplitPath,FileName,NurFileName
einmal ersetzen von

Code: Select all

        SplitPath,NewFileName,FileName
durch

Code: Select all

        FileName:=NewFileName
        SplitPath,NewFileName,NurFileName
zweimal ersetzen von

Code: Select all

        GuiControl,Main:,SelectFile,%FileName%
durch

Code: Select all

        GuiControl,Main:,SelectFile,%NurFileName%
behebt bei mir das Problem
Win 10 Home (x64) and Win 11 Pro N
https://github.com/Grrdi/ZackZackOrdner/archive/master.zip --> get folders on the quick
garry
Posts: 3750
Joined: 22 Dec 2013, 12:50

Re: Text-Editor

04 Aug 2015, 15:05

danke Gerdi , dies hat funktioniert
jetzt möchte ich noch dass :
-der Editor beim starten das letzte file öffnet ( ifexist) . ( ( im ini ist der Pfad schon gespeichert , Zeile / Spalte / Zeichen ist im Editor erfasst) )
und der cursor auf die position springt wo ich zuletzt war ( speichert File und Cursor-Position )
just me
Posts: 9439
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Text-Editor

05 Aug 2015, 00:28

Gerdi wrote:wenn ich Dateien auserhalb von A_ScriptDir öffne ist es wie bei aaffe
Bei mir das gleiche. AHK 1.1.16.05, UTF-8, Windows 8.1
Öffne ich eine DAtei im Editor, steht in der ersten Zeile des Inhalts immer nur:
C:\Users\<MeinName>\AppData\Local\Temp
Wenn ich Dateien im Skriptverzeichnis öffne sieht alles OK aus

Gerdi
Bei C:\Users\<MeinName>\AppData\Local\Temp dürfte es sich um den Inhalt der Environmentvariablen TEMP handeln. Um das abzustellen, sollte ein #NoEnv am Anfang des Skripts ausreichen, wie Johnny R es bereits oben gesagt hat.

Gerdis Änderungen (Willkommen im Club!) treffen aber des Pudels Kern, weil die TEMP Variable nur dann gezogen wird, wenn die FileRead,temp,%FileName% Anweisung erfolglos bleibt.

Edit: Ich würde allerdings SplitPath,FileName,FileName einfach löschen und SplitPath,NewFileName,FileName durch FileName := NewFileName ersetzen, weil ich meine, dass es Sinn macht, den kompletten Dateipfad anzuzeigen.
Last edited by just me on 05 Aug 2015, 03:00, edited 1 time in total.
User avatar
Gerdi
Posts: 185
Joined: 03 Aug 2015, 18:48
Location: Germany
Contact:

Re: Text-Editor

05 Aug 2015, 02:33

Hallo Garry,

die letzte Datei laden sollte so (vor Ende des Hauptprogramms einfügen)

Code: Select all

Ue1=%1%
; Ue1=Last
IfExist, %Ue1%
{					; lade uebergebenen Pfad
    FileName:=Ue1
    gosub FileNameLaden
}
else if (Ue1="Last")
{					; lade letzten Pfad
    IniRead, FileName,SimpleEditor.ini,Options,LastFile,%A_Space%
    gosub FileNameLaden
}
mit

Code: Select all

FileNameLaden:
{
    If !(Kodierung := IsTextFile(FileName)) {
        GuiControl,Main:,SelectFile,Bitte eine Textdatei auswählen...        
        if FileName
            MsgBox("Die gewählte Datei ist keine Textdatei!","Fehler",262160)
        FileName = ""
        return
    }
    IniWrite,%FileName%,SimpleEditor.ini,Options,LastFile
    Kodierung_Original := Kodierung := (Kodierung="CP65001")?"UTF-8":(Kodierung="CP1200")?"UTF-16":Kodierung
    GuiControl,Main:,CodePage,% Kodierung
    GuiControl,Main:-Disabled, CodePage
    SplitPath,FileName,NurFileName
    GuiControl,Main:,SelectFile,%NurFileName%
    FileRead,temp,%FileName%
    ; MsgBox % temp
    Inhalt:=[]
    Inhalt.0:=temp
    CursorPos:=1,ShowRow:="",Inhalt.0:=StrReplace(temp,"`r`n,`n"),temp:="",Inhalt.Index:=0 ; Inhalt.0 ist der Originalzustand
    GuiControl,Main:,Edit,% Inhalt.0
    GuiControl,Main:-Disabled,Suchen
    GuiControl,Main:,Suchen,
    GuiControl,Main:-Disabled,Ersetzen
    GuiControl,Main:,Ersetzen,
    GuiControl,Main:-Disabled,SaveTo
    GuiControl,Main:-Disabled,Edit
    GuiControl,Main:+Default,ButtonSuchen
    Loop,%ZeilenAnzahl%
        ShowRow .= "`n" a_index
    StringTrimLeft,ShowRow,ShowRow,1
    GuiControl,Main:,ShowRow,%ShowRow%
    return
}
gehen. Du rufst das Skript dann mit dem Übergabeparameter Last auf.
Zu Risiken und Nebenwirkungen lesen Sie die Packungsbeilage und sprechen mit Ihrem Artzt oder Apotheker.
(Nebenwirkungen sind nicht geprüft!)

Das mit dem genauen Ort in der Datei müsste Holle machen.
Win 10 Home (x64) and Win 11 Pro N
https://github.com/Grrdi/ZackZackOrdner/archive/master.zip --> get folders on the quick
just me
Posts: 9439
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Text-Editor

05 Aug 2015, 02:59

Hallo Gerdi,
Das mit dem genauen Ort in der Datei müsste Holle machen.
Ich fürchte, Holle kommt nicht mehr oft hierher.

Es geht ja darum, den richtigen Punkt im Skript zu finden, an dem das Wegschreiben der Position Sinn macht. Ich möchte mich aber nur ungern einmischen, weil ich die für mich kaum zu unterdrückende Angewohnheit habe, fremde Skripte auf meine Art der Programmierung umzustellen. Und bei diesem Skript springt dieser Trieb voll an.

Das hat nichts mit 'besser' oder 'schlechter' zu tun, ich kann halt nicht anders. ;)
Last edited by just me on 05 Aug 2015, 03:03, edited 1 time in total.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Text-Editor

05 Aug 2015, 03:01

just me wrote:Ich fürchte, Holle kommt nicht mehr oft hierher.
Jup, sieht so aus...
Last active: Sun Mar 01, 2015 5:12 pm

just me wrote:... weil ich die für mich kaum zu unterdrückende Angewohnhet habe, fremde Skripte auf meine Art der Programmierung umzustellen. Und bei diesem Skript springt dieser Trieb voll an.
Haha :D Kenn ich nur zu gut, geht mir meinstens genauso ;)
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
Gerdi
Posts: 185
Joined: 03 Aug 2015, 18:48
Location: Germany
Contact:

Re: Text-Editor

05 Aug 2015, 04:31

Hallo Just Me
Es geht ja darum, den richtigen Punkt im Skript zu finden, an dem das Wegschreiben der Position Sinn macht.
wäre zur Einarbeitung ins Skript eventuell gar nicht schlecht.
Eigentlich bin ich nämlich daran interessiert einen Varianten-Editor zu erhalten (bzw. zur Not zu koden).
Unter einem Varianten-Editor verstehe ich einen Editor der z.B. die 2 Varianten eine Skriptes für
- AHK-Version 1.x
- AHK-Version 2.x
(beide Varianten sollen das gleiche tun,
die 1. mit AHK-Version 1.x
die 2. mit AHK-Version 2.x )
in einer Anzeige und einer Komplett-Datei unterstützt.
Die Zeilen die in V1 gleich sind wie in V2 werden ganz normal schwarz angezeigt.
Die Zeilen(-Teile) die sich unterscheiden werden übereinander ggf. in unterschiedlicher Farbe angezeigt.
Mal sehen ob ich die Zeit finde.
Win 10 Home (x64) and Win 11 Pro N
https://github.com/Grrdi/ZackZackOrdner/archive/master.zip --> get folders on the quick
garry
Posts: 3750
Joined: 22 Dec 2013, 12:50

Re: Text-Editor

05 Aug 2015, 14:31

Vielen Dank für die Hilfe , Gerdi
es fehlt mir nur noch dass es zur letztbenutzten Cursor-Stellung scrollt

Angaben sind vorhanden : Filename , Zeile , Spalte , Zeichen
Zeile , Spalte , Zeichen noch im ini-file speichern
garry
Posts: 3750
Joined: 22 Dec 2013, 12:50

Re: Text-Editor

05 Aug 2015, 14:33

@Gerdi
Die Zeilen die in V1 gleich sind wie in V2 werden ganz normal schwarz angezeigt.
Die Zeilen(-Teile) die sich unterscheiden werden übereinander ggf. in unterschiedlicher Farbe angezeigt.
ein kleines script , die Wörter , welche übereinstimmen , im msgbox angezeigt

Code: Select all

;- compare 2 files
clip1=
(
alpha
beta
gamma
delta
epsilon
zeta
)

clip2 =
(
beta
delta
)

word := []
loop, parse, clip2, `n, `r
	word[A_LoopField] := true
loop, parse, clip1, `n, `r
	out .= word[A_LoopField] ?  A_LoopField "`n" : "`n"
MsgBox % out
return
User avatar
Gerdi
Posts: 185
Joined: 03 Aug 2015, 18:48
Location: Germany
Contact:

Re: Text-Editor

06 Aug 2015, 02:24

Danke Garry,

mit

Code: Select all

        IniWrite, %CursorZeile%, SimpleEditor.ini, Position, CursorZeile
        IniWrite, %CursorPos%, SimpleEditor.ini, Position, CursorPos
im Unterprogramm MainButtonSpeichern bekomme ich das Abspeichern hin,
aber das Einlesen mit

Code: Select all

    IniRead, CursorZeile, SimpleEditor.ini, Position, CursorZeile,%A_Space%
    IniRead, CursorPos, SimpleEditor.ini, Position, CursorPos,%A_Space%
war nicht erfolgreich, es wird irgendwo überschrieben.
Hier kannst Du probieren ob Du die Werte aktiv bringen kannst.
Win 10 Home (x64) and Win 11 Pro N
https://github.com/Grrdi/ZackZackOrdner/archive/master.zip --> get folders on the quick
just me
Posts: 9439
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Text-Editor

06 Aug 2015, 05:18

Moin zusammen!

Wenn ihr weitermachen wollt, hätte ich ein paar Tipps.

Das Skript hat leider (Verzeih bitte, Holle) einige Schwachpunkte. Dazu gehört auch das Ermitteln der Cursor/Zeichenposition. Holle macht das mit:

Code: Select all

    ControlGet,CursorZeile,CurrentLine,,Edit3,A
    ControlGet,CursorSpalte,CurrentCol,,Edit3,A
    CursorPos := 0
    Loop,%CursorZeile% {
        ControlGet,Zeile,Line,%A_Index%,Edit3,A
        CursorPos += (A_Index!=CursorZeile)?StrLen(Zeile)+!RegExMatch(zeile,"\s$"):CursorSpalte
    }
Dabei wird zu StrLen(Zeile) abhängig vom Ergebnis des RegEx entweder 0 oder 1 addiert. Mir ist schon nicht wirklich klar, was der RegEx bezwecken soll. Tatsache ist aber, dass Edit Controls als Zeilentrenner 2 (unsichtbare) Zeichen verwenden: `r`n. In mehrzeiligen Edits mag die ermittelte Cursorposition deshalb vielleicht bezogen auf die sichtbaren Zeichen korrekt sein, nicht aber in Bezug auf die in der Datei enthaltenen sichtbaren und unsichtbaren Zeichen. Wenn man die Einfügemarke setzen will (dafür gibt es die Message EM_SETSEL), werden die unsichtbaren Zeichen aber immer mitgezählt.

Lange Rede, kurzer Sinn: Um die korrekte Position der Einfügemarke zu ermitteln, sollte man die Message EM_GETSEL nutzen. Die gibt den Start und das Ende der aktuellen Auswahl zurück. Wenn nichts ausgewählt ist, sind Start und Ende identisch. In jedem Fall entspricht aber Ende genau der Zeichenposition, an der das Edit Control die Einfügemarke anzeigt. Der Wert ist allerdings ein 0-basierter Index. Um ihn für den Benutzer etwas logischer zu machen, sollte man deshalb 1 addieren.

Die INI-Datei würde ich um zwei Einträge ergänzen:
LastModified - Zeitstempel der letzten Änderung, damit man überprüfen kann, ob die Datei zwischenzeitlich außerhalb des Skripts verändert wurde. Den Wert kann man sich nach dem Speichern mit FileGetTime holen.
LastPos - Position der Einfügemarke zu Zeitpunkt des Speicherns.

Man kann dann am Anfang des Skripts prüfen, ob die Datei existiert und nicht geändert wurde. Dann kann man die Einfügemarke per EM_SETSEL() mit Start und End = LastPos setzen.
Will man dafür sorgen, dass die Zeile mit der Einfügemarke in jedem Fall sichtbar ist, nutzt man dafür die Message EM_SCROLLCARET. Dann noch ein Gosub, WindowsMessage und vielleicht ein GuiControl, Focus, und schon sollte der Himmel glänzen.

Return to “Skripte und Funktionen”

Who is online

Users browsing this forum: No registered users and 1 guest