#
# Simple Interactive Text I/O -- 文字模式下的簡單繪圖副程式庫.
#
# 主要供其他程式叫用, 所以通常從其他 perl 程式內用
# require "./sitio"; 來引用. 請參考 15puzzle 與 knight 兩範例程式
#
#
# 本程式只是 perl 教學範例 (詳見 http://www.cyut.edu.tw/~ckhung/b/pl/)
# 所以 (1) 功能相當不完整 (2) 看不懂裡面在做什麼也沒有關係.
# 如果真的要在文字模式下寫大的程式, 建議用 ncurses 甚至 cdk, 見
# http://www.cyut.edu.tw/~ckhung/b/mi/ 其中的
# "反樸歸真: 文字模式下的程式設計"

# 前半段的功能, 其實用 perl 內建模組 Term::ANSIColor 更方便。

#################################################################
# 用 ANSI escape sequence 來製造文字模式下的特殊效果.
# 注意: 使用下列副程式之前, 必須先執行 $| = 1; (程式最開始時執行一次就可以了.)

# 清除螢幕
sub clearscr {
    print "\x1b[2J";
}

# 把遊標移到第 $row 列第 $col 行
sub gotorc {
    my ($row, $col) = @_;

    print "\x1b[${row};${col}H";
}

# 類似 printf, 但可以指定印出來的字串屬性, 例如顏色, 反白, 底線, ...
sub aprintf {
    my ($attr, $fmt, @rest) = @_;

    print "\x1b[${attr}m";
    printf $fmt, @rest;
    print "\x1b[m";
}

#################################################################
# (與 ANSI escape sequence 無關, 但經常搭配使用)
# 以下程式參考 "Perl Cookbook" 15.8

my ($term, $old_flag);

BEGIN {
    use POSIX qw(:termios_h);

    $term = POSIX::Termios->new();
    $term->getattr(fileno(STDIN));
    $old_flag = $term->getlflag();

    # 把鍵盤設定成 "立即反應" 的模式
    my ($lflag) = ECHO | ICANON;
    $term->setlflag($old_flag & ~$lflag);
    $term->setcc(VTIME, 1);
    $term->setattr(fileno(STDIN), TCSANOW);

    # 凡是用到 ANSI escape sequence 來控制螢幕, 都一定要先執行下面這句.
    # 因為平時要印到 stdout 的東西會被 buffer 起來, 等累積夠了才一次輸出,
    # 無法立即看到移動遊標等效果.
    $| = 1;		
}

END {
    # 把鍵盤設定回內定的 "讀一列才反應" 的模式
    $term->setlflag($old_flag);
    $term->setcc(VTIME, 0);
    $term->setattr(fileno(STDIN), TCSANOW);
}

# 從鍵盤上讀入一個鍵.
sub getkey {
    my ($c);

    sysread(STDIN, $c, 1);
    return $c;
}

1;

