'BEGIN LICENCE "Lynnecence V1"
'1. pls no bully
'2. don't pass this software off as your own (covered by clause 1)
'  a. also, don't sell this software (also covered by clause 1)
'3. if you decide to modify this for others to use, note the following:
'  a. you must change the name and the icon (idk why you'd even want to keep the icon)
'  b. you must express that the initial version is called notepad ultra and is made by lynnear software, and provide a link to the original
'  c. feel free to include the original credits, you don't have to though
'  d. use whatever licence you want for your version
'  e. i'd appreciate being notified of the modified version's existence, but it's not necessary to do so. if you do want to, email me at thecoolone3@hotmail.com
'4. if you modify it for personal use, then go ahead and do whatever you want, but you still can't sell it
'5. feel free to rehost this, but provide a link to the original location
'6. if something is technically allowed by the licence, but it is against the spirit of the licence, don't do it (also covered by clause 1)
'7. you can't hold me liable if there's damages or whatever (unless you are pet)

'if you feel that this licence is too stupid/vague/memeish, use MPL 2.0 instead since that's pretty much what i was going for (sans the whole "YOU MUST INHERIT THIS LICENCE" rubbish)
'END LICENCE

Imports System.IO
Imports System.Text.RegularExpressions
Imports System.Text 'saves precious, precious bytes. also it makes my code look cleaner! ~u0

