Page 1 of 1

Probably done before but: Crappy text file cleaner

Posted: Thu Nov 17, 2005 4:52 am
by Fangbeast
Probably been done before but I don't care, someone newer than me might use it. Needed a quick little utility to clean NFO files (that seem to be in everything these days) out of every rubbish character in them.

If you don't own the PV designer, you won't be able to run this until you clean out any line with "PVDynamic_" and then adjust the callback with your own resize and colouring for the window and the splitters.

Of course, the code will run quite fine without the PV stuff in it and no resizing.

I file bugs under #NULL. This works here, do what you want with it, extend it, ignore it, whatever:)

Code: Select all

; Do whatever you want with it!
;============================================================================================================================
; 
;============================================================================================================================

Enumeration 1
  #Window_nfoclean                  ; Window constants
EndEnumeration

#WindowIndex = #PB_Compiler_EnumerationValue

Enumeration 1
  #Gadget_nfoclean_fmain            ; Gadget constants
  #Gadget_nfoclean_tdirs
  #Gadget_nfoclean_lfiles
  #Gadget_nfoclean_nfofile
  #Gadget_nfoclean_bclean
  #Gadget_nfoclean_bsavefile
  #Gadget_nfoclean_scharlist        ; Splitter constants
  
  #Splitter_nfoclean_vertical
  #Splitter_nfoclean_horizontal
EndEnumeration

#GadgetIndex = #PB_Compiler_EnumerationValue

Enumeration 1
  #StatusBar_nfoclean
  #StatusBar_nfoclean_message = 0
EndEnumeration

#StatusBarIndex = #PB_Compiler_EnumerationValue

;============================================================================================================================
; Any program structures I need
;============================================================================================================================

Structure ProgramVariables
  ProgQuit.l
EndStructure

;============================================================================================================================
; Global variables
;============================================================================================================================

Global Program.ProgramVariables

;============================================================================================================================
; Visual designer window code
;============================================================================================================================

