1 // =================================
  2 // Copyright (c) 2022 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System.Os;
  7 using System.Unicode;
  8 
  9 namespace System
 10 {
 11     public const uchar keyBackspace = '\b';
 12     public const uchar keyTab = '\t';
 13     public const uchar keyNewline = '\n';
 14     public const uchar keyControlA = cast<uchar>(0x001);
 15     public const uchar keyControlB = cast<uchar>(0x002);
 16     public const uchar keyControlC = cast<uchar>(0x003);
 17     public const uchar keyControlD = cast<uchar>(0x004);
 18     public const uchar keyControlE = cast<uchar>(0x005);
 19     public const uchar keyControlF = cast<uchar>(0x006);
 20     public const uchar keyControlG = cast<uchar>(0x007);
 21     public const uchar keyControlH = cast<uchar>(0x008);
 22     public const uchar keyControlI = cast<uchar>(0x009);
 23     public const uchar keyControlJ = cast<uchar>(0x00A);
 24     public const uchar keyControlK = cast<uchar>(0x00B);
 25     public const uchar keyControlL = cast<uchar>(0x00C);
 26     public const uchar keyControlM = cast<uchar>(0x00D);
 27     public const uchar keyControlN = cast<uchar>(0x00E);
 28     public const uchar keyControlO = cast<uchar>(0x00F);
 29     public const uchar keyControlP = cast<uchar>(0x010);
 30     public const uchar keyControlQ = cast<uchar>(0x011);
 31     public const uchar keyControlR = cast<uchar>(0x012);
 32     public const uchar keyControlS = cast<uchar>(0x013);
 33     public const uchar keyControlT = cast<uchar>(0x014);
 34     public const uchar keyControlU = cast<uchar>(0x015);
 35     public const uchar keyControlV = cast<uchar>(0x016);
 36     public const uchar keyControlW = cast<uchar>(0x017);
 37     public const uchar keyControlX = cast<uchar>(0x018);
 38     public const uchar keyControlY = cast<uchar>(0x019);
 39     public const uchar keyControlZ = cast<uchar>(0x01A);
 40     public const uchar keyEscape = cast<uchar>(0x01B);
 41     public const uchar keyFS = cast<uchar>(0x01C);
 42     public const uchar keyGS = cast<uchar>(0x01D);
 43     public const uchar keyRS = cast<uchar>(0x01E);
 44     public const uchar keyUS = cast<uchar>(0x01F);
 45     
 46 //     special keys are mapped to Unicode Private Use Area
 47 
 48     public const uchar specialKeyStart = cast<uchar>(0xE000);
 49 
 50     public const uchar keyDown = cast<uchar>(0xE000);
 51     public const uchar keyUp = cast<uchar>(0xE001);
 52     public const uchar keyLeft = cast<uchar>(0xE002);
 53     public const uchar keyRight = cast<uchar>(0xE003);
 54     public const uchar keyHome = cast<uchar>(0xE004);
 55     public const uchar keyMsg = cast<uchar>(0xE005);
 56     public const uchar keyF1 = cast<uchar>(0xE006);
 57     public const uchar keyF2 = cast<uchar>(0xE007);
 58     public const uchar keyF3 = cast<uchar>(0xE008);
 59     public const uchar keyF4 = cast<uchar>(0xE009);
 60     public const uchar keyF5 = cast<uchar>(0xE00A);
 61     public const uchar keyF6 = cast<uchar>(0xE00B);
 62     public const uchar keyF7 = cast<uchar>(0xE00C);
 63     public const uchar keyF8 = cast<uchar>(0xE00D);
 64     public const uchar keyF9 = cast<uchar>(0xE00E);
 65     public const uchar keyF10 = cast<uchar>(0xE00F);
 66     public const uchar keyF11 = cast<uchar>(0xE010);
 67     public const uchar keyF12 = cast<uchar>(0xE011);
 68     public const uchar keyDel = cast<uchar>(0xE012);
 69     public const uchar keyIns = cast<uchar>(0xE013);
 70     public const uchar keyPgDown = cast<uchar>(0xE014);
 71     public const uchar keyPgUp = cast<uchar>(0xE015);
 72     public const uchar keyPrint = cast<uchar>(0xE016);
 73     public const uchar keyEnd = cast<uchar>(0xE017);
 74     public const uchar keyShiftDel = cast<uchar>(0xE018);
 75     public const uchar keyShiftEnd = cast<uchar>(0xE019);
 76     public const uchar keyShiftHome = cast<uchar>(0xE01A);
 77     public const uchar keyShiftLeft = cast<uchar>(0xE01B);
 78     public const uchar keyShiftRight = cast<uchar>(0xE01C);
 79     public const uchar keyResize = cast<uchar>(0xE01D);
 80     public const uchar keyShiftUp = cast<uchar>(0xE01E);
 81     public const uchar keyShiftDown = cast<uchar>(0xE01F);
 82     public const uchar keyControlUp = cast<uchar>(0xE020);
 83     public const uchar keyControlDown = cast<uchar>(0xE021);
 84     public const uchar keyControlLeft = cast<uchar>(0xE022);
 85     public const uchar keyControlRight = cast<uchar>(0xE023);
 86     public const uchar keyControlPgUp = cast<uchar>(0xE024);
 87     public const uchar keyControlPgDown = cast<uchar>(0xE025);
 88     public const uchar keyControlHome = cast<uchar>(0xE026);
 89     public const uchar keyControlEnd = cast<uchar>(0xE027);
 90     
 91     public const uchar keyControlDel = cast<uchar>(0xE028);
 92     public const uchar keyControlF1 = cast<uchar>(0xE029);
 93     public const uchar keyControlF2 = cast<uchar>(0xE02A);
 94     public const uchar keyControlF3 = cast<uchar>(0xE02B);
 95     public const uchar keyControlF4 = cast<uchar>(0xE02C);
 96     public const uchar keyControlF5 = cast<uchar>(0xE02D);
 97     public const uchar keyControlF6 = cast<uchar>(0xE02E);
 98     public const uchar keyControlF7 = cast<uchar>(0xE02F);
 99     public const uchar keyControlF8 = cast<uchar>(0xE030);
100     public const uchar keyControlF9 = cast<uchar>(0xE031);
101     public const uchar keyControlF10 = cast<uchar>(0xE032);
102     public const uchar keyControlF11 = cast<uchar>(0xE033);
103     public const uchar keyControlF12 = cast<uchar>(0xE034);
104     public const uchar keyShiftPgUp = cast<uchar>(0xE035);
105     public const uchar keyShiftPgDown = cast<uchar>(0xE036);
106     public const uchar keyShiftF1 = cast<uchar>(0xE037);
107     public const uchar keyShiftF2 = cast<uchar>(0xE038);
108     public const uchar keyShiftF3 = cast<uchar>(0xE039);
109     public const uchar keyShiftF4 = cast<uchar>(0xE03A);
110     public const uchar keyShiftF5 = cast<uchar>(0xE03B);
111     public const uchar keyShiftF6 = cast<uchar>(0xE03C);
112     public const uchar keyShiftF7 = cast<uchar>(0xE03D);
113     public const uchar keyShiftF8 = cast<uchar>(0xE03E);
114     public const uchar keyShiftF9 = cast<uchar>(0xE03F);
115     public const uchar keyShiftF10 = cast<uchar>(0xE040);
116     public const uchar keyShiftF11 = cast<uchar>(0xE041);
117     public const uchar keyShiftF12 = cast<uchar>(0xE042);
118 
119     public const uchar keyAltA = cast<uchar>(0xE043);
120     public const uchar keyAltB = cast<uchar>(0xE044);
121     public const uchar keyAltC = cast<uchar>(0xE045);
122     public const uchar keyAltD = cast<uchar>(0xE046);
123     public const uchar keyAltE = cast<uchar>(0xE047);
124     public const uchar keyAltF = cast<uchar>(0xE048);
125     public const uchar keyAltG = cast<uchar>(0xE049);
126     public const uchar keyAltH = cast<uchar>(0xE04A);
127     public const uchar keyAltI = cast<uchar>(0xE04B);
128     public const uchar keyAltJ = cast<uchar>(0xE04C);
129     public const uchar keyAltK = cast<uchar>(0xE04D);
130     public const uchar keyAltL = cast<uchar>(0xE04E);
131     public const uchar keyAltM = cast<uchar>(0xE04F);
132     public const uchar keyAltN = cast<uchar>(0xE050);
133     public const uchar keyAltO = cast<uchar>(0xE051);
134     public const uchar keyAltP = cast<uchar>(0xE052);
135     public const uchar keyAltQ = cast<uchar>(0xE053);
136     public const uchar keyAltR = cast<uchar>(0xE054);
137     public const uchar keyAltS = cast<uchar>(0xE055);
138     public const uchar keyAltT = cast<uchar>(0xE056);
139     public const uchar keyAltU = cast<uchar>(0xE057);
140     public const uchar keyAltV = cast<uchar>(0xE058);
141     public const uchar keyAltW = cast<uchar>(0xE059);
142     public const uchar keyAltX = cast<uchar>(0xE05A);
143     public const uchar keyAltY = cast<uchar>(0xE05B);
144     public const uchar keyAltZ = cast<uchar>(0xE05C);
145 
146     public const uchar keyAltF1 = cast<uchar>(0xE05D);
147     public const uchar keyAltF2 = cast<uchar>(0xE05E);
148     public const uchar keyAltF3 = cast<uchar>(0xE05F);
149     public const uchar keyAltF4 = cast<uchar>(0xE060);
150     public const uchar keyAltF5 = cast<uchar>(0xE061);
151     public const uchar keyAltF6 = cast<uchar>(0xE062);
152     public const uchar keyAltF7 = cast<uchar>(0xE063);
153     public const uchar keyAltF8 = cast<uchar>(0xE064);
154     public const uchar keyAltF9 = cast<uchar>(0xE065);
155     public const uchar keyAltF10 = cast<uchar>(0xE066);
156     public const uchar keyAltF11 = cast<uchar>(0xE067);
157     public const uchar keyAltF12 = cast<uchar>(0xE068);
158     
159     public const uchar keyControlShiftLeft = cast<uchar>(0xE069);
160     public const uchar keyControlShiftRight = cast<uchar>(0xE06A);
161     public const uchar keyControlShiftHome = cast<uchar>(0xE06B);
162     public const uchar keyControlShiftEnd = cast<uchar>(0xE06C);
163     public const uchar keyControlTab = cast<uchar>(0xE06D);
164     public const uchar keyShiftTab = cast<uchar>(0xE06E);
165     public const uchar keyControlIns = cast<uchar>(0xE06F);
166     public const uchar keyShiftIns = cast<uchar>(0xE070);
167     
168     public const uchar specialKeyEnd = cast<uchar>(0xE070);
169     
170     public class KeyBuffer
171     {
172         static KeyBuffer() : instance(new KeyBuffer())
173         {
174         }
175         public static nothrow KeyBuffer& Instance()
176         {
177             return *instance;
178         }
179         public nothrow void Put(byte ch)
180         {
181             engine.Put(ch);
182         }
183         public nothrow bool KeyReady() const
184         {
185             return engine.ResultReady();
186         }
187         public nothrow uchar GetKey() const
188         {
189             return engine.Get();
190         }
191         private static UniquePtr<KeyBuffer> instance;
192         private UnicodeEngine engine;
193     }
194     
195     public uchar ReadKey(int fd)
196     {
197         KeyBuffer& keyBuffer = KeyBuffer.Instance();
198         byte ch = 0u;
199         long count = Read(fd&ch1);
200         while (count > 0)
201         {
202             keyBuffer.Put(ch);
203             if (keyBuffer.KeyReady())
204             {
205                 return keyBuffer.GetKey();
206             }
207             count = Read(fd&ch1);
208         }
209         return cast<uchar>(0);
210     }
211     
212     public string KeyName(uchar c)
213     {
214         switch (c)
215         {
216             case keyBackspace:
217             {
218                 return "Backspace";
219             }
220             case keyTab:
221             {
222                 return "Tab";
223             }
224             case keyNewline:
225             {
226                 return "Newline";
227             }
228             case keyControlA:
229             {
230                 return "Ctrl+A";
231             }
232             case keyControlB:
233             {
234                 return "Ctrl+B";
235             }
236             case keyControlC:
237             {
238                 return "Ctrl+C";
239             }
240             case keyControlD:
241             {
242                 return "Ctrl+D";
243             }
244             case keyControlE:
245             {
246                 return "Ctrl+E";
247             }
248             case keyControlF:
249             {
250                 return "Ctrl+F";
251             }
252             case keyControlG:
253             {
254                 return "Ctrl+G";
255             }
256             case keyControlK:
257             {
258                 return "Ctrl+K";
259             }
260             case keyControlL:
261             {
262                 return "Ctrl+L";
263             }
264             case keyControlM:
265             {
266                 return "Ctrl+M";
267             }
268             case keyControlN:
269             {
270                 return "Ctrl+N";
271             }
272             case keyControlO:
273             {
274                 return "Ctrl+O";
275             }
276             case keyControlP:
277             {
278                 return "Ctrl+P";
279             }
280             case keyControlQ:
281             {
282                 return "Ctrl+Q";
283             }
284             case keyControlR:
285             {
286                 return "Ctrl+R";
287             }
288             case keyControlS:
289             {
290                 return "Ctrl+S";
291             }
292             case keyControlT:
293             {
294                 return "Ctrl+T";
295             }
296             case keyControlU:
297             {
298                 return "Ctrl+U";
299             }
300             case keyControlV:
301             {
302                 return "Ctrl+V";
303             }
304             case keyControlW:
305             {
306                 return "Ctrl+W";
307             }
308             case keyControlX:
309             {
310                 return "Ctrl+X";
311             }
312             case keyControlY:
313             {
314                 return "Ctrl+Y";
315             }
316             case keyControlZ:
317             {
318                 return "Ctrl+Z";
319             }
320             case keyEscape:
321             {
322                 return "Escape";
323             }
324             case keyFS:
325             {
326                 return "FS";
327             }
328             case keyGS:
329             {
330                 return "GS";
331             }
332             case keyRS:
333             {
334                 return "RS";
335             }
336             case keyUS:
337             {
338                 return "US";
339             }
340             case keyDown:
341             {
342                 return "Down Arrow";
343             }
344             case keyUp:
345             {
346                 return "Up Arrow";
347             }
348             case keyLeft:
349             {
350                 return "Left Arrow";
351             }
352             case keyRight:
353             {
354                 return "Right Arrow";
355             }
356             case keyHome:
357             {
358                 return "Home";
359             }
360             case keyMsg:
361             {
362                 return "MSG";
363             }
364             case keyF1:
365             {
366                 return "F1";
367             }
368             case keyF2:
369             {
370                 return "F2";
371             }
372             case keyF3:
373             {
374                 return "F3";
375             }
376             case keyF4:
377             {
378                 return "F4";
379             }
380             case keyF5:
381             {
382                 return "F5";
383             }
384             case keyF6:
385             {
386                 return "F6";
387             }
388             case keyF7:
389             {
390                 return "F7";
391             }
392             case keyF8:
393             {
394                 return "F8";
395             }
396             case keyF9:
397             {
398                 return "F9";
399             }
400             case keyF10:
401             {
402                 return "F10";
403             }
404             case keyF11:
405             {
406                 return "F11";
407             }
408             case keyF12:
409             {
410                 return "F12";
411             }
412             case keyDel:
413             {
414                 return "Delete";
415             }
416             case keyIns:
417             {
418                 return "Insert";
419             }
420             case keyPgDown:
421             {
422                 return "Page Down";
423             }
424             case keyPgUp:
425             {
426                 return "Page Up";
427             }
428             case keyPrint:
429             {
430                 return "Print Screen";
431             }
432             case keyEnd:
433             {
434                 return "End";
435             }
436             case keyShiftDel:
437             {
438                 return "Shift+Delete";
439             }
440             case keyShiftEnd:
441             {
442                 return "Shift+End";
443             }
444             case keyShiftHome:
445             {
446                 return "Shift+Home";
447             }
448             case keyShiftLeft:
449             {
450                 return "Shift+Left Arrow";
451             }
452             case keyShiftRight:
453             {
454                 return "Shift+Right Arrow";
455             }
456             case keyResize:
457             {
458                 return "Resize";
459             }
460             case keyShiftUp:
461             {
462                 return "Shift+Up Arrow";
463             }
464             case keyShiftDown:
465             {
466                 return "Shift+Down Arrow";
467             }
468             case keyControlUp:
469             {
470                 return "Ctrl+Up Arrow";
471             }
472             case keyControlDown:
473             {
474                 return "Ctrl+Down Arrow";
475             }
476             case keyControlLeft:
477             {
478                 return "Ctrl+Left Arrow";
479             }
480             case keyControlRight:
481             {
482                 return "Ctrl+Right Arrow";
483             }
484             case keyControlPgUp:
485             {
486                 return "Ctrl+Page Up";
487             }
488             case keyControlPgDown:
489             {
490                 return "Ctrl+Page Down";
491             }
492             case keyControlHome:
493             {
494                 return "Ctrl+Home";
495             }
496             case keyControlEnd:
497             {
498                 return "Ctrl+End";
499             }
500             case keyControlDel:
501             {
502                 return "Ctrl+Delete";
503             }
504             case keyControlF1:
505             {
506                 return "Ctrl+F1";
507             }
508             case keyControlF2:
509             {
510                 return "Ctrl+F2";
511             }
512             case keyControlF3:
513             {
514                 return "Ctrl+F3";
515             }
516             case keyControlF4:
517             {
518                 return "Ctrl+F4";
519             }
520             case keyControlF5:
521             {
522                 return "Ctrl+F5";
523             }
524             case keyControlF6:
525             {
526                 return "Ctrl+F6";
527             }
528             case keyControlF7:
529             {
530                 return "Ctrl+F7";
531             }
532             case keyControlF8:
533             {
534                 return "Ctrl+F8";
535             }
536             case keyControlF9:
537             {
538                 return "Ctrl+F9";
539             }
540             case keyControlF10:
541             {
542                 return "Ctrl+F10";
543             }
544             case keyControlF11:
545             {
546                 return "Ctrl+F11";
547             }
548             case keyControlF12:
549             {
550                 return "Ctrl+F12";
551             }
552             case keyShiftPgUp:
553             {
554                 return "Shift+Page Up";
555             }
556             case keyShiftPgDown:
557             {
558                 return "Shift+Page Down";
559             }
560             case keyShiftF1:
561             {
562                 return "Shift+F1";
563             }
564             case keyShiftF2:
565             {
566                 return "Shift+F2";
567             }
568             case keyShiftF3:
569             {
570                 return "Shift+F3";
571             }
572             case keyShiftF4:
573             {
574                 return "Shift+F4";
575             }
576             case keyShiftF5:
577             {
578                 return "Shift+F5";
579             }
580             case keyShiftF6:
581             {
582                 return "Shift+F6";
583             }
584             case keyShiftF7:
585             {
586                 return "Shift+F7";
587             }
588             case keyShiftF8:
589             {
590                 return "Shift+F8";
591             }
592             case keyShiftF9:
593             {
594                 return "Shift+F9";
595             }
596             case keyShiftF10:
597             {
598                 return "Shift+F10";
599             }
600             case keyShiftF11:
601             {
602                 return "Shift+F11";
603             }
604             case keyShiftF12:
605             {
606                 return "Shift+F12";
607             }
608             case keyAltA:
609             {
610                 return "Alt+A";
611             }
612             case keyAltB:
613             {
614                 return "Alt+B";
615             }
616             case keyAltC:
617             {
618                 return "Alt+C";
619             }
620             case keyAltD:
621             {
622                 return "Alt+D";
623             }
624             case keyAltE:
625             {
626                 return "Alt+E";
627             }
628             case keyAltF:
629             {
630                 return "Alt+F";
631             }
632             case keyAltG:
633             {
634                 return "Alt+G";
635             }
636             case keyAltH:
637             {
638                 return "Alt+H";
639             }
640             case keyAltI:
641             {
642                 return "Alt+I";
643             }
644             case keyAltJ:
645             {
646                 return "Alt+J";
647             }
648             case keyAltK:
649             {
650                 return "Alt+K";
651             }
652             case keyAltL:
653             {
654                 return "Alt+L";
655             }
656             case keyAltM:
657             {
658                 return "Alt+M";
659             }
660             case keyAltN:
661             {
662                 return "Alt+N";
663             }
664             case keyAltO:
665             {
666                 return "Alt+O";
667             }
668             case keyAltP:
669             {
670                 return "Alt+P";
671             }
672             case keyAltQ:
673             {
674                 return "Alt+Q";
675             }
676             case keyAltR:
677             {
678                 return "Alt+R";
679             }
680             case keyAltS:
681             {
682                 return "Alt+S";
683             }
684             case keyAltT:
685             {
686                 return "Alt+T";
687             }
688             case keyAltU:
689             {
690                 return "Alt+U";
691             }
692             case keyAltV:
693             {
694                 return "Alt+V";
695             }
696             case keyAltW:
697             {
698                 return "Alt+W";
699             }
700             case keyAltX:
701             {
702                 return "Alt+X";
703             }
704             case keyAltY:
705             {
706                 return "Alt+Y";
707             }
708             case keyAltZ:
709             {
710                 return "Alt+Z";
711             }
712             case keyAltF1:
713             {
714                 return "Alt+F1";
715             }
716             case keyAltF2:
717             {
718                 return "Alt+F2";
719             }
720             case keyAltF3:
721             {
722                 return "Alt+F3";
723             }
724             case keyAltF4:
725             {
726                 return "Alt+F4";
727             }
728             case keyAltF5:
729             {
730                 return "Alt+F5";
731             }
732             case keyAltF6:
733             {
734                 return "Alt+F6";
735             }
736             case keyAltF7:
737             {
738                 return "Alt+F7";
739             }
740             case keyAltF8:
741             {
742                 return "Alt+F8";
743             }
744             case keyAltF9:
745             {
746                 return "Alt+F9";
747             }
748             case keyAltF10:
749             {
750                 return "Alt+F10";
751             }
752             case keyAltF11:
753             {
754                 return "Alt+F11";
755             }
756             case keyAltF12:
757             {
758                 return "Alt+F12";
759             }
760             case keyControlShiftLeft:
761             {
762                 return "Ctrl+Shift+Left Arrow";
763             }
764             case keyControlShiftRight:
765             {
766                 return "Ctrl+Shift+Right Arrow";
767             }
768             case keyControlShiftHome:
769             {
770                 return "Ctrl+Shift+Home";
771             }
772             case keyControlShiftEnd:
773             {
774                 return "Ctrl+Shift+End";
775             }
776             case keyControlTab:
777             {
778                 return "Ctrl+Tab";
779             }
780             case keyShiftTab:
781             {
782                 return "Shift+Tab";
783             }
784             case keyControlIns:
785             {
786                 return "Ctrl+Insert";
787             }
788             case keyShiftIns:
789             {
790                 return "Shift+Insert";
791             }
792             default:
793             {
794                 if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
795                 {
796                     ustring k(c);
797                     return ToUtf8(ToUpper(k));
798                 }
799                 break;
800             }
801         }
802         return "<unknown key>";
803     }
804 }