Newer
Older
emul / emul_repl.c
#include "emul_repl.h"
#include "emul_inst_exec.h"
#include "emul_inst_decipher.h"
#include "emul_io_std.h"
#include <stdio.h>
#include <string.h>
//#include <ncurses.h>
#include <panel.h>

#define READ_LINE_MAX 64

static int REPL_RUNMODE = REPL_OK;

static WINDOW *win;

// ヒストリ番号表示のため
void emul_repl_show_history(char *input, int line) {
    int i;
    int max_y, max_x;
    int y, x;
    input[0] = '\0';
    emul_inst_dec_get_line(input, line);
    getyx(win, y, x);
    // 1行削除
    move(y, 0);
    clrtoeol();
    // ヒストリ番号表示
    getmaxyx(win, max_y, max_x);
    move(y, max_x-8);
    printw("L[%5d]", line);
    // ヒストリ表示および格納
    move(y, 0);
    printw(">>");
    i = 0;
    while ( input[i] != '\n' && input[i] != '\0') {
        echochar(input[i++]);
    }
    refresh();
}

// ヘルプの表示
void emul_repl_show_help() {
    PANEL *help_panel;
    int y, x;
    char help_title[] = "Display for help";

    endwin();
    set_term(emul_getScr(1));
    refresh();

    // title
    getmaxyx(win, y, x);
    move(1, (x-strlen(help_title))/2);
    printw("%s\n\n", help_title);
    printw("Summary:\n\n");
    printw(" This program is Asembly Emulator.\n\n");
    printw("Command to this Emulator REPL:\n\n");
    printw(" You need to put ':' for swich command mode.\n\n");
    printw("    :help    Display help\n");
    printw("    :quit    Exit repl\n");
    refresh();

    move(y-1, 0);
    printw(" Put any key to exit this help.");
    move(y-1, 0);
    getch();

    endwin();
    set_term(emul_getScr(0));
    refresh();
}

int emul_repl_read(char *input, int *i, int c) {
    static int history;
    // プログラムの行数を取得
    int current_line = emul_inst_dec_get_program_line_max();
    int y, x;
    if (c == '\n') {
        history = 0;
    } else if (c == 127 || c == KEY_BACKSPACE || c == KEY_LEFT) { // Delete and back
        if ( (*i) > 0 ) {
            getyx(win, y, x);
            input[--(*i)] = '\0';
            wmove(win, y, x-1);
            clrtoeol();
            refresh();
        }
    } else if (c == KEY_UP) {
        if (current_line+history > 0) {
            history--;
            emul_repl_show_history(input, current_line+history);
        }
    } else if (c == KEY_DOWN) {
        if (current_line+history < current_line) {
            history++;
            emul_repl_show_history(input, current_line+history);
        }
    } else if (c == KEY_RIGHT) {
        // Nothing do
    } else {
        input[(*i)++] = (char)c;
        input[(*i)] = '\0';
        printw("%c", c);
        refresh();
    }
    return c;
}

// コマンド入力用
void emul_repl_command() {
    char buff[READ_LINE_MAX];
    int index;
    int c;

    int temp_y, temp_x;
    int y, x;
    getyx(win, temp_y, temp_x);
    getmaxyx(win, y, x);
    y -= 1;

    wmove(win, y, 0);
    printw(":");
    refresh();

    buff[0] = '\0';
    while ((c = getch()) != '\n') {
        if (c == KEY_UP || c == KEY_DOWN) continue;
        c = emul_repl_read(buff, &index, c);
    }

    if (strcmp(buff, "help") == 0) emul_repl_show_help();
    if (strcmp(buff, "quit") == 0) REPL_RUNMODE = REPL_EXIT;

    // end
    move(y,0);
    clrtoeol();
    move(temp_y, temp_x);
    refresh();
}

// インタプリンタ入力用
void emul_repl_readline(char input[READ_LINE_MAX]) {
    int c;
    int y, x;
    int temp_y, temp_x;
    int index = 0;
    int history = 0;

    // 何はともあれヌル代入
    input[0] = '\0';

    getyx(win, y, x);
    getmaxyx(win, temp_y, temp_x);
    scrollok(win, TRUE);
    if (y > temp_y-2) {
        scrl(1);
        move(y-1, 0);
    }

    printw(">>");
    refresh();
    noecho();
    cbreak();
    while( (c = getch()) != '\n' ) {
        c = emul_repl_read(input, &index, c);
        if (c == ':') {
            emul_repl_read(input, &index, KEY_BACKSPACE);
            emul_repl_command();
            if (REPL_RUNMODE == REPL_EXIT) break;
        }
        refresh();
    }
    // キャッシュをクリア
    emul_repl_read(input, &index, '\n');
    echo();
    clrtoeol();
    printw("\n");
    refresh();
}

void emul_repl_printline();

void emul_repl_init() {
    emul_inst_exec_init();
    // ウィンドウポインタ取得
    win = emul_getWin();
    keypad(stdscr, TRUE);
}

char *menu[] = {
    "Display help  >>:help",
    "   Exit       >>:quit"
};

void emul_repl_start() {
    char input[READ_LINE_MAX];
    exitcode_t state;
    int y, x;
    char *title = "Wellcome!";
    int i,j;

    emul_repl_init();

    // title
    getmaxyx(win, y, x);
    move(y/2-2, (x-strlen(title))/2);
    printw("%s", title);
    for (i = 0; i < 2; i++) {
        move(y/2+i, (x-strlen(menu[i]))/2);
        printw("%s", menu[i]);
    }
    move(0, 0);
    printw("");
    refresh();
    getch();
    wclear(win);
    refresh();

    while (1) {
        emul_repl_readline(input);
        // フラグを確認
        if (REPL_RUNMODE == REPL_EXIT) break;

        emul_inst_exec_loadline(input);
        state = emul_inst_exec_run();
        if (state == Failed) {
            emul_out_std_debug("Abend exit\n");
        } else if (state == Success) {
            emul_out_std_debug("Sucsess\n");
            break;
        }
    }
}

void emul_repl_end() {
    emul_inst_exec_end();
}