Procedure.l Window_nfoclean()
  If OpenWindow(#Window_nfoclean,70,73,700,600,#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_ScreenCentered|#PB_Window_Invisible,"Clean crap from NFO files")
    Brush.LOGBRUSH\lbColor=16764640
    SetClassLong_(WindowID(#Window_nfoclean),#GCL_HBRBACKGROUND,CreateBrushIndirect_(Brush))
    If CreateGadgetList(WindowID(#Window_nfoclean))
      Frame3DGadget(#Gadget_nfoclean_fmain,0,0,700,580,"")
      ExplorerTreeGadget(#Gadget_nfoclean_tdirs,5,10,200,541,"",#PB_Explorer_AlwaysShowSelection|#PB_Explorer_NoDriveRequester|#PB_Explorer_NoFiles)
        SendMessage_(GadgetID(#Gadget_nfoclean_tdirs),$111D,0,16764640)
        ImageList_SetBkColor_(SendMessage_(GadgetID(#Gadget_nfoclean_tdirs),#TVM_GETIMAGELIST,#TVSIL_NORMAL,0),16764640)
      ExplorerListGadget(#Gadget_nfoclean_lfiles,210,10,485,180,"*.nfo",#PB_Explorer_AlwaysShowSelection|#PB_Explorer_FullRowSelect|#PB_Explorer_NoDriveRequester|#PB_Explorer_NoFolders)
        SendMessage_(GadgetID(#Gadget_nfoclean_lfiles),#LVM_SETBKCOLOR,0,16764640)
        SendMessage_(GadgetID(#Gadget_nfoclean_lfiles),#LVM_SETTEXTBKCOLOR,0,16764640)
        ImageList_SetBkColor_(SendMessage_(GadgetID(#Gadget_nfoclean_lfiles),#TVM_GETIMAGELIST,#TVSIL_NORMAL,0),16764640)
      EditorGadget(#Gadget_nfoclean_nfofile,210,195,485,360)
        SendMessage_(GadgetID(#Gadget_nfoclean_nfofile),#EM_SETBKGNDCOLOR,0,16764640)
      ButtonGadget(#Gadget_nfoclean_bclean,5,555,100,20,"Clean the NFO file")
      ButtonGadget(#Gadget_nfoclean_bsavefile,105,555,100,20,"Save the NFO file")
      StringGadget(#Gadget_nfoclean_scharlist,210,555,485,20,"")
        PVDynamic_AddColorGadget(#Gadget_nfoclean_scharlist,0,16764640)
      CreateStatusBar(#StatusBar_nfoclean,WindowID(#Window_nfoclean))
        AddStatusBarField(700)
      PVDynamic_AddLockWindow(#Window_nfoclean,#StatusBar_nfoclean,1,3)
      PVDynamic_AddGadget(#Window_nfoclean,#Gadget_nfoclean_fmain,3)
      PVDynamic_AddGadget(#Window_nfoclean,#Gadget_nfoclean_tdirs,1)
      PVDynamic_AddGadget(#Window_nfoclean,#Gadget_nfoclean_lfiles,2)
      PVDynamic_AddGadget(#Window_nfoclean,#Gadget_nfoclean_nfofile,3)
      PVDynamic_AddGadget(#Window_nfoclean,#Gadget_nfoclean_bclean,4)
      PVDynamic_AddGadget(#Window_nfoclean,#Gadget_nfoclean_bsavefile,4)
      PVDynamic_AddGadget(#Window_nfoclean,#Gadget_nfoclean_scharlist,6)
      HideWindow(#Window_nfoclean,0)
      ProcedureReturn WindowID()
    EndIf
  EndIf
EndProcedure

;============================================================================================================================
; Object resizing and colouring
;============================================================================================================================

Procedure WindowCallback(WindowID, Message, wParam, lParam)
  ReturnValue = #PB_ProcessPureBasicEvents
  If Message = #WM_GETMINMAXINFO
    ReturnValue = PVDynamic_LockWindow(WindowID, lParam)
  EndIf
  If Message = #WM_SIZE
    ReturnValue = PVDynamic_Resize(WindowID)
  EndIf
  If Message = #WM_CTLCOLORSTATIC Or Message = #WM_CTLCOLOREDIT Or Message = #WM_CTLCOLORLISTBOX
    ReturnValue = PVDynamic_ColorGadget(lParam, wParam)
  EndIf
  ProcedureReturn ReturnValue
EndProcedure

;============================================================================================================================
; Main event handler
;============================================================================================================================

If Window_nfoclean()                                                  ; Open the main window if you can

  SetWindowTitle(#Window_nfoclean, "Crappy little NFO cleaner open")  ; Set the window title bar
  
  Gosub AddSplitters                                                  ; Add the vetical and horizontal splitter
  
  SetWindowCallback(@WindowCallback())                                ; Set the object colouring and resizing callback

  Program\ProgQuit = 0                                                ; Set the initial quit value to zero

  Gosub DisplayBadChars                                               ; Load the bad character list you can add to
  
  Repeat                                                              ; Now start checking for events
    EventID   = WaitWindowEvent()
    MenuID    = EventMenuID()
    GadgetID  = EventGadgetID()
    WindowID  = EventWindowID()

    Select EventID                                                   ; What type of window event was triggered
      Case #PB_Event_CloseWindow                                      ; If it was a close window event, do the following
        Select EventWindowID()                                        ; Which window generated the close event
          Case #Window_nfoclean : Program\ProgQuit = 1                ; Main window close was triggered, set the quit flag
        EndSelect

      Case #PB_Event_Gadget                                           ; If the window event was a gadget firing, do the following
        Select GadgetID                                               ; Which gadget fired the event on the window
          Case #Gadget_nfoclean_tdirs       : Gosub ShowDirFiles      ; Someone clicked on the directory tree
          Case #Gadget_nfoclean_lfiles      : Gosub ShowCurrentFile   ; Someone clicked on the file list window
          Case #Gadget_nfoclean_nfofile     :                          ; Someone clicked on the editor window
          Case #Gadget_nfoclean_bclean      : Gosub CleanNfo          ; Someone clicked on the clean file button
          Case #Gadget_nfoclean_bsavefile   : Gosub SaveNfo           ; Someone clicked on the save file button
        EndSelect

    EndSelect                                                         ; No more event check types
  Until Program\ProgQuit                                              ; Keep loopint till the quit flag is set
  CloseWindow(#Window_nfoclean)                                        ; Close the window because the flag was trigerred
EndIf                                                                 ; Window code finished
End                                                                   ; End the program, removes code stub from memory

;============================================================================================================================
ShowDirFiles: ; Show files in the ExplorerListIcon when a directory is selected in the ExplorerTreeIcon
;============================================================================================================================

  SetGadgetText(#Gadget_nfoclean_lfiles, GetGadgetText(#Gadget_nfoclean_tdirs))
  
  StatusBarText(#StatusBar_nfoclean, #StatusBar_nfoclean_message, "Current Directory: " + GetGadgetText(#Gadget_nfoclean_tdirs))
  
Return

;============================================================================================================================
ShowCurrentFile:  ; Open the currently highlighted file and display it in the EditorGadget
;============================================================================================================================

  Select EventType()                                ; What sort of mouse click was this?
  
    Case #PB_EventType_LeftClick                    ; We clicked with the left mouse
    
      ClearGadgetItemList(#Gadget_nfoclean_nfofile) ; Clear the previous results if any
      
      FileName.s    = GetGadgetText(#Gadget_nfoclean_lfiles) + GetGadgetItemText(#Gadget_nfoclean_lfiles, GetGadgetState(#Gadget_nfoclean_lfiles), 0)
      
      If ReadFile(0, FileName.s) <> 0               ; Can we read the file?
      
        While Eof(0) = 0                            ; Keep reading till the end of the file
        
          AddGadgetItem(#Gadget_nfoclean_nfofile, -1, ReadString()) ; Add each read line to the editorgadget
          
        Wend                                         ; Continue till the end of the file
        
      CloseFile(0)                                   ; End of the file reached so close it
      
      NumLines.l = CountGadgetItems(#Gadget_nfoclean_nfofile) -1  ; Get count of lines for other functions
      
      EndIf                                         ; File reading loop finished
    
      StatusBarText(#StatusBar_nfoclean, #StatusBar_nfoclean_message, "Current FileName: " + FileName.s + " with " + Str(NumLines) + " Lines of text")
        
  EndSelect                                        ; No more events to check
  
Return                                             ; Return from this task

;============================================================================================================================
DisplayBadChars:  ; Read the list of bad characters from the data section
;============================================================================================================================

  Restore BadChars          ; Go to the label in the datasection where the bad characters are

    Read BadCharList.s      ; Read the entire line into ta string variable

      SetGadgetText(#Gadget_nfoclean_scharlist, BadCharList.s)  ; Set the string variable to the string gadget so that the user can also add to it later

Return

;============================================================================================================================
CleanNfo: ; Clean the NFO file of all characters you didn't want
;============================================================================================================================

  For NfoLoop = 0 To NumLines   ; Go through all lines in the editorgadget

    TempString.s = GetGadgetItemText(#Gadget_nfoclean_nfofile, NfoLoop, 0)  ; Grab the line into a temporary variable

    BadCharList.s = GetGadgetText(#Gadget_nfoclean_scharlist) ; Get the bad characters from the string gadget in case someone added to it

    For BadCharLen = 1 To Len(BadCharList.s)                 ; Cycle throuhg the list of bad characters

      CurrentChar.s = Mid(BadCharList.s, BadCharLen, 1)       ; Grab one character from the list of bad characters

      TempString.s = ReplaceString(TempString.s, CurrentChar.s, "", 1, 1) ; Remove the bad char from the temp string

    Next BadCharLen                                         ; Now go through the next bad character

    SetGadgetItemText(#Gadget_nfoclean_nfofile, NfoLoop, TempString.s, 0) ; Put the temp string back to the line you got it from

    SendMessage_(GadgetID(#Gadget_nfoclean_nfofile), #LVM_ENSUREVISIBLE, NfoLoop, 0)  ; Scroll to the end of the current window if a line you are working on has gone past the window boundary

  Next NfoLoop                                             ; Process the next line

  NumLines.l = CountGadgetItems(#Gadget_nfoclean_nfofile) -1  ; Get count of lines in case clean removed some lines

Return

;============================================================================================================================
AddSplitters: ; Add the splitter gadgets to the window
;============================================================================================================================

  SplitterGadget(#Splitter_nfoclean_horizontal, 209, 10, 486, 542, #Gadget_nfoclean_lfiles, #Gadget_nfoclean_nfofile, #PB_Splitter_Separator)
  
  SetGadgetState(#Splitter_nfoclean_horizontal, 140)
  
  SplitterGadget(#Splitter_nfoclean_vertical, 5, 10, 690, 542, #Gadget_nfoclean_tdirs, #Splitter_nfoclean_horizontal, #PB_Splitter_Separator|#PB_Splitter_Vertical)
  
  SetGadgetState(#Splitter_nfoclean_vertical, 200)
  
  PVDynamic_AddGadget(#Window_nfoclean, #Splitter_nfoclean_horizontal, 3)
  
  PVDynamic_AddGadget(#Window_nfoclean, #Splitter_nfoclean_vertical, 3)

Return

;============================================================================================================================
Savenfo: ; Save the cleaned up file to disk
;============================================================================================================================

  If NumLines <> 0
  
    NumLines.l = CountGadgetItems(#Gadget_nfoclean_nfofile) -1  ; Get count of lines in case clean removed some lines
  
    NewFileName.s = SaveFileRequester("Save cleaned file", "" ,"Text file | *.txt;*.asc", 0)
  
    If NewFileName.s <> ""
    
      If Right(NewFileName.s, 4) <> ".txt"
      
        NewFileName.s + ".txt"
        
      EndIf
    
      If CreateFile(0, NewFileName.s) <> 0
      
        For NfoLoop = 0 To NumLines   ; Go through all lines in the editorgadget
      
          WriteStringN(GetGadgetItemText(#Gadget_nfoclean_nfofile, NfoLoop, 0))
      
        Next NfoLoop
        
        CloseFile(0)
        
      EndIf
      
    Else
    
      StatusBarText(#StatusBar_nfoclean, #StatusBar_nfoclean_message, "Error: You have not given a filename to save anything to")
    
    EndIf  

  Else
  
    StatusBarText(#StatusBar_nfoclean, #StatusBar_nfoclean_message, "Error: There is nothing in the list to save!!")
    
  EndIf
  
Return

;============================================================================================================================
; My data section
;============================================================================================================================

DataSection

  BadChars:
  
  Data.s  "ß°ÜÛ²ÝÞÚÄ¿³±þÀÙ"
  
EndDataSection


Posted: Sat Dec 10, 2005 10:44 am
by Randy Walker
Using CountGadgetItems() with GetGadgetItemText() failed to capture CR/LF for me reliably. Results were corrupted using either WriteString() or WriteStringN() so I needed a workaround.

The goal in the code below is a "write-back" workaround to exceed the 64K text size limitation. It isn't pretty, but it works. (Although I would like to know how to do so without using the clipboard.)

I am highlighting and capturing one block at a time to the clipboard, and writing each block as I go until I reach beyond the #EM_GETLIMITTEXT return value. Sample "test.txt" file will write to your root on drive C:

Code: Select all

;/ SETUP WINDOW CONTENTS FOR SAMPLE CODE SEEN BELOW
#MyWindow = 0
#MyText = 0
HWND5 = OpenWindow(#MyWindow, 0, 0, 631, 449,  #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_TitleBar , "Large Text File")
If HWND5
  If CreateGadgetList(WindowID())
    MyFileText = EditorGadget(#MyText, -2, 25, 635, 426)
    SendMessage_(MyFileText, #EM_SETTARGETDEVICE, #Null, 0) ; 0=wrap , $FFFFFF(effectively)=wrapoff
    SendMessage_(MyFileText, #EM_SETREADONLY, 1, 0) 
    s$ = "This test is intended to fill the Editorgadget with a large quantity of text and write it back to a test file and otherwise does noting at all."
    For e.l = 1 To 700
      AddGadgetItem(#MyText, -1, s$) ;/ Stuff EditorGadget with dummy (sample) text 
    Next e
    AddGadgetItem(#MyText, -1, "The END") ; add terminating line for visual confirmation
  EndIf
EndIf
;
;/ SAMPLE CODE TO WRITE OUT ENTIRE CONTENTS OF EDITOR GADGET BEGINS HERE
h.l = SendMessage_(MyFileText, #EM_GETLIMITTEXT, 0, 0) ; 
If CreateFile(0, "c:\test.txt")
  e.l = 0
  Repeat ;/ Write LARGE amounts of text from EditorGadget() to a file.
    SendMessage_(MyFileText, #EM_SETSEL, e.l, e.l + 32000)  ; highlight block.
    SendMessage_(MyFileText, #WM_COPY, 0, 0) ; place block in clipboard.
    buffer$ = GetClipboardText() ; load my buffer from clipboard.
    WriteString(buffer$) ; send my buffer to file.
    If e.l + 32000 > h.l
      Break       ; bail out if my new buffer goes past end of editor content.
    Else
      WindowEvent()
      Delay(1)      ; share time slices with other apps.
    EndIf
    e.l = e.l + 32000
  ForEver
  CloseFile(0)
  SendMessage_(MyFileText, #EM_SETSEL, 0, 0)  ; 
  SetClipboardText("") ; free windows clipboard buffer.
  buffer$ = "" ; free memory used in my buffer.
EndIf
SetGadgetText(#MyText, "DONE")
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow

Posted: Sat Dec 10, 2005 11:40 am
by Fangbeast
Crikey, I'd forgotten I did this. It was old and simple, like me.

And yes, GetGadgetItemText won't get CR/LF pairs, they are invisible to that function.

**EDIT** Forgot to mention that I designed this with NFO files in mind and they are rarely beyond 5k in size so the routine is perfect for that.

If you needed to clean text files beyond 64k, I'd use Ring's FastFile lib from the PBOSL library and implement a streaming from disk solution with that. Mine was a visual one and not suitable for large disk files but perfect for small files.

Posted: Sat Dec 10, 2005 12:02 pm
by Fangbeast
Just had another idea. Since you can access an editorgadget line with Standard pb commands, how about trying the following.

if readfile(1, myinfile.s) : endif
if createfile(2, myoutfile) : endif

while eof(1)
usefile(1)
temp.s = readstring()
temp.s = cleancrapfromline(temp.s) ; (clean the line first)
if countgadgetitems(#myeditorgadget) <> 0 ; Delete first line if any items
removegadgetitem(#myeditorgadget, 0)
endif
addgadgetitem(#myeditorgadget, temp.s) ; Add new cleaned item
usefile(2)
writestringn(temp.s) ; Write cleaned line to file
wend
closefile(1)
closefile(2)

This routine would make the editorgadget appear to scroll lines through it and although not fast like FastFile reads, it looks interesting and appears to work okay. You also have to adjust this to accomodate the height of the editorgadget to make it fill up.