1 #Region "Microsoft.VisualBasic::7f3fa27989514f04af91955ba655eb1d, Microsoft.VisualBasic.Core\ApplicationServices\Terminal\xConsole\xConsole.vb"
2
3     ' Author:
4     
5     '       asuka (amethyst.asuka@gcmodeller.org)
6     '       xie (genetics@smrucc.org)
7     '       xieguigang (xie.guigang@live.com)
8     
9     ' Copyright (c) 2018 GPL3 Licensed
10     
11     
12     ' GNU GENERAL PUBLIC LICENSE (GPL3)
13     
14     
15     ' This program is free software: you can redistribute it and/or modify
16     ' it under the terms of the GNU General Public License as published by
17     ' the Free Software Foundation, either version 3 of the License, or
18     ' (at your option) any later version.
19     
20     ' This program is distributed in the hope that it will be useful,
21     ' but WITHOUT ANY WARRANTY; without even the implied warranty of
22     ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     ' GNU General Public License for more details.
24     
25     ' You should have received a copy of the GNU General Public License
26     ' along with this program. If not, see <http://www.gnu.org/licenses/>.
27
28
29
30     ' /********************************************************************************/
31
32     ' Summaries:
33
34     '     Module xConsole
35     
36     '         Constructor: (+1 OverloadsSub New
37     
38     '         Function: CheckNewVersion, ClearInput, ClosestConsoleColor, ConvertHexStringToByteArray, getColor
39     '                   GetConsoleWindow, (+2 Overloads) Implode, ParseLine, Print, ReadKeys
40     '                   ReadLine, RetrieveLinkerTimestamp, SetWindowPos
41     
42     '         Sub: __checkUpdates, CheckforUpdates, ClearInput, (+2 Overloads) CoolWrite, CoolWriteLine
43     '              Credits, ListFonts, RestoreColors, SetFont, SetIcon
44     '              SetWindowPos, Wait, Write, (+3 Overloads) WriteLine
45     '         Class CoolWriteSettings
46     
47     '             Properties: CoolWriting, CoolWritingDelay, CWRDDelay
48     
49     '             Constructor: (+1 OverloadsSub New
50     
51     '         Class Comparer
52     
53     '             Constructor: (+3 OverloadsSub New
54     '             Function: Find
55     
56     '         Class Spinner
57     
58     '             Constructor: (+2 OverloadsSub New
59     
60     '             Function: Turn
61     
62     '             Sub: Break, Run, RunTask
63     
64     
65     
66     
67     ' /********************************************************************************/
68
69 #End Region
70
71 ' ' * xConsole Source Code v 0.3.1
72 ' * Created by TheTrigger { overpowered.it } { thetriggersoft[at]]gmail[dot]com }
73 ' * 23/05/2014
74 '
75
76 Imports System.Drawing
77 Imports System.Globalization
78 Imports System.Reflection
79 Imports System.Runtime.InteropServices
80 Imports System.Text.RegularExpressions
81 Imports System.Threading
82 Imports System.Xml
83 Imports Microsoft.VisualBasic.Language
84 Imports sys = System.Math
85
86 Namespace Terminal
87
88     ''' <summary>
89     ''' Allows you to color and animate the console. ~ overpowered.it ~ TheTrigger - 💸
90     ''' </summary>
91     ''' <remarks>http://www.codeproject.com/Tips/626856/xConsole-Project</remarks>
92     Public Module xConsole
93
94 #Region "STATIC COSTRUCTOR .."
95
96         Sub New()
97             If System.Diagnostics.Debugger.IsAttached Then
98                 Try
99                     If CheckForUpdatesEnabled = True Then
100                         Call __checkUpdates()
101                     End If
102                 Catch generatedExceptionName As Exception
103                     Call App.LogException(generatedExceptionName)
104                 End Try
105             End If
106         End Sub
107
108         Private Sub __checkUpdates()
109             Dim key As Microsoft.Win32.RegistryKey =
110             Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software"True).CreateSubKey("OverPowered")
111
112             If key.GetValue("UpdateLastCheck"Is Nothing Then
113                 key.SetValue("UpdateLastCheck", 0)
114             End If
115
116             If CInt(key.GetValue("UpdateLastCheck")) < DateTime.Now.DayOfYear - 30 Then
117                 key.SetValue("UpdateLastCheck"DateTime.Now.DayOfYear)
118                 xConsole.CheckforUpdates()
119             End If
120
121             Call key.Close()
122         End Sub
123
124 #End Region
125
126 #Region "COOL WRITING ✌"
127
128         Public NotInheritable Class CoolWriteSettings
129             Private Sub New()
130             End Sub
131             ''' <summary>
132             ''' Gradual typing the output into console
133             ''' </summary>
134             Public Shared Property CoolWriting As Boolean = False
135
136             ''' <summary>
137             ''' Write speed
138             ''' </summary>
139             Public Shared Property CoolWritingDelay As Integer = 8
140
141             ''' <summary>
142             ''' Set the delay when write a new line or dots. (Default = 200).
143             ''' </summary>
144             Public Shared Property CWRDDelay As Integer = 280
145         End Class
146
147         ''' <summary>
148         ''' Gradual output animation 👍👍
149         ''' </summary>
150         ''' <param name="obj">The object to convert</param>
151         Public Sub CoolWrite(obj As Object)
152             CoolWrite(String.Format("{0}", obj))
153         End Sub
154
155         ''' <summary>
156         ''' Gradual output animation 👍👍
157         ''' </summary>
158         ''' <param name="format">The input string</param>
159         ''' <param name="args"></param>
160         Public Sub CoolWrite(format As StringParamArray args As Object())
161             My.AddToQueue(Sub()
162                               Dim old As Boolean = CoolWriteSettings.CoolWriting
163                               CoolWriteSettings.CoolWriting = True
164                               Call Print(String.Format(format, args))
165                               CoolWriteSettings.CoolWriting = old
166                           End Sub)
167         End Sub
168
169         ''' <summary>
170         ''' Gradual output animation
171         ''' </summary>
172         ''' <param name="format">The input string</param>
173         ''' <param name="args">Arguments</param>
174         Public Sub CoolWriteLine(format As StringParamArray args As Object())
175             Call CoolWrite(format & NEW_LINE, args)
176         End Sub
177
178         '////////////////////////////////////////////////////////////////////////////////////////////////
179         '////////////////////////////////////////////////////////////////////////////////////////////////
180         '////////////////////////////////////////////////////////////////////////////////////////////////
181 #End Region
182
183 #Region "WRITE LINE ✏"
184
185         ''' <summary>
186         ''' Allows you to write in the console-output with custom colors, followed by the current line terminator
187         ''' </summary>
188         Public Sub WriteLine()
189             Write(NEW_LINE)
190         End Sub
191
192         ''' <summary>
193         ''' Allows you to write in the console-output with custom colors, followed by the current line terminator
194         ''' </summary>
195         ''' <param name="obj">The object to convert</param>
196         Public Sub WriteLine(obj As Object)
197             Write(String.Format("{0}", obj) & NEW_LINE)
198         End Sub
199
200         ''' <summary>
201         ''' Allows you to write in the console-output with custom colors, followed by the current line terminator
202         ''' </summary>
203         ''' <param name="format">The input string</param>
204         ''' <param name="args">Arguments</param>
205         Public Sub WriteLine(format As StringParamArray args As Object())
206             Write(format & NEW_LINE, args)
207         End Sub
208
209         ''' <summary>
210         ''' Allows you to write in the console-output with custom colors
211         ''' </summary>
212         ''' <param name="format">The input string</param>
213         ''' <param name="args">Arguments</param>
214         Public Sub Write(format As StringParamArray args As Object())
215             My.InnerQueue.AddToQueue(Sub() Print(String.Format(format, args)))
216         End Sub
217
218         '////////////////////////////////////////////////////////////////////////////////////////////////
219         '////////////////////////////////////////////////////////////////////////////////////////////////
220         '////////////////////////////////////////////////////////////////////////////////////////////////
221 #End Region
222
223 #Region "OTHER 🔦"
224
225         ''' <summary>
226         ''' (php-like) Implode function
227         ''' </summary>
228         ''' <param name="args">The list input</param>
229         ''' <param name="delimiter">Delimiter</param>
230         ''' <param name="start">Index offset</param>
231         ''' <returns>Imploded string</returns>
232         Public Function Implode(args As List(Of String), Optional delimiter As String = " "Optional start As Integer = 0) As String
233             Dim text As String = String.Empty
234             For i As Integer = start To args.Count - 1
235                 text += args(i) & (If((i = args.Count - 1), String.Empty, delimiter))
236             Next
237             Return text
238         End Function
239
240         ''' <summary>
241         ''' (php-like) Implode a List of strings
242         ''' </summary>
243         ''' <param name="args">The list input</param>
244         ''' <param name="start">Index offset</param>
245         ''' <returns>Imploded string</returns>
246         Public Function Implode(args As List(Of String), Optional start As Integer = 0) As String
247             Return Implode(args, Nothing, start)
248         End Function
249
250         ''' <summary>
251         ''' Just wait. in milliseconds
252         ''' </summary>
253         ''' <param name="time"></param>
254         Public Sub Wait(time As Integer)
255             My.InnerQueue.AddToQueue(Sub() Thread.Sleep(time))
256         End Sub
257
258         ''' <summary>
259         ''' Restore default colors
260         ''' </summary>
261         Public Sub RestoreColors()
262             Console.ResetColor()
263             FONT_COLOR = Console.ForegroundColor
264             BACKGROUND_COLOR = Console.BackgroundColor
265         End Sub
266
267         ''' <summary>
268         ''' Show credits
269         ''' </summary>
270         Public Sub Credits()
271             WriteLine(vbCr & vbLf)
272             WriteLine(vbCr & vbTab & vbTab & "^8╒^r≡^7=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=^r≡^8╕^!")
273             WriteLine(vbCr & vbTab & vbTab & "^y│" & vbTab & "^3Created by^!:" & vbTab & "^8TheTrigger^!" & vbTab & vbTab & "^y│")
274             WriteLine(vbCr & vbTab & vbTab & "^y│" & vbTab & "^3WebSite^!:" & vbTab & "^8overpowered.it^!" & vbTab & vbTab & "^y│")
275             WriteLine(vbCr & vbTab & vbTab & "^y│" & vbTab & "^3Version^!:" & vbTab & "^g{0} ^!" & vbTab & vbTab & "^y│", MyASM.Version)
276             WriteLine(vbCr & vbTab & vbTab & "^y│" & vbTab & "^3Build Date^!:" & vbTab & "^y{0}" & vbTab & vbTab & "^y│^!.", RetrieveLinkerTimestamp().ToShortDateString())
277             WriteLine(vbCr & vbTab & vbTab & "^8╘^r■^7=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=═=^r■^8╛^!``")
278             WriteLine(vbCr & vbLf)
279         End Sub
280
281 #End Region
282
283 #Region "USER INPUT 🔣"
284
285         ''' <summary>
286         ''' Read the line, then parse it.
287         ''' </summary>
288         ''' <param name="ClearInput">Clear the buffer input</param>
289         ''' <returns>Return a List of strings</returns>
290         Public Function ReadLine(Optional Clearinput As Boolean = TrueAs List(Of String)
291             My.InnerQueue.WaitQueue()
292
293             If Clearinput Then
294                 xConsole.ClearInput()
295             End If
296
297             Dim sReadLine As String = Console.ReadLine()
298
299             Return ParseLine(sReadLine)
300         End Function
301
302         ''' <summary>
303         ''' Give back a ConsoleKeyInfo list
304         ''' </summary>
305         ''' <param name="Return"></param>
306         ''' <returns></returns>
307         Public Function ClearInput([Return] As BooleanAs List(Of ConsoleKeyInfo)
308             Dim CKI As New List(Of ConsoleKeyInfo)()
309             While Console.KeyAvailable
310                 CKI.Add(Console.ReadKey(False))
311             End While
312             Return CKI
313         End Function
314
315         ''' <summary>
316         ''' Clear the user input in stack
317         ''' </summary>
318         Public Sub ClearInput()
319             While Console.KeyAvailable
320                 Console.ReadKey(True)
321             End While
322         End Sub
323
324         ''' <summary>
325         ''' Parse the input string
326         ''' </summary>
327         ''' <param name="s">Input string</param>
328         ''' <returns></returns>
329         Public Function ParseLine(s As StringAs List(Of String)
330             Dim args As List(Of String) = Nothing
331
332             If String.IsNullOrWhiteSpace(s) Then
333                 args = New List(Of String)() From {
334                     String.Empty
335                 }
336                 Return args
337             End If
338
339             If even index
340             ' Split the item
341             ' Keep the entire item
342             args = s.Split(""""c).Select(Function(element, index) If(index Mod 2 = 0, element.Split(New Char() {" "c}, StringSplitOptions.RemoveEmptyEntries), New String() {element})).SelectMany(Function(element) element).AsList()
343
344             If args.Count = 0 Then
345                 args.Add(String.Empty)
346             End If
347             Return args
348         End Function
349
350         ''' <summary>
351         ''' Read EACH keys from the buffer input (visible and hidden chars)
352         ''' </summary>
353         ''' <param name="ClearInput">Clear the buffer input</param>
354         ''' <returns>string with all chars</returns>
355         Public Function ReadKeys(Optional Clearinput As Boolean = TrueAs String
356             My.InnerQueue.WaitQueue()
357
358             If Clearinput Then
359                 xConsole.ClearInput()
360             End If
361
362             Dim key As New Value(Of Char)
363             Dim result As New List(Of Char)()
364             While AscW(key = Console.ReadKey(True).KeyChar) >= 0 AndAlso
365                 AscW(+key) <> 13
366                 Call result.Add(key.value)
367             End While
368
369             Return String.Join("", result)
370         End Function
371
372         '////////////////////////////////////////////////////////////////////////////////////////////////
373         '////////////////////////////////////////////////////////////////////////////////////////////////
374         '////////////////////////////////////////////////////////////////////////////////////////////////
375 #End Region
376
377 #Region "THE MAGIC-WRITER 👻"
378
379         ''' <summary>
380         ''' Convert input to color
381         ''' </summary>
382         ''' <param name="s">Input string</param>
383         ''' <returns>👽👽👽👾</returns>
384         Private Function getColor(s As StringOptional ForeC As ConsoleColor? = NothingOptional BackC As ConsoleColor? = NothingAs ConsoleColor
385             Dim FC As ConsoleColor = If(ForeC, FONT_COLOR)
386             Dim BC As ConsoleColor = If(BackC, BACKGROUND_COLOR)
387
388             If String.IsNullOrWhiteSpace(s) Then
389                 Return FC
390             End If
391
392             Dim Type As Char = s(0)
393             s = s.TrimStart(New Char() {"^"c, "*"c})
394             Dim i As Integer = -1
395
396             ' RGB case
397             If s.Length = 3 Then
398                 s = String.Format("{0}{0}{1}{1}{2}{2}", s(0), s(1), s(2))
399                 Dim colors As Byte() = ConvertHexStringToByteArray(s)
400                 Dim cc = ClosestConsoleColor(colors(0), colors(1), colors(2))
401                 Return cc
402
403                 Single Char
404             ElseIf s.Length = 1 OrElse s.Length = 2 Then
405
406                 ' INT CASE
407                 If Integer.TryParse(s, i) Then
408                     Return CType(If((i < 0 OrElse i > 16), 1, i), ConsoleColor)
409                 Else
410                     Char case
411                     Select Case s.ToLower()
412                         Case "!""-"
413                             ' Restore color
414                             Return If((Type = "^"c), FC, BC)
415
416                         Case "."
417                             ' Random color
418                             Dim c As Integer = 0
419                             Dim cList = [Enum].GetNames(GetType(ConsoleColor))
420                             Do
421                                 c = (RDN.[Next](0, cList.Length - 1))
422                             Loop While c = CInt(If((Type = "*"c), Console.ForegroundColor, Console.BackgroundColor))
423
424                             Return CType(c, ConsoleColor)
425
426                         Case "w"
427                             Return ConsoleColor.White
428                         Case "z"
429                             Return ConsoleColor.Black
430                         Case "y"
431                             Return ConsoleColor.Yellow
432                         Case "g"
433                             Return ConsoleColor.Green
434                         Case "r"
435                             Return ConsoleColor.Red
436                         Case "b"
437                             Return ConsoleColor.Blue
438                         Case "c"
439                             Return ConsoleColor.Cyan
440                         Case "m"
441                             Return ConsoleColor.Magenta
442                         Case Else
443                     End Select
444                 End If
445             End If
446             Return Console.ForegroundColor
447         End Function
448
449         Const c As String = vbCr & vbLf & ".,:;!?"
450         'string pattern = @"[\\]{0,1}(?:[\^|\*|°]{1})(?:[0-9a-fA-F]{3}|[0-9]{1,2}|[a-zA-Z!\.]{1})";
451         Const pattern As String = "[\\]{0,1}(?:[\^|\*]{1})(?:[0-9A-F]{3}|[0-9]{1,2}|[a-zA-Z!\.]{1})"
452
453         ''' <summary>
454         ''' The Parser
455         ''' </summary>
456         ''' <param name="input">Input string</param>
457         Private Function Print(input As StringAs Integer
458             If String.IsNullOrWhiteSpace(input) Then
459                 Return 0
460             End If
461
462             ' temp var for restore previous color
463             Dim ForAs ConsoleColor = Console.ForegroundColor
464             Dim Back As ConsoleColor = Console.BackgroundColor
465             Dim matches As MatchCollection = Regex.Matches(input, pattern)
466             Dim substrings As String() = Regex.Split(input, pattern)
467
468             Dim i As Integer = 0, StringSize As Integer = 0
469
470             For Each [sub] As String In substrings
471                 StringSize += [sub].Count()
472                 If CoolWriteSettings.CoolWriting Then
473                     For j As Integer = 0 To [sub].Length - 1
474                         Console.Write([sub](j))
475
476                         If c.Contains([sub](j)) AndAlso (j < [sub].Length - 1 AndAlso [sub](j + 1) <> [sub](j)) Then
477                             Thread.Sleep(CoolWriteSettings.CWRDDelay)
478                         Else
479                             Thread.Sleep(CoolWriteSettings.CoolWritingDelay)
480                         End If
481                     Next
482                 Else
483                     Console.Write([sub])
484                 End If
485
486                 If i < matches.Count Then
487                     Dim Type As Char = matches(i).Groups(0).Value(0)
488                     Select Case Type
489                         Case "*"c
490                             Console.BackgroundColor = getColor(matches(i).Groups(0).Value)
491                         Case "^"c
492                             Console.ForegroundColor = getColor(matches(i).Groups(0).Value)
493                         Case Else
494                             Console.Write("{0}", matches(i).Groups(0).Value.TrimStart("\"c))
495                     End Select
496                 End If
497
498                 i += 1
499             Next
500
501             If ClearColorsAtEnd Then
502                 Console.BackgroundColor = Fore
503                 Console.ForegroundColor = Back
504             End If
505
506             Return StringSize
507         End Function
508
509
510         '////////////////////////////////////////////////////////////////////////////////////////////////
511         '////////////////////////////////////////////////////////////////////////////////////////////////
512         '////////////////////////////////////////////////////////////////////////////////////////////////
513 #End Region
514
515 #Region "COMPARER 💻"
516
517         ''' <summary>
518         ''' This can compute the input then return back the most appropriate word.
519         ''' </summary>
520         Public Class Comparer
521
522             ''' <summary>
523             ''' This is the word to find
524             ''' </summary>
525             Public Word As String = String.Empty
526
527             ''' <summary>
528             ''' Descrizione
529             ''' </summary>
530             Public Description As String = String.Empty
531
532             ''' <summary>
533             ''' Init to 0!
534             ''' </summary>
535             Private Points As Integer = 0
536
537             ''' <summary>
538             ''' Initliaze a new instance
539             ''' </summary>
540             ''' <param name="w">The word to find</param>
541             ''' <param name="p">It's should be 0</param>
542             Public Sub New(w As String, p As Integer)
543                 Word = w
544                 Points = p
545             End Sub
546
547             ''' <summary>
548             ''' Initliaze a new instance
549             ''' </summary>
550             ''' <param name="w">The word to find</param>
551             Public Sub New(w As String)
552                 Word = w
553                 Points = 0
554             End Sub
555
556             ''' <summary>
557             ''' Initliaze a new instance
558             ''' </summary>
559             ''' <param name="w">The word to find</param>
560             ''' <param name="desc">Description (do nothing)</param>
561             Public Sub New(w As String, desc As String)
562                 Word = w
563                 Description = desc
564             End Sub
565
566             ''' <summary>
567             ''' Find a word from an input abbreviation (es n > name)
568             ''' </summary>
569             ''' <returns></returns>
570             Public Overloads Shared Function Find(abbr As StringByRef Words As List(Of Comparer)) As String
571                 Dim Result As String = String.Empty
572                 Dim Best As Integer = 0
573                 Dim c As Integer = 0
574
575                 While Words.Count > c AndAlso Words(c) IsNot Nothing
576                     Dim word = Words(c)
577
578                     If abbr = word.Word Then
579                         Result = abbr
580                         Exit While
581                     End If
582
583                     For i As Integer = 0 To abbr.Length - 1
584                         If abbr.Length < word.Word.Length AndAlso abbr(i) = word.Word(i) Then
585                             word.Points += 1
586                         Else
587                             word.Points = 0
588                             Exit For
589                         End If
590                     Next
591
592                     If word.Points > Best Then
593                         Best = word.Points
594                     End If
595
596
597                     c += 1
598                 End While
599                 End while
600                 Dim n As Integer = 0
601                 For Each word As Comparer In Words
602                     If word.Points = Best AndAlso word.Points > 0 Then
603                         Result = word.Word
604                         If System.Threading.Interlocked.Increment(n) > 1 Then
605                             Result = String.Empty
606                         End If
607                     End If
608                 Next
609
610                 Return Result
611             End Function
612         End Class
613
614         '////////////////////////////////////////////////////////////////////////////////////////////////
615         '////////////////////////////////////////////////////////////////////////////////////////////////
616         '////////////////////////////////////////////////////////////////////////////////////////////////
617 #End Region
618
619 #Region "SPINNER ⌛"
620
621         ''' <summary>
622         ''' A list of spinners for your console ❤
623         ''' </summary>
624         Public Class Spinner
625             Private counter As Integer = 0
626             Private c As Char()
627
628             ''' <summary>
629             ''' List of available spinners (you can add new)
630             ''' </summary>
631             Public Spinners As New List(Of Char())() From {
632                 New Char() {"-"c, "\"c, "|"c, "/"c},
633                 New Char() {"▄"c, "■"c, "▀"c, "■"c},
634                 New Char() {"╔"c, "╗"c, "╝"c, "╚"c},
635                 New Char() {"."c, "·"c, "`"c, "·"c},
636                 New Char() {"1"c, "2"c, "3"c, "4"c, "5"c, "6"c, "7"c, "8"c, "9"c, "0"c}
637             }
638
639             ''' <summary>
640             ''' looplooplooplooplooplooplooplooplooploop[...]
641             ''' </summary>
642             Private inLoop As Boolean = True
643
644             ''' <summary>
645             ''' The base string for spinning. {0} will display the spinner. COLOR is SUPPORTED! 🆒
646             ''' </summary>
647             Public SpinText As String = "{0} ^gLoading^!..."
648
649             ''' <summary>
650             ''' Initialize the spinner
651             ''' </summary>
652             ''' <param name="i">Index of the spinner to use</param>
653             ''' <param name="txt">Base string. `{0} show the spinner`</param>
654             Public Sub New(Optional i As Integer = 0, Optional txt As String = Nothing)
655                 If Not String.IsNullOrWhiteSpace(txt) Then
656                     SpinText = txt
657                 End If
658                 c = If((Spinners.Count > i), Spinners(i), Spinners(0))
659             End Sub
660
661             ''' <summary>
662             ''' Initialize a custom spinner
663             ''' </summary>
664             ''' <param name="spinner">Set a custom spinner, no size limit.</param>
665             Public Sub New(spinner As Char())
666                 c = spinner
667             End Sub
668
669             ''' <summary>
670             ''' Breaks the spinner
671             ''' </summary>
672             Public Sub Break()
673                 inLoop = False
674             End Sub
675
676             Private StringSize As Integer = 0
677
678             ''' <summary>
679             ''' Turn the spin!
680             ''' </summary>
681             ''' <param name="time">Waiting time. Default 130 ms</param>
682             ''' <returns>False if it has been stopped</returns>
683             ''' <example>while(spinner.Turn());</example>
684             Public Function Turn(Optional time As Integer = 130) As Boolean
685                 Dim [loop] = inLoop
686
687                 If [loop] Then
688                     counter += 1
689                     Dim wr As String = String.Format(SpinText, c(counter Mod c.Length), "wtf?")
690                     My.InnerQueue.AddToQueue(Sub()
691                                                  StringSize = Print(wr)
692                                                  Dim left As Integer = Console.CursorLeft - StringSize
693                                                  If left < 0 Then
694                                                      left = 0
695                                                  End If
696                                                  Console.SetCursorPosition(left, Console.CursorTop)
697                                              End Sub)
698
699                     Thread.Sleep(time)
700                 Else
701                     My.InnerQueue.AddToQueue(Sub()
702                                                  Dim pos As New Point(Console.CursorLeft, Console.CursorTop)
703                                                  Console.Write(New String(" "c, StringSize))
704                                                  Console.SetCursorPosition(pos.X, pos.Y)
705                                              End Sub)
706                 End If
707
708                 Console.CursorVisible = Not [loop]
709
710                 Return [loop]
711             End Function
712
713             Public Sub Run(Optional speed As Integer = 130)
714                 Do While inLoop
715                     Call Turn(speed)
716                     Call Thread.Sleep(10)
717                 Loop
718             End Sub
719
720             Public Sub RunTask(Optional speed As Integer = 130)
721                 Call Parallel.RunTask(Sub() Call Run(speed))
722             End Sub
723         End Class
724
725 #End Region
726
727 #Region "SET FONT / ICON ⚠"
728
729         ''' <summary>
730         ''' Show list of fonts
731         ''' </summary>
732         Public Sub ListFonts()
733             Dim fonts = Helpers.ConsoleFonts
734
735             For f As Integer = 0 To fonts.Length - 1
736                 Console.WriteLine("{0}: X={1}, Y={2}", fonts(f).Index, fonts(f).SizeX, fonts(f).SizeY)
737             Next
738
739         End Sub
740
741         ''' <summary>
742         ''' Change console font
743         ''' </summary>
744         ''' <param name="i"></param>
745         Public Sub SetFont(Optional i As UInteger = 6)
746             Helpers.SetConsoleFont(i)
747         End Sub
748
749         Public Sub SetIcon(icon As Icon)
750             Helpers.SetConsoleIcon(icon)
751         End Sub
752
753 #End Region
754
755 #Region "Windows Positions 📍"
756
757 #Region "DLL IMPORT"
758         <DllImport("user32.dll", EntryPoint:="SetWindowPos")>
759         Private Function SetWindowPos(hWnd As IntPtr, hWndInsertAfter As Integer, x As Integer, Y As Integer, cx As Integer, cy As Integer,
760             wFlags As IntegerAs IntPtr
761         End Function
762         <DllImport("kernel32.dll", ExactSpelling:=True)>
763         Private Function GetConsoleWindow() As IntPtr
764         End Function
765         Private MyConsole As IntPtr = GetConsoleWindow()
766 #End Region
767
768         ''' <summary>
769         ''' Set new window position
770         ''' </summary>
771         Public Sub SetWindowPos(x As Integer, y As Integer)
772             SetWindowPos(MyConsole, 0, x, y, 0, 0,
773                 1)
774         End Sub
775 #End Region
776
777 #Region "SOME VARS 🔧"
778
779         ''' <summary>
780         ''' My ASM FILE
781         ''' </summary>
782         Dim MyASM As AssemblyName = Assembly.GetAssembly(GetType(xConsole)).GetName()
783
784         ''' <summary>
785         ''' Random number Generator
786         ''' </summary>
787         Dim RDN As New Random()
788
789         ''' <summary>
790         ''' This value is used when restoring the colors of the console.
791         ''' </summary>
792         Dim FONT_COLOR As ConsoleColor = Console.ForegroundColor
793         ''' <summary>
794         ''' This value is used when restoring the colors of the console.
795         ''' </summary>
796         Dim BACKGROUND_COLOR As ConsoleColor = Console.BackgroundColor
797
798         ''' <summary>
799         ''' Default line terminator
800         ''' </summary>
801         ReadOnly NEW_LINE As String = Environment.NewLine
802
803         ''' <summary>
804         ''' Check for updates every 7days. False to disable. (Default = true);
805         ''' </summary>
806         Public CheckForUpdatesEnabled As Boolean = True
807
808         ''' <summary>
809         ''' Clear colors automatically at the end of each Writeline. (Default = false);
810         ''' </summary>
811         Public ClearColorsAtEnd As Boolean = False
812
813
814 #End Region
815
816 #Region "THIRD PART ✅"
817         ''' <summary>
818         ''' Convert rgb color to ConsoleColor. From stackoverflow
819         ''' </summary>
820         Private Function ClosestConsoleColor(r As Byte, g As Byte, b As ByteAs ConsoleColor
821             Dim ret As ConsoleColor = 0
822             Dim rr As Double = r, gg As Double = g, bb As Double = b, delta As Double = Double.MaxValue
823
824             For Each cc As ConsoleColor In [Enum].GetValues(GetType(ConsoleColor))
825                 Dim n = [Enum].GetName(GetType(ConsoleColor), cc)
826                 Dim c = Color.FromName(If(n = "DarkYellow""Orange", n))
827                 Dim t = sys.Pow(c.R - rr, 2.0) + sys.Pow(c.G - gg, 2.0) + sys.Pow(c.B - bb, 2.0)
828                 If t = 0.0 Then
829                     Return cc
830                 End If
831                 If t < delta Then
832                     delta = t
833                     ret = cc
834                 End If
835             Next
836             Return ret
837         End Function
838
839
840         ''' <summary>
841         ''' Linker Timestamp
842         ''' </summary>
843         Private Function RetrieveLinkerTimestamp() As DateTime
844             ' from stackoverflow
845             Dim filePath As String = System.Reflection.Assembly.GetCallingAssembly().Location
846             Const c_PeHeaderOffset As Integer = 60
847             Const c_LinkerTimestampOffset As Integer = 8
848             Dim b As Byte() = New Byte(2047) {}
849             Dim s As System.IO.Stream = Nothing
850
851             Try
852                 s = New System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read)
853                 s.Read(b, 0, 2048)
854             Finally
855                 If s IsNot Nothing Then
856                     s.Close()
857                 End If
858             End Try
859
860             Dim i As Integer = System.BitConverter.ToInt32(b, c_PeHeaderOffset)
861             Dim secondsSince1970 As Integer = System.BitConverter.ToInt32(b, i + c_LinkerTimestampOffset)
862             Dim dt As New DateTime(1970, 1, 1, 0, 0, 0)
863             dt = dt.AddSeconds(secondsSince1970)
864             dt = dt.AddHours(TimeZone.CurrentTimeZone.GetUtcOffset(dt).Hours)
865             Return dt
866         End Function
867
868
869         ''' <summary>
870         ''' Convert String to byte array
871         ''' </summary>
872         ''' <param name="hexString"></param>
873         ''' <returns></returns>
874         Private Function ConvertHexStringToByteArray(hexString As StringAs Byte()
875             ' from stackoverflow
876             If hexString.Length Mod 2 <> 0 Then
877                 Throw New ArgumentException(String.Format(CultureInfo.InvariantCulture, "The binary key cannot have an odd number of digits: {0}", hexString))
878             End If
879
880             Dim HexAsBytes As Byte() = New Byte(hexString.Length \ 2 - 1) {}
881             For index As Integer = 0 To HexAsBytes.Length - 1
882                 Dim byteValue As String = hexString.Substring(index * 2, 2)
883                 HexAsBytes(index) = Byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture)
884             Next
885
886             Return HexAsBytes
887         End Function
888
889 #End Region
890
891 #Region "CHECK FOR NEW VERSION ♻"
892
893         Public Sub CheckforUpdates()
894             CheckForUpdatesEnabled = False
895
896             New version
897             ' BACK TO THE FUTURE!? wooooooooo
898             ' up to date
899             Call New Thread(Sub()
900                                 Thread.Sleep(10)
901                                 Dim data = CheckNewVersion()
902                                 If Not String.IsNullOrWhiteSpace(data("url").ToString()) Then
903                                     xConsole.WriteLine("[^mxConsole^!] ^6Current Ver: ^y{0}^! / ^6Latest: ^y{1}^!", MyASM.Version, data("ver"))
904                                     Dim compared As Integer = MyASM.Version.CompareTo(data("ver"))
905                                     If compared = -1 Then
906                                         xConsole.WriteLine("[^mxConsole^!] ^gNew version available!^!")
907                                         xConsole.WriteLine("[^mxConsole^!]^11 Download/info page: ^w{0}^!", data("url"))
908                                     ElseIf compared = 1 Then
909                                         xConsole.WriteLine("[^mxConsole^!] *y^r>>>^6" & vbNullChar & "BACK TO THE ^rFUTURE!^!*!")
910                                     Else
911                                         xConsole.WriteLine("[^mxConsole^!] ^gUp to date! :)^!")
912                                     End If
913                                 Else
914                                     xConsole.WriteLine("[^mxConsole^!] ^rCan not check for updates :/^!")
915                                 End If
916
917                             End Sub).Start()
918         End Sub
919
920         Private Function CheckNewVersion() As Dictionary(Of StringObject)
921             Dim reader As XmlTextReader = Nothing
922             Dim data As New Dictionary(Of StringObject)()
923             data.Add("ver"New Version())
924             data.Add("url"String.Empty)
925
926             Try
927                 Dim xmlURL As String = "http://trigger.overpowered.it/xConsole/curr_version.xml"
928                 reader = New XmlTextReader(xmlURL)
929                 xConsole.WriteLine("[^mxConsole^!] ^6Checking for newer version...^!")
930
931                 reader.MoveToContent()
932
933                 Dim elementName As String = ""
934
935                 If (reader.NodeType = XmlNodeType.Element) AndAlso (reader.Name = "data"Then
936                     While reader.Read()
937                         If reader.NodeType = XmlNodeType.Element Then
938                             elementName = reader.Name
939                         Else
940                             If (reader.NodeType = XmlNodeType.Text) AndAlso (reader.HasValue) Then
941                                 Select Case elementName
942                                     Case "version"
943                                         data("ver") = New Version(reader.Value)
944
945
946                                     Case "url"
947                                         data("url") = reader.Value
948
949
950                                 End Select
951                             End If
952                         End If
953                     End While
954                 End If
955
956             Catch generatedExceptionName As Exception
957             Finally
958                 If reader IsNot Nothing Then
959                     reader.Close()
960                 End If
961             End Try
962
963             Return data
964         End Function
965 #End Region
966     End Module
967 End Namespace