From bb031b1b823f3d37cfd25ff4d39f705bb6abd5d9 Mon Sep 17 00:00:00 2001 From: Deon George Date: Wed, 31 Jul 2019 20:19:41 +0800 Subject: [PATCH] Initial work on Frame Edit --- app/Classes/Control/EditFrame.php | 182 ++++++++++++++++++++++++++++++ app/Classes/Frame.php | 23 ++++ app/Classes/Frame/Ansi.php | 12 ++ app/Classes/Parser.php | 25 ++++ app/Classes/Parser/Ansi.php | 34 ++++-- app/Classes/Server/Ansi.php | 3 +- app/Classes/Server/Videotex.php | 1 + 7 files changed, 269 insertions(+), 11 deletions(-) create mode 100644 app/Classes/Control/EditFrame.php diff --git a/app/Classes/Control/EditFrame.php b/app/Classes/Control/EditFrame.php new file mode 100644 index 0000000..50f91aa --- /dev/null +++ b/app/Classes/Control/EditFrame.php @@ -0,0 +1,182 @@ +so->co->send(CLS.HOME.DOWN.CON); + + // @todo Add page number + "EDIT" (prob only required for login pages which dont show page num) + $this->so->co->send($this->fo->raw().$this->so->moveCursor(1,2)); + + $this->updateBaseline(); + } + + public function handle(string $read) + { + static $esc = FALSE; + static $brace = FALSE; + static $out = ''; + static $key = ''; + + $out .= $read; + + switch ($read) + { + case 'A': + if ($esc AND $brace) + { + $this->y--; + if ($this->y < 1) { + $this->y = 1; + $out = ''; + } + + $brace = $esc = FALSE; + } + break; + + case 'B': + if ($esc AND $brace) + { + $this->y++; + if ($this->y > $this->fo->frame_length()) { + $this->y = $this->fo->frame_length(); + $out = ''; + } + + $brace =$esc = FALSE; + } + break; + + case 'C': + if ($esc AND $brace) + { + $this->x++; + if ($this->x > $this->fo->frame_width()) { + $this->x = $this->fo->frame_width(); + $out = ''; + } + + $brace =$esc = FALSE; + } + break; + + case 'D': + if ($esc AND $brace) + { + $this->x--; + if ($this->x < 1) { + $this->x = 1; + $out = ''; + } + + $brace = $esc = FALSE; + } + break; + + case '[': + if ($esc) + $brace = TRUE; + break; + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '0': + if ($esc AND $brace) { + $key .= $read; + } else { + $this->x++; + } + break; + + case '~': + if ($esc AND $brace) + { + switch ($key) + { + // F9 Pressed + case 20: + break; + + // F10 Pressed + case 21: + $this->complete = TRUE; + $this->state = ['action'=>ACTION_GOTO,'mode'=>NULL]; + break; + } + + $brace = $esc = FALSE; + $key = ''; + } + break; + + case ESC; + $esc = TRUE; + break; + + case LF: $this->y++; break; + case CR; $this->x = 1; break; + + default: + if ($esc) + $esc = FALSE; + + $this->x++; + } + + if (! $esc) + { + printf(" . SENDING OUT: %s\n",$out); + $this->so->co->send($out); + $this->updateBaseline(); + $out = ''; + } + + printf(" . X:%d,Y:%d,C:%s,ESC:%s\n", + $this->x, + $this->y, + (ord($read) < 32 ? '.' : $read), + ($esc AND $brace) ? 'TRUE' : 'FALSE'); + + return $read; + } + + public function updateBaseline() + { + $this->so->sendBaseline( + $this->so->co, + sprintf('%02.0f:%02.0f]%s'.RESET.'[', + $this->y, + $this->x, + ($this->fo->attr($this->x,$this->y) != '-' ? ESC.'['.$this->fo->attr($this->x,$this->y) : '').$this->fo->char($this->x,$this->y), + ) + ); + } + + public function process() + { + dump(__METHOD__); + } +} \ No newline at end of file diff --git a/app/Classes/Frame.php b/app/Classes/Frame.php index 341c190..380635c 100644 --- a/app/Classes/Frame.php +++ b/app/Classes/Frame.php @@ -130,6 +130,18 @@ abstract class Frame ->limit(9); } + /** + * Return the attributes for character at position + * + * @param int $x + * @param int $y + * @return string + */ + public function attr(int $x,int $y): string + { + return $this->po->attr($x,$y); + } + /** * Frame Created Date */ @@ -138,6 +150,17 @@ abstract class Frame return $this->fo->created_at; } + /** + * Return the character at a specific position + * @param $x + * @param $y + * @return string + */ + public function char(int $x,int $y): string + { + return $this->po->char($x,$y); + } + /** * Return fields within the frame. */ diff --git a/app/Classes/Frame/Ansi.php b/app/Classes/Frame/Ansi.php index 127137c..d4e492c 100644 --- a/app/Classes/Frame/Ansi.php +++ b/app/Classes/Frame/Ansi.php @@ -38,4 +38,16 @@ class Ansi extends Frame public static function strlenv($text):int { return strlen($text ? preg_replace('/'.ESC.'\[[0-9;?]+[a-zA-Z]/','',$text) : $text); } + + // @todo make abstract + /** + * This function returns the frame content, raw + * + * @return string + */ + public function raw(): string + { + // We need to convert any ESC's, not next to [ into a character, otherwise we are off by one + return preg_replace('/'.ESC.'([^\[])/',"|$1",$this->fo->content); + } } \ No newline at end of file diff --git a/app/Classes/Parser.php b/app/Classes/Parser.php index fc39e24..4f11c89 100644 --- a/app/Classes/Parser.php +++ b/app/Classes/Parser.php @@ -36,5 +36,30 @@ abstract class Parser return $this->output; } + /** + * Return the character at a specific position + * + * @param int $x + * @param int $y + * @return string + */ + public function char(int $x,int $y): string + { + $y += 1; + + return (isset($this->frame_content[$y]) AND isset($this->frame_content[$y][$x])) + ? $this->frame_content[$y][$x] + : ' '; + } + + public function attr(int $x,int $y) + { + $y += 1; + + return (isset($this->frame_data[$y]) AND isset($this->frame_data[$y][$x])) + ? implode(';',$this->frame_data[$y][$x]).'m' + : '-'; + } + abstract protected function parse(int $startline,string $content,int $width): string; } \ No newline at end of file diff --git a/app/Classes/Parser/Ansi.php b/app/Classes/Parser/Ansi.php index 5721704..9e5ef7b 100644 --- a/app/Classes/Parser/Ansi.php +++ b/app/Classes/Parser/Ansi.php @@ -39,6 +39,11 @@ class Ansi extends AbstractParser { $y = $startline; $output = ''; + // Default Attributes + $f = 39; + $b = 49; + $i = 0; + // Scan the frame for a field start for ($c=0; $c<=strlen($content); $c++) { @@ -76,17 +81,25 @@ class Ansi extends AbstractParser { $advance += strlen($matches[0])-1; $chars .= $matches[0]; - if (! isset($this->frame_data[$y][$x])) - $this->frame_data[$y][$x] = ''; - else - $this->frame_data[$y][$x] .= '|'; - - $this->frame_data[$y][$x] .= $matches[0]; - switch ($matches[2]) { - // We ignore 'm' they are color CSIs - case 'm': break; + // Color CSIs + case 'm': + foreach (explode(';',chop($matches[0],'m')) as $num) + { + if ($num >= 0 AND $num <= 8) + { + $i = $num; + $f = 39; + $b = 49; + } elseif ($num >= 30 AND $num <= 39) + $f = $num; + elseif ($num >= 40 AND $num <= 49) + $b = $num; + } + break; + + // Advance characters case 'C': $x += $matches[1]; // Advance our position break; @@ -127,10 +140,11 @@ class Ansi extends AbstractParser { break; default: + $this->frame_data[$y][$x] = ['i'=>$i,'f'=>$f,'b'=>$b]; + $this->frame_content[$y][$x] = $byte; $x++; } - $this->frame_content[$y][$x] = $byte; $output .= $byte; if ($advance) { diff --git a/app/Classes/Server/Ansi.php b/app/Classes/Server/Ansi.php index dcf8b2f..54726b0 100644 --- a/app/Classes/Server/Ansi.php +++ b/app/Classes/Server/Ansi.php @@ -27,6 +27,7 @@ class Ansi extends AbstractServer { define('SPACE', ' '); // Space (for compatibility with Videotex) // NOTE: This consts are effective output + define('RESET', ESC.'[0;39;49m'); define('RED', ESC.'[0;31m'); define('GREEN', ESC.'[0;32m'); define('YELLOW', ESC.'[1;33m'); @@ -64,7 +65,7 @@ class Ansi extends AbstractServer { // Abstract function public function sendBaseline($client,$text,$reposition=FALSE) { - $client->send(CSAVE.ESC.'[24;0f'.$text. + $client->send(CSAVE.ESC.'[24;0f'.RESET.$text. ($this->blp > $this->fo->strlenv($text) ? str_repeat(' ',$this->blp-$this->fo->strlenv($text)). ($reposition ? ESC.'[24;0f'.str_repeat(RIGHT,$this->fo->strlenv($text)) : CRESTORE) diff --git a/app/Classes/Server/Videotex.php b/app/Classes/Server/Videotex.php index 2069480..1317665 100644 --- a/app/Classes/Server/Videotex.php +++ b/app/Classes/Server/Videotex.php @@ -26,6 +26,7 @@ class Videotex extends AbstractServer { define('SPACE', ''); // Space // NOTE: This consts are effective output + define('RESET', ''); define('RED', ESC.'A'); define('GREEN', ESC.'B'); define('YELLOW', ESC.'C');