Public Class NPUWindow 'NPU is short for Notepad Ultra

	'i know that "it's self commenting" is a copout, but... well, it kinda is. UpdateFilePicker() obviously updates the file picker. still, i've left comments here and there.

	'DELICIOUS, DELICIOUS GLOBAL VARIABLES! AAAAHAHAHAHAHAHA! I AM THE BEST PROGRAMMER TO EVER LIIIIIVE!

	Dim npuLocation As String = Application.StartupPath() 'i'm lazy, sue me
	Dim currentFile As String = ""
	Dim rightClickedFile As String = ""
	Dim Bullet As String
	Dim showSidebar, unsaved, ShowRightClick, AutoBullets, FirstTabPress As Boolean
	Dim checkPrint, IndentLevel As Integer

	'Dim trueDpiX As Single = CreateGraphics.DpiX 'dpi shit
	'Dim trueDpiY As Single = CreateGraphics.DpiY
	'Dim dpiX = trueDpiX / 100 'for multiplication
	'Dim dpiY = trueDpiY / 100
	Dim MenuBarWidth = 10 'temp

	Dim encType As System.Text.Encoding
	Dim unableToDetermineEncType As Boolean = False

	Dim notifyStack As Queue(Of Notification) = New Queue(Of Notification) 'don't remove this, it'll make mustard gas. seriously though it causes notifystack to equal nothing, which gives us a nullreferenceexception at runtime

	Dim UndoList As LinkedList(Of String) = New LinkedList(Of String) 'oh boy, here we go
	Dim UndoPos As Integer = 0

	Private basedirectory As String
	Private newfilebg As Boolean = False

	Public Property basedir() As String
		Get
			Return basedirectory
		End Get
		Private Set(ByVal value As String)
			basedirectory = value
			BaseDirWatch.Path = value
			StatDirectory.ToolTipText = value
			My.Settings.WorkingDirectory = value
		End Set
	End Property

	Public Property NewFile() As Boolean
		Get
			Return newfilebg
		End Get
		Set(value As Boolean)
			newfilebg = value
			FileInfoToolStripMenuItem.Enabled = Not value
			DuplicateToolStripMenuItem.Enabled = Not value
			DeleteToolStripMenuItem2.Enabled = Not value
		End Set
	End Property

	Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
		Icon = ProgramIcon()
		NewFile = True
		UndoList.AddLast(TextFileHolder.Text)
		SetDefaultThemes()
		Try
			basedir = My.Settings.WorkingDirectory
			FilePicker.Width = ViewToolStripMenuItem.Width + ViewToolStripMenuItem.Bounds.X + 15
			Find.npu = Me
			FindReplace.npu = Me
			FindCommon.npu = Me 'visual studio will try to tell you that the name can be shortened, but it's a nest of lies
			Settings.npu = Me
			chocolatePuddingOvenTimer.Start()

			SaveDialogue.InitialDirectory = basedir
			FontPicker.Font = TextFileHolder.Font
			Redraw()
			UpdateFilePicker()
			updateStatusBar()
			RedrawStatusBar()

			Notify("Welcome!", 3)
		Catch ex As Exception
			If Not My.Computer.FileSystem.DirectoryExists(basedir) Then
				MsgBox("Your working directory is unavailable! Press OK to select a new working directory. For reference, your working directory is currently set as" & vbNewLine & basedir & ".")
				FolderPicker.ShowDialog()
				basedir = FolderPicker.SelectedPath
				My.Settings.WorkingDirectory = basedir
				If basedir = "" Then
					MsgBox("Don't play me like this")
					'GoTo fug 'shhhh... it's our little secret! c;
					End
				End If
				My.Settings.WorkingDirectory = basedir
				UpdateFilePicker()
			Else
				MsgBox("Whoops!" & vbNewLine & "We've run into a bit of a fuckup." & vbNewLine & ex.Message & vbNewLine & "Press F to pay respects, then click OK.", MsgBoxStyle.OkOnly, "You've gone and busted, my good man")
			End If
		Finally
			BaseDirWatch.Path = basedir
			TextFileHolder.Font = My.Settings.Font
			TextFileHolder.WordWrap = My.Settings.WordWrap
			WordWrapToolStripMenuItem.Checked = My.Settings.WordWrap
			showSidebar = Not My.Settings.ShowSidebar
			SidebarToolStripMenuItem_Click(sender, e)
			reloadCurrentTheme()
			CleanOutTextFileHolder()
			Splash_Screen.Hide()
			Splash_Screen.ShowInTaskbar = False
			Splash_Screen.TopMost = False
			Activate()
			SplashKillTimer.Start()

			If FileToOpen <> "" And FileToOpen IsNot Nothing Then 'for opening files directly (open with ==> npu)
				Dim SelectMe As String = GetFile(FileToOpen)
				For fileIndex = 0 To FilePicker.Items.Count - 1
					If FilePicker.Items(fileIndex).ToString = SelectMe Then
						If My.Computer.FileSystem.FileExists(basedir & SelectMe) Then FilePicker.SelectedIndex = fileIndex
						Exit For
					End If
				Next
				Open_Passed_File.Hide()
				Open_Passed_File.ShowInTaskbar = False
				OPFKillTimer.Start()
			End If
		End Try

	End Sub

	Private Sub UpdateFilePicker()
		FilePicker.Items.Clear()
		Dim filenames = My.Computer.FileSystem.GetFiles(basedir, FileIO.SearchOption.SearchTopLevelOnly, "*.anusberries") 'don't edit this. it's temporary, and avoids the NullReferenceException meme
		If Not basedir.EndsWith("\") Then basedir &= "\" 'basedir *needs* to end with a backslash. if it somehow doesn't, it does now
		Dim files As Boolean = False
		For i = 0 To My.Settings.SupportedExtensions.Count - 1
			Dim ext As String = My.Settings.SupportedExtensions(i)
			filenames = My.Computer.FileSystem.GetFiles(basedir, FileIO.SearchOption.SearchTopLevelOnly, "*." & ext)
			For Each fileName As String In filenames
				If fileName.ToLower.EndsWith(ext) Then FilePicker.Items.Add(fileName.Remove(0, Len(basedir))) 'if the user only wants to open txt files, files with extensions like "txt1" and such will also open. this fixes that.
				files = True 'TODO: not this
			Next
		Next
		FilePicker.Items.Add(" ..\")
		If Not files Then
			'Notify("Directory contains no compatible files", 2)
			StatStatus.Text = "No compatible files"
		End If

		Dim directoryNames = My.Computer.FileSystem.GetDirectories(basedir, FileIO.SearchOption.SearchTopLevelOnly)
		For Each dirName As String In directoryNames
			FilePicker.Items.Add(" " & dirName.Remove(0, Len(basedir)) & "\") 'add every subdirectory in basedir, and put a space in front of them so they show up first
		Next
	End Sub

	Private Sub Redraw() Handles Me.Resize, Me.ResizeEnd 'FIX THIS FOR WEIRD DPI SETTINGS! ensures that everything's the right size to fit in the window.
		Dim TitleBarHeight As Integer = RectangleToScreen(ClientRectangle).Top - Top

		If showSidebar Then
			FilePicker.Height = ClientRectangle.Height - MenuBar.Height - Notification.Bounds.Height - 3 'thanks to http://stackoverflow.com/a/41018091/4480824 for this one weird ClientRectangle trick
			FilePicker.Top = MenuBar.Height
			TextFileHolder.Height = FilePicker.Height + MenuBar.Height + 3
			TextFileHolder.Width = Width - FilePicker.Width - 15 '*shrugs knowingly*
			TextFileHolder.Left = FilePicker.Width - 1
			TextFileHolder.Top = -1
			TextFileHolder.BorderStyle = BorderStyle.FixedSingle
		Else
			TextFileHolder.Height = ClientRectangle.Height - MenuBar.Height - Notification.Bounds.Height - 3
			TextFileHolder.Width = Width - 15
			TextFileHolder.Left = 0
			TextFileHolder.Top = MenuBar.Height
			TextFileHolder.BorderStyle = BorderStyle.None
		End If
	End Sub

	Private Async Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles FilePicker.SelectedIndexChanged 'when the user clicks on a file/directory in the filepicker
		If unsaved Then
			BaseDirWatch.EnableRaisingEvents = False ' turn basedirwatch off because it'll try to reselect the file we just saved while it's still saving, which will cause bad things to take place
			Dim response As MsgBoxResult = MsgBox("Save changes made to " & If(NewFile, "new file", """" & currentFile & """") & "?", MsgBoxStyle.YesNoCancel)
			If response = MsgBoxResult.Yes Then
				SaveToolStripMenuItem.PerformClick() 'the save function ends up reenabling basedirwatch, don't worry
			ElseIf response = MsgBoxResult.No Then
				BaseDirWatchReenabler.Start() 'if they don't wanna save, then reenable basedirwatch
			Else
				BaseDirWatch.EnableRaisingEvents = True
				Exit Sub
				'handle cancel
			End If
		End If

		If IsNothing(FilePicker.SelectedItem) Or FilePicker.SelectedItem = "" Or FilePicker.SelectedItem Is Nothing Then
			Notify("Please select a file or directory.", 2) 'if the user clicks on the blank space at the bottom of the filepicker (which is possible for some reason), shoo them
			reselectCurrentFile() 'already checks to make sure it's not empty
		Else
			Cursor = Cursors.WaitCursor
			Enabled = False
			StatStatus.Text = "Loading..."
			'MsgBox(basedir & FilePicker.SelectedItem.ToString.Substring(1))

			If FilePicker.SelectedItem.ToString = " ..\" Then 'if you clicked the ..\ item (which means go up)...
				Enabled = True
				Cursor = Cursors.Default
				StatStatus.Text = "No file loaded"
				GoUpToolStripMenuItem.PerformClick() '...click the go up button! ;p
			Else
				If FilePicker.SelectedItem.ToString.EndsWith("\") Then 'if you clicked on a directory
					Try
						If Not My.Computer.FileSystem.DirectoryExists(basedir & FilePicker.SelectedItem.ToString.Substring(1)) Then Throw New DirectoryNotFoundException
						BaseDirWatch.Path = basedir + FilePicker.SelectedItem.ToString.Substring(1) 'cd into it!
						basedir = BaseDirWatch.Path
						CleanOutTextFileHolder()
						Notify("Directory changed", 3)
						ResetUndoList()
					Catch ex As Exception
						Notify("Failed to load directory!", 1)
						CleanOutTextFileHolder()
						ResetUndoList()
					End Try
					Enabled = True
					Cursor = Cursors.Default

				ElseIf My.Computer.FileSystem.FileExists(basedir & FilePicker.SelectedItem.ToString) Then 'or, if you clicked a file...
					Dim chosenFile As StreamReader
					currentFile = FilePicker.SelectedItem
					Dim fileToLoad As String = basedir & currentFile

					Dim p As New Process
					p.StartInfo.UseShellExecute = False
					p.StartInfo.RedirectStandardOutput = True
					p.StartInfo.FileName = "dependencies\file\bin\file.exe"
					p.StartInfo.CreateNoWindow = True
					p.StartInfo.Arguments = "-b --mime-encoding """ & basedir & currentFile & """"
					p.Start()
					Dim output As String = p.StandardOutput.ReadToEnd()
					p.WaitForExit() 'firstly, get the encoding.
					unableToDetermineEncType = False

					output = output.ToLower() 'just to be 1000% sure
					'MsgBox(output)

					'and now we load that encoding!
					Select Case True 'call the cops, i don't give a fuck
						Case output.Contains("utf-8") 'TODO: find better way of doing this, it's disgusting
							encType = Encoding.UTF8
						Case output.Contains("utf-32")
							encType = Encoding.UTF32
						Case output.Contains("utf-7")
							encType = Encoding.UTF7
						Case output.Contains("unicode") Or output.Contains("utf-16") 'microsoft, the absolute madmen
							encType = Encoding.Unicode
						Case output.Contains("ansi") Or output.Contains("iso-8859") 'fucking apple i swear to god
							encType = Encoding.Default 'idk why but there's no System.Text.Encoding.ANSI.
						Case output.Contains("ascii")
							encType = Encoding.ASCII
						Case output.Contains("no read permission") Or output.Contains("no such file") 'basedirwatch tries to reload the file immediately after it's saved, which causes errors. it also causes the "couldn't determine encoding" notification to pop erroneously. this "fixes" that.
							encType = Encoding.UTF8
						Case Else
							Notify("Unsupported encoding: " & output.Replace(vbCrLf, "").Replace(vbNewLine, "") & ". Saving will convert to UTF-8.", 2) 'TODO: replace utf-8 with the user's default
							encType = Encoding.Default
							unableToDetermineEncType = True
					End Select

					Try 'you never know what'll happen with IO
						chosenFile = New StreamReader(fileToLoad, encoding:=encType) 'schnik the file into a streamreader
						LoadTimeWarningTimer.Start() 'start waiting for it to load. if it takes more than 10 seconds, bad things are taking place.
						TextFileHolder.Text = Await chosenFile.ReadToEndAsync 'When building for Windows XP, remove the "async" bit, as .Net 4.0 (the last version XP supports, rip ;u;7) doesn't support it
						LoadTimeWarningTimer.Stop() 'it's over, isn't it? isn't it? isn't it over?
						Text = currentFile & " - Notepad Ultra" 'just in case the user forgets that they're using THE BEST PROGRAM EVER WRITTEN BY MORTAL HANDS
						TextFileHolder.Select(0, 0)
						TextFileHolder.ScrollToCaret() 'jump to the top of the file
						chosenFile.Close() 'close the streamreader
						ResetUndoList() 'clear the undo list, because it'd be stupid if you could undo file2.txt so it becomes file1.txt
						NewFile = False 'we're not using a new file
						'reset the font because certain characters (like ＡＥＳＴＨＥＴＩＣ) fuck things up
						TextFileHolder.Font = New Font("FUCK", 10) 'unless the user actually has a font called FUCK, and is using it for notepad ultra, it'll be fine
						TextFileHolder.Font = My.Settings.Font
						updateStatusBar()
						StatStatus.Text = "Loaded"
						Cursor = Cursors.Default
						Enabled = True
						'FilePicker.Visible = True
					Catch ex As Exception
						'FilePicker.Visible = False
						'I don't know why, but that fucks things up BADLY
						Notify("Failed to load file!", 1)
						Enabled = True
						Cursor = Cursors.Default
						CleanOutTextFileHolder()
					End Try
					'reselectCurrentFile()
					unsaved = False
				Else
					Enabled = True
					Cursor = Cursors.Default
					Notify("Failed to load selected object!", 1) 'just in case things go terribly wrong
					CleanOutTextFileHolder()
				End If
			End If
		End If 'you know it's good code when the subroutine ends with 3 "end if" statements
	End Sub

	Private Sub WordWrapToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles WordWrapToolStripMenuItem.Click 'TODO: fucking hell
		Select Case WordWrapToolStripMenuItem.Checked
			Case False
				WordWrapToolStripMenuItem.Checked = True
				TextFileHolder.WordWrap = True
			Case True
				WordWrapToolStripMenuItem.Checked = False
				TextFileHolder.WordWrap = False
		End Select
	End Sub

	Private Sub DeleteToolStripMenuItem2_Click(sender As Object, e As EventArgs) Handles DeleteToolStripMenuItem2.Click
		If currentFile = "" Or NewFile Then
			MsgBox("You can't delete the current file when there isn't a current file, you dunce!" & vbNewLine & "(This message box should never appear! If it does, invest everything you have in gold and move out of the country)")
		Else
			If MsgBox("Are you sure you want to delete " & currentFile & "?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
				Dim DeleteOption As FileIO.RecycleOption = 3
				If My.Settings.UseRecycleBin Then
					DeleteOption = 2 'if the user wants to use the recycle bin because they're afraid of commitment, then so be it
				End If
				Enabled = False
				My.Computer.FileSystem.DeleteFile(basedir & currentFile, FileIO.UIOption.OnlyErrorDialogs, DeleteOption)
				CleanOutTextFileHolder()
				Enabled = True
			End If
		End If
	End Sub

	Private Sub NewToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles NewToolStripMenuItem.Click
		currentFile = "New file"
		NewFile = True 'TODO: a LOT of stuff (probably) breaks with new files. fix it all!
		Text = "Notepad Ultra: New file"
		TextFileHolder.Clear()
		Redraw()
		UpdateFilePicker() 'it's really quick, and deselects any files
		ResetUndoList()
	End Sub

	Private Sub SaveToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles SaveToolStripMenuItem.Click
		If NewFile Then
			SaveAsToolStripMenuItem_Click(sender, e) 'if you try to save a new file, bring up the Save As dialogue instead
		Else
			StatStatus.Text = "Saving..."
			Enabled = False
			BaseDirWatch.EnableRaisingEvents = False
			If unableToDetermineEncType Then encType = Encoding.UTF8
			My.Computer.FileSystem.WriteAllText(basedir & currentFile, TextFileHolder.Text.Replace(vbLf, vbCrLf), False, encType) 'TODO: make this an async streamwriter?
			'While Not My.Computer.FileSystem.FileExists(basedir & currentFile) 'wait for the file to exist before continuing
			'	Threading.Thread.Sleep(25) 'pause briefly to make sure we aren't thrashing the disk
			'End While
			Enabled = True
			Notify("Saved!", 3)
			StatStatus.Text = "Loaded"
			unsaved = False
			If Text.EndsWith(" (Unsaved)") Then Text = Text.RemoveLast(10) 'get rid of the (Unsaved) bit
			BaseDirWatchReenabler.Start() 'TODO: does this really need to be a timer?
		End If
	End Sub

	Private Sub SaveAsToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles SaveAsToolStripMenuItem.Click
		'all new files save as utf-8 at the moment, and that's probably for the best
		SaveDialogue.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*"
		SaveDialogue.FilterIndex = 1
		SaveDialogue.RestoreDirectory = True
		SaveDialogue.InitialDirectory = basedir
		If NewFile Then encType = Encoding.UTF8  'TODO: load this from My.Settings.DefaultEncoding
		If IsNothing(encType) Then encType = Encoding.UTF8
		If SaveDialogue.ShowDialog() = DialogResult.OK Then
			My.Computer.FileSystem.WriteAllText(SaveDialogue.FileName, TextFileHolder.Text.Replace(vbLf, vbCrLf), False, encType)
			StatStatus.Text = "Saving..."
		End If
		currentFile = SaveDialogue.FileName.Split("\")(SaveDialogue.FileName.Split("\").Length - 1)
		If Text.EndsWith(" (Unsaved)") Then Text = Text.RemoveLast(10)
		If NewFile Then
			NewFile = False
			reselectCurrentFile()
		End If
		'BaseDirWatch will take over from here
	End Sub

	Private Sub OneDriveTextFilesToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OneDriveTextFilesToolStripMenuItem.Click
		basedir = "F:\OneDrive\Documents\Other\Text files"
		UpdateFilePicker()
	End Sub

	Private Sub ChangeTheme(sender As Object, e As EventArgs, Optional ByVal silent As Boolean = False) Handles NightTheme.Click, StandardTheme.Click, TertiaryTheme.Click
		StandardTheme.Checked = False
		NightTheme.Checked = False
		TertiaryTheme.Checked = False
		sender.checked = True
		Dim themeName As String = sender.Name.ToString.Replace("Theme", "").Replace("Night", "Nite")

		TextFileHolder.BackColor = CallByName(My.Settings, themeName & "TextBG", CallType.Get)
		TextFileHolder.ForeColor = CallByName(My.Settings, themeName & "TextFG", CallType.Get)
		FilePicker.BackColor = CallByName(My.Settings, themeName & "SidebarBG", CallType.Get)
		FilePicker.ForeColor = CallByName(My.Settings, themeName & "SidebarFG", CallType.Get)
		StatusBar.BackColor = CallByName(My.Settings, themeName & "StatBG", CallType.Get)
		StatusBar.ForeColor = CallByName(My.Settings, themeName & "StatFG", CallType.Get)

		If Not silent Then Notify("Applied " & sender.Name.ToString.Replace("Theme", " Theme") & "!", 3) 'have some sort of cooldown?
		Dim themeToSet As Integer = 0
		Select Case sender.name
			Case "StandardTheme"
				themeToSet = 0
			Case "NightTheme"
				themeToSet = 1
			Case "TertiaryTheme"
				themeToSet = 2
			Case Else 'you never know when shit will hit the fan
				themeToSet = 0
		End Select

		My.Settings.CurrentTheme = themeToSet
	End Sub

	Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ExitToolStripMenuItem.Click
		saveSettings()
		End
	End Sub

	Private Sub SidebarToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles SidebarToolStripMenuItem.Click 'TODO: i'm pretty sure this doesn't really do anything except waste cycles
		Select Case SidebarToolStripMenuItem.Checked
			Case False
				SidebarToolStripMenuItem.Checked = True
				showSidebar = True
				FilePicker.Visible = True
				TextFileHolder.Left = MenuBarWidth + 25 '*shrugs knowingly*
			Case True
				SidebarToolStripMenuItem.Checked = False
				showSidebar = False
				FilePicker.Visible = False
				TextFileHolder.Left = 0
		End Select
		Redraw()
	End Sub

	Private Sub updateStatusBar() Handles TextFileHolder.TextChanged 'TODO: wait for user to stop typing before updating? this could murder slow computers, or any computer working with a fucking MASSIVE text file
		UndoTimer.Stop()
		StatChars.Text = "Characters: " & TextFileHolder.Text.Length
		'MsgBox(unsaved)
		If Not IsNothing(encType) Then StatBytes.Text = encType.GetByteCount(TextFileHolder.Text) & " Bytes"
		If My.Settings.UndoSteps <> 0 Then UndoTimer.Start()
	End Sub

	Public Sub unsavedCheck(sender As Object, e As EventArgs) Handles TextFileHolder.KeyPress
		If Not My.Computer.Keyboard.CtrlKeyDown Then 'don't mark as unsaved if you only press ctrl-a, ctrl-c, etc. TODO: handle ctrl v, ctrl, x...
			If Not unsaved Then
				Text = Text + " (Unsaved)"
				unsaved = True
			End If
			If Text.EndsWith("(Unsaved) (Unsaved)") Then Text = Text.RemoveLastInstanceOf(" (Unsaved)") 'just to be sure. this will break if the user is editing a file with the extension ".(Unsaved) (Unsaved)", but, i mean... come on.
		End If
	End Sub

	Private Sub opacify() Handles Me.Move
		If My.Settings.MoveTransparency Then Opacity = 0.5 'fade on move!
		If Not IsNothing(chocolatePuddingOvenTimer) Then
			chocolatePuddingOvenTimer.Stop()
			chocolatePuddingOvenTimer.Start()
		Else
			Opacity = 1
		End If
	End Sub

	Private Sub chocolatePuddingOvenTimer_Tick(sender As Object, e As EventArgs) Handles chocolatePuddingOvenTimer.Tick
		Opacity = 1 'stop being faded on stopped being moved!
		chocolatePuddingOvenTimer.Stop()
	End Sub

	Private Sub ToolStripSplitButton1_ButtonClick(sender As Object, e As EventArgs) Handles StatDirectory.ButtonClick
		Process.Start(basedir)
	End Sub

	Private Sub toggleSidebar(sender As Object, e As EventArgs)
		SidebarToolStripMenuItem.PerformClick()
	End Sub

	Private Sub RestartToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles RestartToolStripMenuItem.Click
		saveSettings() 'better safe than sorry!
		Application.Restart()
	End Sub

	Private Sub saveSettings()
		My.Settings.Font = TextFileHolder.Font
		My.Settings.WordWrap = TextFileHolder.WordWrap
		My.Settings.ShowSidebar = showSidebar
		My.Settings.WorkingDirectory = basedir
		My.Settings.Save()
	End Sub

	Private Sub emergencySave(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
		Try
			My.Computer.Clipboard.SetText(My.Computer.Clipboard.GetText)
			saveSettings()
			If unsaved Then
				Dim response As MsgBoxResult = MsgBox("Save changes made to " & If(NewFile, "new file", """" & currentFile & """") & "?", MsgBoxStyle.YesNoCancel)
				If response = MsgBoxResult.Yes Then
					SaveToolStripMenuItem_Click(SaveToolStripMenuItem, EventArgs.Empty)
				ElseIf response = MsgBoxResult.Cancel Then
					e.Cancel = True
					Exit Sub
				End If
			End If
			End
		Catch ex As Exception
			MsgBox(ex.Message)
		End Try
	End Sub

	Private Sub SHOWRECENTSHEREToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles SHOWRECENTSHEREToolStripMenuItem.Click '???
		currentFile = ""
		FolderPicker.ShowDialog()
		basedir = FolderPicker.SelectedPath
		UpdateFilePicker()
	End Sub

	Private Sub ChangeToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ChangeToolStripMenuItem.Click '?????
		SHOWRECENTSHEREToolStripMenuItem_Click(sender, e)
	End Sub

	Private Sub UndoToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles UndoToolStripMenuItem.Click
		If My.Settings.UndoSteps <> 0 Then
			Try
				If UndoPos <> 0 Then
					UndoPos -= 1
					TextFileHolder.Text = UndoList(UndoPos).ToString
					UndoTimer.Stop()
				Else
					Notify("Nothing to undo", 2)
				End If
			Catch ex As Exception 'better safe than sorry
				Notify("Undo error: " & ex.Message, 1)
			End Try
		Else
			Notify("Undo disabled by user.", 2) 'just in case the user's being a silly billy and forgets that they've turned off undo
		End If
	End Sub

	Private Sub RedoToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles RedoToolStripMenuItem.Click 'TODO: consider merge with undo
		If My.Settings.UndoSteps <> 0 Then
			Try
				If UndoPos <> UndoList.Count - 1 Then
					UndoPos += 1
					TextFileHolder.Text = UndoList(UndoPos).ToString
					UndoTimer.Stop()
				Else
					Notify("Nothing to redo", 2)
				End If
			Catch ex As Exception
				Notify("Undo error: " & ex.Message, 1)
			End Try
		Else
			Notify("Undo disabled by user.", 2)
		End If
	End Sub

	Private Sub FindToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles FindToolStripMenuItem.Click
		Find.npu = Me 'ensure that the find menu can access npu's main window
		Find.Show(Me)
	End Sub

	Private Sub CustomToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles CustomToolStripMenuItem.Click
		FontPicker.ShowDialog()
		TextFileHolder.Font = FontPicker.Font
		My.Settings.Font = TextFileHolder.Font
	End Sub

	Private Sub AboutToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AboutToolStripMenuItem.Click
		'MsgBox("NotePad Ultra (Version 0.10 Alpha)" & vbNewLine & vbNewLine & "An advanced Notepad for advanced minds." & vbNewLine & vbNewLine & "© 2016 Lynnear Software" & vbNewLine & "QA: Petra Morse")
		About.Show()
	End Sub

	Private Sub ArialToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ArialToolStripMenuItem.Click
		My.Settings.Font = New Font("Arial", My.Settings.Font.SizeInPoints, My.Settings.Font.Style)
		TextFileHolder.Font = My.Settings.Font
	End Sub

	Private Sub GoUpToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles GoUpToolStripMenuItem.Click
		If basedir.Length <> 3 And Not Regex.IsMatch(basedir, "^\\\\[^?:+\\<>]+\\[^?:\\<>*""|/]+\\$", RegexOptions.None) Then basedir = StrReverse(Replace(Replace(StrReverse(basedir), StrReverse(basedir.Split("\")(basedir.Split("\").Length - 2)), "",, 1), "\\", "\",, 1)) Else Notify("Already at root!", 2) 'wew lady
		'HOW THIS WORKS:
		'>check to make sure that we're not at the root path (either C:\, D:\ etc OR \\server\folder)
		'>start with basedir (C:\Path\Folder\)
		'>split it into an array using backslash as a separator ("C:", "Path", "Folder", "")
		'>select the second last string in this array ("Folder")
		'>reverse it ("redloF")
		'>reverse the whole basedir string (\redloF\htaP\:C)
		'>replace the first instance of the reversed second-last item in the array inside the reversed basedir with nothing (replace the first instance of "redloF" with "", giving "\\htaP\:C")
		'>replace the first instance of "\\" with "\" (\htaP\:C)
		'>reverse the whole thing ("C:\Path\")

		'a few weeks after writing this, i found out about My.Computer.FileSystem.ParentPath. but i'm not fucking changing it.

		Text = "Notepad Ultra"
		If My.Computer.FileSystem.DirectoryExists(basedir) Then
			'Notify("Directory changed", 3) 'Notification stack is FIFO, we gotta get in there first
			UpdateFilePicker()
			CleanOutTextFileHolder()
		Else
			Notify("Failed to change directory!", 1)
		End If
	End Sub

	Private Sub GoUpToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles GoUpToolStripMenuItem1.Click 'TODO: why are there two separate subs for this, what the fuck?
		GoUpToolStripMenuItem_Click(sender, e)
	End Sub

	Private Sub FileInfoToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles FileInfoToolStripMenuItem.Click
		Dim p As New Process
		p.StartInfo.UseShellExecute = False
		p.StartInfo.RedirectStandardOutput = True
		p.StartInfo.FileName = "dependencies\file\bin\file.exe"
		p.StartInfo.CreateNoWindow = True
		p.StartInfo.Arguments = "-b """ & basedir & currentFile & """"
		p.Start()
		Dim output As String = p.StandardOutput.ReadToEnd()
		p.WaitForExit()
		Dim q As New Process
		q.StartInfo.UseShellExecute = False
		q.StartInfo.RedirectStandardOutput = True
		q.StartInfo.FileName = "dependencies\file\bin\file.exe"
		q.StartInfo.CreateNoWindow = True
		q.StartInfo.Arguments = "-b --mime-encoding """ & basedir & currentFile & """"
		q.Start()
		Dim output2 As String = q.StandardOutput.ReadToEnd()
		q.WaitForExit()
		Try
			MsgBox("Detected type: " & output & "Detected encoding: " & output2 & "Approximate file size (on save): " & encType.GetByteCount(TextFileHolder.Text) & " Bytes" & vbNewLine & "Creation date: " & My.Computer.FileSystem.GetFileInfo(basedir & currentFile).CreationTime)
		Catch ex As Exception
			If ex.Message = "Object reference not set to an instance of an object." Then MsgBox("Failed to get file info: " & ex.Message & vbNewLine & "This almost certainly means that the file does not exist.") Else MsgBox("Failed to get file info: " & ex.Message)

		End Try
	End Sub

	Private Sub SoftwareUsedToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles SoftwareUsedToolStripMenuItem.Click
		MsgBox("Notepad Ultra makes use of the following open-source software:" & vbNewLine & vbNewLine & "GNU file" & vbNewLine & "http://www.darwinsys.com/file/" & vbNewLine & "http://gnuwin32.sourceforge.net/packages/file.htm" & "(Used for detecting file encoding)") 'i looked for a windows tool that could do the job of "file" for so fucking long! anyone who cares enough to open the software used box should know about it!
	End Sub

	Private Sub EDocumentsToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles EDocumentsToolStripMenuItem.Click 'tempura
		basedir = "E:\Documents"
		UpdateFilePicker()
	End Sub

	Private Sub autoFPUpdate() Handles BaseDirWatch.Deleted, BaseDirWatch.Created, BaseDirWatch.Renamed ', Me.Activated, Me.Deactivate, Me.GotFocus, Me.LostFocus
		UpdateFilePicker()
		reselectCurrentFile()
	End Sub

	Private Sub MakeFontLarger_Click(sender As Object, e As EventArgs) Handles MakeFontLarger.Click 'TODO: merge with vvv
		If My.Settings.Font.SizeInPoints < 500 Then
			My.Settings.Font = New Font(My.Settings.Font.FontFamily, My.Settings.Font.SizeInPoints + 1, My.Settings.Font.Style)
			TextFileHolder.Font = My.Settings.Font
		Else
			Notify("Maximum font size!", 2)
		End If
	End Sub

	Private Sub MakeFontSmaller_Click(sender As Object, e As EventArgs) Handles MakeFontSmaller.Click 'TODO: merge with ^^^
		If My.Settings.Font.SizeInPoints > 4 Then
			My.Settings.Font = New Font(My.Settings.Font.FontFamily, My.Settings.Font.SizeInPoints - 1, My.Settings.Font.Style)
			TextFileHolder.Font = My.Settings.Font
		Else
			Notify("Minimum font size!", 2)
		End If
	End Sub

	Private Sub RefreshFileList_Click(sender As Object, e As EventArgs) Handles RefreshFileList.Click
		UpdateFilePicker()
		reselectCurrentFile()
	End Sub

	Private Sub SegoeUIToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles SegoeUIToolStripMenuItem.Click 'TODO: merge this with the following 3
		My.Settings.Font = New Font("Segoe UI", My.Settings.Font.SizeInPoints, My.Settings.Font.Style)
		TextFileHolder.Font = My.Settings.Font
	End Sub

	Private Sub ConsolasToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ConsolasToolStripMenuItem.Click
		My.Settings.Font = New Font("Consolas", My.Settings.Font.SizeInPoints, My.Settings.Font.Style)
		TextFileHolder.Font = My.Settings.Font
	End Sub

	Private Sub LucidaConsoleToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles LucidaConsoleToolStripMenuItem.Click
		My.Settings.Font = New Font("Lucida Console", My.Settings.Font.SizeInPoints, My.Settings.Font.Style)
		TextFileHolder.Font = My.Settings.Font
	End Sub

	Private Sub SettingsToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles SettingsToolStripMenuItem.Click
		Settings.npu = Me
		Settings.Show(Me)
	End Sub

	Private Sub CleanOutTextFileHolder()
		UpdateFilePicker()
		ResetUndoList()
		NewFile = True
		unsaved = False
		Text = "Notepad Ultra"
		StatStatus.Text = "No file loaded"
		TextFileHolder.Text = "Welcome to Notepad Ultra! Select a file from the left." 'get everything nice and phresh
	End Sub

	Private Sub TimeDateToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles TimeDateToolStripMenuItem1.Click
		'Dim timeAndDate As String = My.Computer.Clock.LocalTime.ToShortTimeString & " " & My.Computer.Clock.LocalTime.ToShortDateString
		TextFileHolder.SelectionLength = 0
		TextFileHolder.SelectedText = My.Computer.Clock.LocalTime.ToShortTimeString & " " & My.Computer.Clock.LocalTime.ToShortDateString 'schnick the current time in
	End Sub

	Private Sub Notification_Click(sender As Object, e As EventArgs) Handles Notification.MouseDown
		Notification.Visible = False
		ShowNotificationTimer.Interval = 1
	End Sub

	Private Sub Notify(notifyText As String, category As Integer)
		notifyStack.Enqueue(New Notification() With {.Text = notifyText, .Category = category})
		ShowNotificationTimer.Start()
	End Sub

	Private Sub ShowNotificationTimer_Tick(sender As Object, e As EventArgs) Handles ShowNotificationTimer.Tick
		If notifyStack.Count = 0 Then
			ShowNotificationTimer.Stop()
			Notification.Visible = False
			ShowNotificationTimer.Interval = 1 'The next time the timer is called after showing all pending notifications, it should appear immediately.
		Else
			Dim PoppedNotify As Notification = notifyStack.Dequeue()
			Notification.Text = PoppedNotify.Text
			ShowNotificationTimer.Interval = 3000

			Select Case PoppedNotify.Category
				Case 1 'Critical: Something critical has gone wrong
					Notification.BackColor = ReturnThemeSettingsAsThemeObject(My.Settings.CurrentTheme).NotificationCriticalBG
					Notification.ForeColor = ReturnThemeSettingsAsThemeObject(My.Settings.CurrentTheme).NotificationCriticalFG
				Case 2 'Warning: Something minor has gone wrong, or an action is unavailable
imSorryCLU:
					Notification.BackColor = ReturnThemeSettingsAsThemeObject(My.Settings.CurrentTheme).NotificationWarningBG
					Notification.ForeColor = ReturnThemeSettingsAsThemeObject(My.Settings.CurrentTheme).NotificationWarningFG
				Case 3 'Just letting you know...
					Notification.BackColor = ReturnThemeSettingsAsThemeObject(My.Settings.CurrentTheme).NotificationInfoBG
					Notification.ForeColor = ReturnThemeSettingsAsThemeObject(My.Settings.CurrentTheme).NotificationInfoFG
					ShowNotificationTimer.Interval = 1500
				Case Else
					GoTo imSorryCLU 'apparently, you can't say "Case 2, Else" :c
			End Select
			Notification.Visible = True
		End If
	End Sub

	Private Sub BaseDirWatchPathToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles BaseDirWatchPathToolStripMenuItem.Click
		MsgBox(BaseDirWatch.Path)
	End Sub

	Private Sub reselectCurrentFile()
		Dim RestoreOnReload As Boolean = False
		Dim TempFileHolder As String = "An error occurred while switching files. Any unsaved changes made to this document have been lost. We apologise for the inconvenience." 'let's hope this shit never happens
		If currentFile IsNot "" And currentFile IsNot Nothing Then
			RestoreOnReload = unsaved
			If RestoreOnReload Then
				TempFileHolder = TextFileHolder.Text 'try to set tempfileholder to the textbox's text
				unsaved = False
			End If
			For fileIndex = 0 To FilePicker.Items.Count - 1
				If FilePicker.Items(fileIndex).ToString = currentFile Then
					If My.Computer.FileSystem.FileExists(basedir & currentFile) Then FilePicker.SelectedIndex = fileIndex
					Exit For
				End If
			Next
			If RestoreOnReload Then
				TextFileHolder.Text = TempFileHolder
				unsaved = True
				Text = Text + " (Unsaved)"
			End If
		End If
	End Sub

	Private Sub BaseDirWatchReenabler_Tick(sender As Object, e As EventArgs) Handles BaseDirWatchReenabler.Tick
		BaseDirWatch.EnableRaisingEvents = True
		'updateFilePicker()
		'reselectCurrentFile()
		BaseDirWatchReenabler.Stop()
	End Sub

	Private Sub DuplicateToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles DuplicateToolStripMenuItem.Click
		Dim response As String = InputBox("Duplicate """ & currentFile & """ with name:", "Duplicate", "Copy of " & currentFile)
		If response IsNot "" And Not NewFile Then
			If My.Computer.FileSystem.FileExists(basedir & response) Then
				If MsgBox("A file with the name """ & response & """ already exists. Please choose a different name.", MsgBoxStyle.OkCancel) = MsgBoxResult.Ok Then
					DuplicateToolStripMenuItem.PerformClick() 'reprompt the user for a new name if it's already taken here
				End If
			Else
				Dim ValidExt As Boolean = False
				For i = 0 To My.Settings.SupportedExtensions.Count - 1
					If response.EndsWith("." & My.Settings.SupportedExtensions(i)) Then ValidExt = True 'if the user only wants npu to work with txt files, and they save it as a cfg, schnick a .txt on the end
					If ValidExt Then Exit For
				Next
				If Not ValidExt Then response &= ".txt" 'default to the txt ending
				Dim OldCurrentFile As String = currentFile
				currentFile = response
				My.Computer.FileSystem.CopyFile(basedir & OldCurrentFile, basedir & response)
				Notify("Duplicated!", 3)
			End If
		End If
	End Sub

	Public Sub reloadCurrentTheme()
		Select Case My.Settings.CurrentTheme
			Case 0
				ChangeTheme(StandardTheme, EventArgs.Empty, True)
			Case 1
				ChangeTheme(NightTheme, EventArgs.Empty, True)
			Case 2
				ChangeTheme(TertiaryTheme, EventArgs.Empty, True)
		End Select
	End Sub

	Public Sub RedrawStatusBar()
		Dim StatBarSettings As String() = {"Chars", "Date", "Dir", "FontSize", "Size", "Status", "Mode"}
		For i = 0 To 6
			GetStatBarObject(i).visible = CallByName(My.Settings, "StatBar" & StatBarSettings(i), CallType.Get) 'only show the ones that the user wants
		Next
	End Sub

	Private Sub ReplaceToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ReplaceToolStripMenuItem.Click
		FindReplace.npu = Me
		FindReplace.Show(Me)
	End Sub

	Private Sub GoToToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles GoToToolStripMenuItem.Click
		MsgBox("Not yet supported") 'TODO: make it supported
	End Sub

	Private Sub GoUpValidatorToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles GoUpValidatorToolStripMenuItem.Click
		Dim benis As String = InputBox("String to check:")
		If benis IsNot Nothing And benis <> "" Then
			If benis.Length <> 3 And Not Regex.IsMatch(benis, "^\\\\[^?:+\\<>]+\\[^?:\\<>*""|/]+\\$", RegexOptions.None) Then MsgBox("Valid!") Else MsgBox("Invalid!") ' ensure it's a valid filename (ignoring stuff like AUX and COM, which windows should catch anyway... right?)
		End If
	End Sub

	Private Sub ShowInExplorer_Click(sender As Object, e As EventArgs) Handles ShowInExplorer.Click
		Process.Start("explorer.exe", "/select, " & basedir & rightClickedFile)
	End Sub

	Public Sub GetFileToShowMenuFor(sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles FilePicker.MouseDown
		If e.Button = MouseButtons.Right Then
			Try
				rightClickedFile = FilePicker.Items(FilePicker.IndexFromPoint(e.X, e.Y)).ToString 'try to show the right-click menu with the right-clicked file as the target
			Catch fug As System.ArgumentOutOfRangeException 'if the user right-clicks that blank bit at the bottom of the filepicker...
				Notify("Invalid selection!", 2) '...tell them to fuck off.
				rightClickedFile = ""
			End Try

		End If
	End Sub

	Private Sub DeleteToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles DeleteToolStripMenuItem.Click
		Dim DeleteOption As FileIO.RecycleOption = 3
		If My.Settings.UseRecycleBin Then DeleteOption = 2
		If MsgBox("Delete """ & rightClickedFile & """?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
			My.Computer.FileSystem.DeleteFile(basedir & rightClickedFile, FileIO.UIOption.OnlyErrorDialogs, DeleteOption)
			UpdateFilePicker()
			If rightClickedFile = currentFile Then
				CleanOutTextFileHolder()
				currentFile = ""
			End If
		End If
	End Sub

	'Printing stuff (courtesy of https://support.microsoft.com/en-us/kb/811401)
	Private Sub PrintDocument1_BeginPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles PrintDocumentThingy.BeginPrint
		checkPrint = 0
	End Sub

	Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocumentThingy.PrintPage
		' Print the content of the RichTextBox. Store the last character printed.
		checkPrint = TextFileHolder.Print(checkPrint, TextFileHolder.TextLength, e)

		' Look for more pages
		If checkPrint < TextFileHolder.TextLength Then
			e.HasMorePages = True
		Else
			e.HasMorePages = False
		End If
	End Sub

	Private Sub PrintToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles PrintToolStripMenuItem.Click
		Try
			PrintDocumentThingy.DocumentName = currentFile
			If PrintPreviewDialog1.ShowDialog() > -1 Then 'wait for the user to close the preview before continuing
				If PrintDialogue.ShowDialog() = DialogResult.OK Then
					PrintDocumentThingy.Print()
				End If
			End If
		Catch ex As Exception
			MsgBox("Failed to print file!" & vbNewLine & ex.Message)
		End Try

	End Sub

	Public Function GetStatBarObject(index)
		Select Case index
			Case 0
				Return StatChars
			Case 1
				Return StatDate
			Case 2
				Return StatDirectory
			Case 3
				Return StatFontSize
			Case 4
				Return StatBytes
			Case 5
				Return StatStatus
			Case 6
				Return StatMode
			Case Else
				Throw New Exception("GetStatBarObject: Invalid index!")
		End Select
	End Function

	Private Sub LoadTimeWarning_Tick(sender As Object, e As EventArgs) Handles LoadTimeWarningTimer.Tick
		LoadTimeWarning.Show() 'if it takes more than 10s to load the file, something's gone wrong
		LoadTimeWarningTimer.Stop()
	End Sub

	Private Sub SplashKillTimer_Tick(sender As Object, e As EventArgs) Handles SplashKillTimer.Tick
		Splash_Screen.Close() 'the program crashes unless you give it some time to do its thing
		SplashKillTimer.Stop()
	End Sub

	Private Sub OPFKillTimer_Tick(sender As Object, e As EventArgs) Handles OPFKillTimer.Tick
		Open_Passed_File.Close()
		OPFKillTimer.Stop()
	End Sub

	Private Sub FilePickerMenu_Opening(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles FilePickerMenu.Opening
		FilePickerMenu.Enabled = False
		If rightClickedFile = "" Then
			FilenametxtToolStripMenuItem.Text = "Invalid selection"
		Else
			FilePickerMenu.Enabled = True
			FilenametxtToolStripMenuItem.Text = rightClickedFile
		End If
	End Sub

	Private Sub UndoTimer_Tick(sender As Object, e As EventArgs) Handles UndoTimer.Tick
		Dim UndoListTooBig As Boolean = False
		If My.Settings.UndoMemoryLimit Then
			Dim UndoListSize As Long
			Dim ms As New IO.MemoryStream
			Dim bf As New Runtime.Serialization.Formatters.Binary.BinaryFormatter()
			bf.Serialize(ms, UndoList)
			UndoListSize = ms.Position
			If UndoListSize / (1024 * 1024) >= My.Settings.UndoMaxMemory Then UndoListTooBig = True 'divide by 1024 to make bytes into kb, then again to make into mb
		End If
		If Not (UndoList.Count < My.Settings.UndoSteps OrElse My.Settings.UndoUnlimitedSteps) OrElse UndoListTooBig Then
			UndoList.RemoveFirst()
			'Notify("Undo limit reached, removing oldest entries", 3)
		End If
		If UndoList.Count > 0 And UndoPos > 0 And UndoList.Count > UndoPos Then
			While UndoPos <> UndoList.Count - 1
				UndoList.RemoveLast()
			End While
		End If
		UndoList.AddLast(TextFileHolder.Text)
		UndoPos = UndoList.Count - 1
		UndoTimer.Stop()
	End Sub

	Private Sub PageSetup_Click(sender As Object, e As EventArgs) Handles PageSetup.Click
		PageSetupDialog1.ShowDialog()
	End Sub

	Public Sub ThrobberToggler() Handles Me.EnabledChanged
		'this subroutine ensures that whenever the form is disabled, the throbber is visible. the throbber's throbbing animation is designed to let the user know that things are happening in the background and that the program is not frozen. after all, who /doesn't/ love throbbers? i know i do!
		'for more about throbbers, visit https://en.wikipedia.org/wiki/Throbber. if you are still interested, and your desire for throbbers is not quenched by this page, the internet contains an astronomical amount of images, posts, videos, games, and more, all revolving around the concept of throbbers.
		Try
			Throbber.Visible = Not Enabled
		Catch ex As Exception
			'could not toggle throbber! throbber must be untoggleable.
			Notify("Throbber toggling failed: " & ex.Message, 1) 'notify the user of their untoggleable throbber. they'll want to know why their throbber isn't throbbing away down there!
		End Try
		'keep things short, we don't want the program sitting around toggling its throbber all day!
	End Sub

	Private Sub RenameToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles RenameToolStripMenuItem.Click 'nearly identical to the duplicate sub
		Dim response As String = InputBox("Enter new name for """ & currentFile & """:", "Rename", currentFile)
		If response IsNot "" And Not NewFile Then
			If My.Computer.FileSystem.FileExists(basedir & response) Then
				If MsgBox("A file with the name """ & response & """ already exists. Please choose a different name.", MsgBoxStyle.OkCancel) = MsgBoxResult.Ok Then
					RenameToolStripMenuItem.PerformClick()
				End If
			Else
				Dim ValidExt As Boolean = False
				For i = 0 To My.Settings.SupportedExtensions.Count - 1
					If response.EndsWith("." & My.Settings.SupportedExtensions(i)) Then ValidExt = True
					If ValidExt Then Exit For
				Next
				If Not ValidExt Then response &= ".txt"
				Dim OldCurrentFile As String = currentFile
				currentFile = response
				My.Computer.FileSystem.RenameFile(basedir & OldCurrentFile, response)
				currentFile = response
				Notify("Renamed!", 3)
				For fileIndex = 0 To FilePicker.Items.Count - 1
					If FilePicker.Items(fileIndex).ToString = currentFile Then
						If My.Computer.FileSystem.FileExists(basedir & currentFile) Then
							FilePicker.SelectedIndex = fileIndex
							NewFile = False
						End If
						Exit For
					End If
				Next
			End If
		End If
	End Sub

	Private Sub MoveToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles MoveToolStripMenuItem.Click 'also nearly identical to the duplicate sub
		MoveFileDialogue.InitialDirectory = basedir
		If MoveFileDialogue.ShowDialog() = DialogResult.OK Then
			Dim response As String = MoveFileDialogue.FileName
			If response IsNot "" And Not NewFile Then
				Dim ValidExt As Boolean = False
				For i = 0 To My.Settings.SupportedExtensions.Count - 1
					If response.EndsWith("." & My.Settings.SupportedExtensions(i)) Then ValidExt = True
					If ValidExt Then Exit For
				Next
				If Not ValidExt Then response &= ".txt"
				Dim OldCurrentFile As String = currentFile
				currentFile = response
				My.Computer.FileSystem.MoveFile(basedir & OldCurrentFile, response)
				basedir = GetPath(response)
				currentFile = GetFile(response)
				Notify("Moved!", 3)
				For fileIndex = 0 To FilePicker.Items.Count - 1
					If FilePicker.Items(fileIndex).ToString = currentFile Then
						If My.Computer.FileSystem.FileExists(basedir & currentFile) Then
							FilePicker.SelectedIndex = fileIndex
							NewFile = False
						End If
						Exit For
					End If
				Next
			End If
		End If
	End Sub

	Private Sub RenameToolStripMenuItem1_Click(sender As Object, e As EventArgs) Handles RenameToolStripMenuItem1.Click
		Dim response As String = InputBox("Enter new name for """ & rightClickedFile & """:", "Rename", currentFile)
		If response IsNot "" Then
			If My.Computer.FileSystem.FileExists(basedir & response) Then
				If MsgBox("A file with the name """ & response & """ already exists. Please choose a different name.", MsgBoxStyle.OkCancel) = MsgBoxResult.Ok Then
					RenameToolStripMenuItem1_Click(sender, e)
				End If
			Else
				Dim ValidExt As Boolean = False
				For i = 0 To My.Settings.SupportedExtensions.Count - 1
					If response.EndsWith("." & My.Settings.SupportedExtensions(i)) Then ValidExt = True
					If ValidExt Then Exit For
				Next
				If Not ValidExt Then response &= ".txt"
				My.Computer.FileSystem.RenameFile(basedir & rightClickedFile, response)
				Notify("Renamed!", 3)
				UpdateFilePicker()
				If currentFile = rightClickedFile Then
					currentFile = response
					reselectCurrentFile()
				End If
			End If
		End If
	End Sub

	Private Sub EncryptToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles EncryptToolStripMenuItem.Click
		'If MsgBox("Create an encrypted copy of this file?") = MsgBoxResult.Yes Then

		'End If
	End Sub

	Private Sub OvertypeToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OvertypeToolStripMenuItem.Click
		My.Computer.Keyboard.SendKeys(Keys.Insert) 'just schnick the insert key
	End Sub

	Private Sub DashesToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles DashesToolStripMenuItem.Click
		Bullet = "-"
		BulletPointsToolStripMenuItem.Checked = False
		AutoBullets = sender.Checked
		TextFileHolder.Focus()
		My.Computer.Keyboard.SendKeys("{END}")
		My.Computer.Keyboard.SendKeys("~") 'TODO: fix weird DING noise
	End Sub

	Private Sub BulletPointsToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles BulletPointsToolStripMenuItem.Click
		Bullet = "•"
		DashesToolStripMenuItem.Checked = False
		AutoBullets = sender.Checked
		TextFileHolder.Focus()
		My.Computer.Keyboard.SendKeys("{END}")
		My.Computer.Keyboard.SendKeys("~")
	End Sub

	Public Sub ResetUndoList()
		UndoList.Clear()
		UndoPos = 0
		UndoList.AddLast(TextFileHolder.Text)
	End Sub

	Private Sub rtb_KeyDown(sender As Object, e As KeyEventArgs) Handles TextFileHolder.KeyDown
		Dim Spaces As String = String.Concat(Enumerable.Repeat("  ", IndentLevel)) & " " 'put two spaces in for every level the user is indented up to, as well as an initial space
		TextFileHolder.Focus() 'sometimes the tab key changes menu settings instead of inserting a tab, this should fix it
		If e.Control AndAlso e.KeyCode = Keys.V Then 'stops people pasting in rich text
			DirectCast(sender, RichTextBox).Paste(DataFormats.GetFormat("Text"))
			e.Handled = True
		End If
		If AutoBullets Then 'handle automatic bullet points
			If e.KeyCode = Keys.Enter Then
				TextFileHolder.SelectedText = vbNewLine & Spaces & Bullet & " "
				My.Computer.Keyboard.SendKeys(vbBack) ':/
			ElseIf e.KeyCode = Keys.Tab Then 'if they pressed tab, they want to increase the indent level
				e.Handled = True 'this should stop a tab being inserted but it doesn't
				Dim WordWrap As Boolean = TextFileHolder.WordWrap
				TextFileHolder.WordWrap = False 'TODO: try to find a better way of doing this
				Dim Lines As String() = TextFileHolder.Lines()
				Dim OldPos As Integer = TextFileHolder.SelectionStart
				If e.Shift Then 'if they pressed shift tab
					IndentLevel -= 1 'unindent
					If Lines(TextFileHolder.GetLineFromCharIndex(TextFileHolder.SelectionStart - 1)).StartsWith("  ") Then
						Lines(TextFileHolder.GetLineFromCharIndex(TextFileHolder.SelectionStart - 1)) = Lines(TextFileHolder.GetLineFromCharIndex(TextFileHolder.SelectionStart - 1)).RemoveFirst(2) 'if the line starts with 2 spaces, get rid of them
					End If

					If IndentLevel < 0 Then
						Notify("AutoBullets disabled", 3) 'turn off autobullets if they unindent when on the lowest level
						AutoBullets = False
						IndentLevel = 0
						DashesToolStripMenuItem.Checked = False
						BulletPointsToolStripMenuItem.Checked = False
					End If
				Else
					IndentLevel += 1
					Lines(TextFileHolder.GetLineFromCharIndex(TextFileHolder.SelectionStart)) = "  " & Lines(TextFileHolder.GetLineFromCharIndex(TextFileHolder.SelectionStart)) 'add the spaces
				End If
				TextFileHolder.Lines = Lines
				If e.Shift Then
					If OldPos > 2 Then TextFileHolder.SelectionStart = OldPos - 2 'move the cursor back 2 spaces because we just deleted 2 characters
				Else
					TextFileHolder.SelectionStart = OldPos + 2
				End If
				My.Computer.Keyboard.SendKeys(vbBack) ':\
				If WordWrap Then
					TextFileHolder.WordWrap = True
					My.Computer.Keyboard.SendKeys(" ")
				End If
			End If
		End If
	End Sub

End Class