1057 lines
34 KiB
C
1057 lines
34 KiB
C
#include "key.h"
|
||
#include <conio.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
|
||
#define MAX_COLUMN 20
|
||
#define MAX_ROW 20
|
||
#define MAX_COLUMN_WIDTH 10
|
||
#define MAX_DATA_LENGTH 100
|
||
#define MAX_TICK 200
|
||
#define MAX_MESSAGE_LENGTH 100
|
||
#define FUNCTION_NUM 8
|
||
|
||
int tick = 0;
|
||
int current_x = 0;
|
||
int current_y = 0;
|
||
int alive = 1;
|
||
int select_mode = 0;
|
||
int select_entry = 0;
|
||
int input_mode = 0;
|
||
|
||
char functions[FUNCTION_NUM][100] = {"Save", "Load", "Sum", "Average",
|
||
"Max", "Min", "Sort", "Exit"};
|
||
|
||
char *message = "Hi~";
|
||
|
||
typedef struct {
|
||
int current_width;
|
||
int current_height;
|
||
int column_width[MAX_COLUMN];
|
||
char data[MAX_ROW][MAX_COLUMN][MAX_DATA_LENGTH];
|
||
} TableInfo;
|
||
|
||
int max(int a, int b) { return a > b ? a : b; }
|
||
|
||
int min(int a, int b) { return a < b ? a : b; }
|
||
|
||
int int_length(int num) {
|
||
if (num == 0)
|
||
return 1;
|
||
int length = 0;
|
||
while (num) {
|
||
num /= 10;
|
||
length++;
|
||
}
|
||
return length;
|
||
}
|
||
|
||
int is_string_all_number(char *str) {
|
||
int length = strlen(str);
|
||
for (int i = 0; i < length; i++) {
|
||
if (str[i] < '0' || str[i] > '9') {
|
||
return 0;
|
||
}
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
int is_index_all_number(TableInfo *table, int type, int index) {
|
||
if (type == 0) {
|
||
// 行
|
||
index = index - 1;
|
||
for (int i = 0; i < table->current_width; i++) {
|
||
if (strlen(table->data[index][i]) > 0) {
|
||
if (!is_string_all_number(table->data[index][i])) {
|
||
return 0;
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
// 列
|
||
index = index - 'A';
|
||
for (int i = 0; i < table->current_height; i++) {
|
||
if (strlen(table->data[i][index]) > 0) {
|
||
if (!is_string_all_number(table->data[i][index])) {
|
||
return 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
// 交换两列
|
||
void changeTwoColumn(TableInfo *table, int column1, int column2) {
|
||
// 验证两列是否合法且不等
|
||
if (column1 == column2 || column1 < 0 || column2 < 0 ||
|
||
column1 >= table->current_width || column2 >= table->current_width) {
|
||
return;
|
||
}
|
||
char tmp[MAX_DATA_LENGTH];
|
||
for (int i = 0; i < table->current_height; i++) {
|
||
strcpy(tmp, table->data[i][column1]);
|
||
strcpy(table->data[i][column1], table->data[i][column2]);
|
||
strcpy(table->data[i][column2], tmp);
|
||
}
|
||
}
|
||
|
||
// 交换两行
|
||
void changeTwoRow(TableInfo *table, int row1, int row2) {
|
||
// 验证两行是否合法且不等
|
||
if (row1 == row2 || row1 < 0 || row2 < 0 || row1 >= table->current_height ||
|
||
row2 >= table->current_height) {
|
||
return;
|
||
}
|
||
char tmp[MAX_DATA_LENGTH];
|
||
for (int i = 0; i < table->current_width; i++) {
|
||
strcpy(tmp, table->data[row1][i]);
|
||
strcpy(table->data[row1][i], table->data[row2][i]);
|
||
strcpy(table->data[row2][i], tmp);
|
||
}
|
||
}
|
||
|
||
int str_cmp(char *str1, char *str2, int case_sensitive) {
|
||
if (case_sensitive) {
|
||
return strcmp(str1, str2);
|
||
} else {
|
||
char *tmp_str1 = (char *)malloc(sizeof(char) * strlen(str1));
|
||
char *tmp_str2 = (char *)malloc(sizeof(char) * strlen(str2));
|
||
strcpy(tmp_str1, str1);
|
||
strcpy(tmp_str2, str2);
|
||
for (int i = 0; i < strlen(tmp_str1); i++) {
|
||
if (tmp_str1[i] >= 'A' && tmp_str1[i] <= 'Z') {
|
||
tmp_str1[i] += 32;
|
||
}
|
||
}
|
||
for (int i = 0; i < strlen(tmp_str2); i++) {
|
||
if (tmp_str2[i] >= 'A' && tmp_str2[i] <= 'Z') {
|
||
tmp_str2[i] += 32;
|
||
}
|
||
}
|
||
int result = strcmp(tmp_str1, tmp_str2);
|
||
free(tmp_str1);
|
||
free(tmp_str2);
|
||
return result;
|
||
}
|
||
}
|
||
|
||
int check_index_valid(TableInfo *table, char *index) {
|
||
// 合法的 index 应该是 A1,A23 这样的格式
|
||
int length = strlen(index);
|
||
if (length == 0) {
|
||
return 0;
|
||
}
|
||
|
||
if (index[0] >= 'A' && index[0] <= 'A' + table->current_width - 1) {
|
||
// 列号合法
|
||
int row = 0;
|
||
for (int i = 1; i < length; i++) {
|
||
if (index[i] < '0' || index[i] > '9') {
|
||
return 0;
|
||
}
|
||
row = row * 10 + index[i] - '0';
|
||
}
|
||
if (row >= 1 && row <= table->current_height) {
|
||
return 1;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
// 传入实际的 index
|
||
int check_valid_formatter(TableInfo *table, int x, int y) {
|
||
// 合法的公示应该以 = 开头,并且只包含 + - 和
|
||
char *data = malloc(sizeof(char) * MAX_DATA_LENGTH);
|
||
strcpy(data, table->data[y][x]);
|
||
if (data[0] != '=') {
|
||
return 0;
|
||
}
|
||
int length = strlen(data);
|
||
char *tmp_data = malloc(sizeof(char) * MAX_DATA_LENGTH);
|
||
for (int i = 1; i < length; i++) {
|
||
if (data[i] == ' ')
|
||
continue;
|
||
// 获取 =,-,+,\n 之间的字符串
|
||
int j = i;
|
||
while (j < length && data[j] != '=' && data[j] != '-' &&
|
||
data[j] != '+' && data[j] != '\n') {
|
||
tmp_data[j - i] = data[j];
|
||
j++;
|
||
}
|
||
tmp_data[j - i] = '\0';
|
||
// 判断是否是合法的 index
|
||
if (tmp_data[0] >= 'A' && tmp_data[0] <= 'Z') {
|
||
if (!check_index_valid(table, tmp_data))
|
||
return 0;
|
||
} else {
|
||
for (int k = 0; k < j - i; k++) {
|
||
if (tmp_data[k] < '0' || tmp_data[k] > '9') {
|
||
return 0;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
// 获取是行还是列
|
||
int get_index_type(int index) { return index >> 7; }
|
||
|
||
// 获取具体的值
|
||
int get_index_value(int index) { return index & 0b01111111; }
|
||
|
||
// 进入选择模式,选择某行或某列
|
||
int start_select_index(int entry) {
|
||
message = "Select a row or column";
|
||
current_x = 0;
|
||
current_y = 1;
|
||
select_mode = 1;
|
||
select_entry = entry;
|
||
}
|
||
|
||
// 退出选择模式
|
||
void end_select_index(TableInfo *table) {
|
||
// 一个 8 位数字
|
||
// 最高位: 0 代表行 1 代表列
|
||
// 低 7 位: 代表行号或列号对应字符的 ASCII 码
|
||
int select_value = 0;
|
||
if (current_x == 0) {
|
||
// x = 0 表示选择行
|
||
select_value = 0b00000000 | current_y;
|
||
} else {
|
||
// x > 0 表示选择列
|
||
select_value = 0b10000000 | (current_x + 'A' - 1);
|
||
}
|
||
int type = get_index_type(select_value);
|
||
int value = get_index_value(select_value);
|
||
|
||
int ascii_sort = 0;
|
||
// 0 代表不区分大小写,1 代表区分大小写
|
||
int case_sensitive = 0;
|
||
|
||
// 判断是否和数字操作有关
|
||
if (select_entry == 2 || select_entry == 3 || select_entry == 4 ||
|
||
select_entry == 5 || select_entry == 6) {
|
||
int valid = is_index_all_number(table, type, value);
|
||
if (!valid) {
|
||
if (select_entry == 6) {
|
||
ascii_sort = 1;
|
||
message =
|
||
"This row or column is not all number, use ASCII to "
|
||
"sort!\n Do you want to use Case Sensitive? ([Y]/n): ";
|
||
// 等待完善:选择大小写敏感
|
||
// char tmp;
|
||
// input_mode = 1;
|
||
// scanf("%c", &tmp);
|
||
// input_mode = 0;
|
||
// if (tmp == 'n' || tmp == 'N') {
|
||
// case_sensitive = 0;
|
||
// } else {
|
||
// case_sensitive = 1;
|
||
// }
|
||
} else {
|
||
message = "This row or column is not all number!";
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (select_entry == 2) {
|
||
// sum
|
||
int sum = 0;
|
||
if (type == 0) {
|
||
// 行
|
||
value = value - 1;
|
||
for (int i = 0; i < table->current_width; i++) {
|
||
if (strlen(table->data[value][i]) > 0) {
|
||
sum += atoi(table->data[value][i]);
|
||
}
|
||
}
|
||
} else {
|
||
// 列
|
||
value = value - 'A';
|
||
for (int i = 0; i < table->current_height; i++) {
|
||
if (strlen(table->data[i][value]) > 0) {
|
||
sum += atoi(table->data[i][value]);
|
||
}
|
||
}
|
||
}
|
||
char *tmp_message = (char *)malloc(sizeof(char) * MAX_MESSAGE_LENGTH);
|
||
sprintf(tmp_message, "Sum: %d", sum);
|
||
message = tmp_message;
|
||
} else if (select_entry == 3) {
|
||
// average
|
||
int sum = 0;
|
||
int count = 0;
|
||
if (type == 0) {
|
||
// 行
|
||
value = value - 1;
|
||
for (int i = 0; i < table->current_width; i++) {
|
||
if (strlen(table->data[value][i]) > 0) {
|
||
sum += atoi(table->data[value][i]);
|
||
count++;
|
||
}
|
||
}
|
||
} else {
|
||
// 列
|
||
value = value - 'A';
|
||
for (int i = 0; i < table->current_height; i++) {
|
||
if (strlen(table->data[i][value]) > 0) {
|
||
sum += atoi(table->data[i][value]);
|
||
count++;
|
||
}
|
||
}
|
||
}
|
||
char *tmp_message = (char *)malloc(sizeof(char) * MAX_MESSAGE_LENGTH);
|
||
sprintf(tmp_message, "Average: %f", (double)sum / count);
|
||
message = tmp_message;
|
||
} else if (select_entry == 4) {
|
||
// max
|
||
int max_ = -0x7fffffff;
|
||
if (type == 0) {
|
||
// 行
|
||
value = value - 1;
|
||
for (int i = 0; i < table->current_width; i++) {
|
||
if (strlen(table->data[value][i]) > 0) {
|
||
max_ = atoi(table->data[value][i]) > max_
|
||
? atoi(table->data[value][i])
|
||
: max_;
|
||
}
|
||
}
|
||
} else {
|
||
// 列
|
||
value = value - 'A';
|
||
for (int i = 0; i < table->current_height; i++) {
|
||
if (strlen(table->data[i][value]) > 0) {
|
||
max_ = atoi(table->data[i][value]) > max_
|
||
? atoi(table->data[i][value])
|
||
: max_;
|
||
}
|
||
}
|
||
}
|
||
char *tmp_message = (char *)malloc(sizeof(char) * MAX_MESSAGE_LENGTH);
|
||
sprintf(tmp_message, "Max: %d", max_);
|
||
message = tmp_message;
|
||
} else if (select_entry == 5) {
|
||
// min
|
||
int min_ = 0x7fffffff;
|
||
if (type == 0) {
|
||
// 行
|
||
value = value - 1;
|
||
for (int i = 0; i < table->current_width; i++) {
|
||
if (strlen(table->data[value][i]) > 0) {
|
||
min_ = atoi(table->data[value][i]) < min_
|
||
? atoi(table->data[value][i])
|
||
: min_;
|
||
}
|
||
}
|
||
} else {
|
||
// 列
|
||
value = value - 'A';
|
||
for (int i = 0; i < table->current_height; i++) {
|
||
if (strlen(table->data[i][value]) > 0) {
|
||
min_ = atoi(table->data[i][value]) < min_
|
||
? atoi(table->data[i][value])
|
||
: min_;
|
||
}
|
||
}
|
||
}
|
||
char *tmp_message = (char *)malloc(sizeof(char) * MAX_MESSAGE_LENGTH);
|
||
sprintf(tmp_message, "Min: %d", min_);
|
||
message = tmp_message;
|
||
} else if (select_entry == 6) {
|
||
// sort
|
||
if (type == 0) {
|
||
// 行
|
||
value = value - 1;
|
||
for (int i = 0; i < table->current_width; i++) {
|
||
for (int j = i + 1; j < table->current_width; j++) {
|
||
if (!ascii_sort) {
|
||
if (atoi(table->data[value][i]) >
|
||
atoi(table->data[value][j])) {
|
||
changeTwoColumn(table, i, j);
|
||
}
|
||
message = "Sorted by number!";
|
||
} else {
|
||
if (str_cmp(table->data[value][i],
|
||
table->data[value][j],
|
||
case_sensitive) > 0) {
|
||
changeTwoColumn(table, i, j);
|
||
}
|
||
message = "Sorted by ASCII!";
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
// 列
|
||
value = value - 'A';
|
||
for (int i = 0; i < table->current_height; i++) {
|
||
for (int j = i + 1; j < table->current_height; j++) {
|
||
if (!ascii_sort) {
|
||
if (atoi(table->data[i][value]) >
|
||
atoi(table->data[j][value])) {
|
||
changeTwoRow(table, i, j);
|
||
}
|
||
message = "Sorted by number!";
|
||
} else {
|
||
if (str_cmp(table->data[i][value],
|
||
table->data[j][value],
|
||
case_sensitive) > 0) {
|
||
changeTwoRow(table, i, j);
|
||
}
|
||
message = "Sorted by ASCII!";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
// 选择行或列
|
||
if (type == 0) {
|
||
// 行
|
||
value = value - 1;
|
||
char *tmp_message =
|
||
(char *)malloc(sizeof(char) * MAX_MESSAGE_LENGTH);
|
||
sprintf(tmp_message, "Selected row: %d", value + 1);
|
||
message = tmp_message;
|
||
} else {
|
||
// 列
|
||
value = value - 'A';
|
||
char *tmp_message =
|
||
(char *)malloc(sizeof(char) * MAX_MESSAGE_LENGTH);
|
||
sprintf(tmp_message, "Selected column: %c", value + 'A');
|
||
message = tmp_message;
|
||
}
|
||
}
|
||
|
||
// char *tmp_message = (char *)malloc(sizeof(char) * MAX_MESSAGE_LENGTH);
|
||
// sprintf(tmp_message, "Selected: %d,%c", get_index_type(select_value),
|
||
// get_index_value(select_value));
|
||
// message = tmp_message;
|
||
|
||
select_mode = 0;
|
||
current_y = -1;
|
||
current_x = select_entry;
|
||
}
|
||
|
||
char *int_to_string(int num) {
|
||
char *str = (char *)malloc(sizeof(char) * 100);
|
||
sprintf(str, "%d", num);
|
||
return str;
|
||
}
|
||
|
||
void init_table(int width, int height, int column_width, TableInfo *table) {
|
||
table->current_width = width;
|
||
table->current_height = height;
|
||
for (int i = 0; i < width; i++) {
|
||
table->column_width[i] = column_width;
|
||
}
|
||
for (int i = 0; i < height; i++) {
|
||
for (int j = 0; j < width; j++) {
|
||
table->data[i][j][0] = '\0';
|
||
}
|
||
}
|
||
}
|
||
|
||
int cal_formula(TableInfo *table, int x, int y) {
|
||
char *data = malloc(sizeof(char) * MAX_DATA_LENGTH);
|
||
strcpy(data, table->data[y][x]);
|
||
int length = strlen(data);
|
||
char *tmp_data = malloc(sizeof(char) * MAX_DATA_LENGTH);
|
||
int result = 0;
|
||
for (int i = 1; i < length; i++) {
|
||
if (data[i] == ' ')
|
||
continue;
|
||
// 标注 -
|
||
int minus = 0;
|
||
// 获取 =,-,+,\n 之间的字符串
|
||
int j = i;
|
||
while (j < length && data[j] != '=' && data[j] != '-' &&
|
||
data[j] != '+' && data[j] != '\n') {
|
||
tmp_data[j - i] = data[j];
|
||
j++;
|
||
}
|
||
tmp_data[j - i] = '\0';
|
||
// 判断是否是 -
|
||
if (data[i - 1] == '-') {
|
||
minus = 1;
|
||
}
|
||
// 判断是否是合法的 index
|
||
if (tmp_data[0] >= 'A' && tmp_data[0] <= 'Z') {
|
||
if (!check_index_valid(table, tmp_data))
|
||
return -1;
|
||
// 0 表示 列,剩下的是行
|
||
int col = tmp_data[0] - 'A';
|
||
int row = 0;
|
||
for (int k = 1; k < strlen(tmp_data); k++) {
|
||
row = row * 10 + tmp_data[k] - '0';
|
||
}
|
||
// 判断 table->data[row - 1][col] 是否是数字
|
||
if (strlen(table->data[row - 1][col]) == 0) {
|
||
return -1;
|
||
}
|
||
if (!is_string_all_number(table->data[row - 1][col])) {
|
||
return -1;
|
||
}
|
||
if (minus) {
|
||
result -= atoi(table->data[row - 1][col]);
|
||
} else {
|
||
result += atoi(table->data[row - 1][col]);
|
||
}
|
||
} else {
|
||
for (int k = 0; k < j - i; k++) {
|
||
if (tmp_data[k] < '0' || tmp_data[k] > '9') {
|
||
return -1;
|
||
}
|
||
}
|
||
if (minus) {
|
||
result -= atoi(tmp_data);
|
||
} else {
|
||
result += atoi(tmp_data);
|
||
}
|
||
}
|
||
i += j - i;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
void printTable(TableInfo *table) {
|
||
system("cls");
|
||
printf("Table v0.2 by Luthics\n");
|
||
int max_l = int_length(table->current_height) + 1;
|
||
// render table
|
||
for (int i = -1; i < table->current_height; i++) {
|
||
for (int j = -1; j < table->current_width; j++) {
|
||
printf("+");
|
||
if (j == -1) {
|
||
for (int k = 0; k < max_l; k++) {
|
||
printf("-");
|
||
}
|
||
continue;
|
||
}
|
||
for (int k = 0; k < table->column_width[j]; k++) {
|
||
printf("-");
|
||
}
|
||
}
|
||
printf("+\n");
|
||
if (i == -1) {
|
||
// 输出 A-Z 的列名
|
||
for (int j = -1; j < table->current_width; j++) {
|
||
if (j == -1) {
|
||
printf("|");
|
||
for (int k = 0; k < max_l; k++) {
|
||
printf(" ");
|
||
}
|
||
continue;
|
||
}
|
||
printf("|");
|
||
for (int k = 0; k < table->column_width[j] - 1; k++) {
|
||
printf(" ");
|
||
}
|
||
if (select_mode) {
|
||
if (current_x - 1 == j && current_y == 0) {
|
||
// RED
|
||
printf("\033[31m");
|
||
// BOLD
|
||
printf("\033[1m");
|
||
}
|
||
}
|
||
printf("%c", 'A' + j);
|
||
if (select_mode) {
|
||
if (current_x - 1 == j && current_y == 0) {
|
||
// RESET
|
||
printf("\033[0m");
|
||
}
|
||
}
|
||
}
|
||
printf("|\n");
|
||
continue;
|
||
}
|
||
for (int j = -1; j < table->current_width; j++) {
|
||
if (j == -1) {
|
||
printf("|");
|
||
int data_length = int_length(i + 1);
|
||
for (int k = 0; k < max_l - data_length; k++) {
|
||
printf(" ");
|
||
}
|
||
if (select_mode) {
|
||
if (current_x == 0 && current_y == i + 1) {
|
||
// RED
|
||
printf("\033[31m");
|
||
// BOLD
|
||
printf("\033[1m");
|
||
}
|
||
}
|
||
printf("%d", i + 1);
|
||
if (select_mode) {
|
||
if (current_x == 0 && current_y == i + 1) {
|
||
// RESET
|
||
printf("\033[0m");
|
||
}
|
||
}
|
||
continue;
|
||
}
|
||
printf("|");
|
||
int data_length =
|
||
table->data[i][j] == NULL ? 0 : strlen(table->data[i][j]);
|
||
|
||
if (data_length == 0) {
|
||
if (i == current_y && j == current_x && !select_mode) {
|
||
printf("_");
|
||
} else {
|
||
printf(" ");
|
||
}
|
||
for (int k = 0; k < table->column_width[j] - 1; k++) {
|
||
printf(" ");
|
||
}
|
||
} else {
|
||
int formatter = 0;
|
||
if (table->data[i][j][0] == '=') {
|
||
formatter = 1;
|
||
}
|
||
int add_ = 0;
|
||
if (select_mode) {
|
||
if (current_x == j + 1 || current_y == i + 1) {
|
||
// RED
|
||
printf("\033[31m");
|
||
// BOLD
|
||
printf("\033[1m");
|
||
}
|
||
} else if (i == current_y && j == current_x) {
|
||
// RED
|
||
printf("\033[31m");
|
||
// BOLD
|
||
printf("\033[1m");
|
||
} else if (formatter) {
|
||
// BLUE
|
||
printf("\033[34m");
|
||
// BOLD
|
||
printf("\033[1m");
|
||
}
|
||
int formatter_success = 0;
|
||
if (formatter && !select_mode &&
|
||
!(i == current_y && j == current_x)) {
|
||
// todo 先计算后渲染,修复列宽不合适的bug
|
||
int data = cal_formula(table, j, i);
|
||
if (data == -1) {
|
||
formatter_success = 0;
|
||
} else {
|
||
char *tmp_data =
|
||
(char *)malloc(sizeof(char) * MAX_DATA_LENGTH);
|
||
sprintf(tmp_data, "%d", data);
|
||
data_length = strlen(tmp_data);
|
||
printf("%s", tmp_data);
|
||
table->column_width[j] =
|
||
max(table->column_width[j], strlen(tmp_data));
|
||
formatter_success = 1;
|
||
}
|
||
}
|
||
if (!formatter_success) {
|
||
for (int k = 0; k < data_length; k++) {
|
||
printf("%c", table->data[i][j][k]);
|
||
}
|
||
}
|
||
if (select_mode) {
|
||
if (current_x == j + 1 || current_y == i + 1) {
|
||
// RESET
|
||
printf("\033[0m");
|
||
}
|
||
} else if (i == current_y && j == current_x) {
|
||
// RESET
|
||
printf("\033[0m");
|
||
// 如果还有空间,就补上下划线
|
||
if (table->column_width[j] - data_length > 0) {
|
||
printf("_");
|
||
add_ = 1;
|
||
}
|
||
} else if (formatter) {
|
||
// Reset
|
||
printf("\033[0m");
|
||
}
|
||
if (formatter) {
|
||
// 补上空格
|
||
for (int k = 0; k < table->column_width[j] - data_length;
|
||
k++) {
|
||
printf(" ");
|
||
}
|
||
} else {
|
||
for (int k = 0;
|
||
k < table->column_width[j] - data_length - add_; k++) {
|
||
printf(" ");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
printf("|\n");
|
||
}
|
||
for (int j = -1; j < table->current_width; j++) {
|
||
if (j == -1) {
|
||
printf("+");
|
||
for (int k = 0; k < max_l; k++) {
|
||
printf("-");
|
||
}
|
||
continue;
|
||
}
|
||
printf("+");
|
||
for (int k = 0; k < table->column_width[j]; k++) {
|
||
printf("-");
|
||
}
|
||
}
|
||
printf("+\n");
|
||
|
||
// render functions
|
||
for (int i = 0; i < FUNCTION_NUM; i++) {
|
||
if (current_y == -1 && i == current_x) {
|
||
// RED
|
||
printf("\033[31m");
|
||
// BOLD
|
||
printf("\033[1m");
|
||
}
|
||
printf("%s", functions[i]);
|
||
if (current_y == -1 && i == current_x) {
|
||
// RESET
|
||
printf("\033[0m");
|
||
}
|
||
if (i != FUNCTION_NUM - 1) {
|
||
printf(" ");
|
||
}
|
||
}
|
||
printf("\n");
|
||
printf("%s\n", message);
|
||
}
|
||
|
||
int is_data_file_exist() {
|
||
FILE *fp = fopen("table.dat", "r");
|
||
if (fp == NULL) {
|
||
return 0;
|
||
} else {
|
||
fclose(fp);
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
TableInfo load_table_from_file(char *filename) {
|
||
TableInfo table;
|
||
FILE *fp = fopen(filename, "r");
|
||
fread(&table, sizeof(TableInfo), 1, fp);
|
||
fclose(fp);
|
||
return table;
|
||
}
|
||
|
||
int save_table_to_file(char *filename, TableInfo table) {
|
||
FILE *fp = fopen(filename, "w");
|
||
fwrite(&table, sizeof(TableInfo), 1, fp);
|
||
fclose(fp);
|
||
return 0;
|
||
}
|
||
|
||
void setCell(TableInfo *table, int row, int column, char *data) {
|
||
if (row >= table->current_height || column >= table->current_width ||
|
||
row < 0 || column < 0) {
|
||
return;
|
||
}
|
||
strcpy(table->data[row][column], data);
|
||
if (strlen(data) > table->column_width[column]) {
|
||
table->column_width[column] = strlen(data);
|
||
}
|
||
}
|
||
|
||
int get_max_width_in_a_column(TableInfo *table, int column) {
|
||
int max_width = 0;
|
||
for (int i = 0; i < table->current_height; i++) {
|
||
int data_length =
|
||
table->data[i][column] == NULL ? 0 : strlen(table->data[i][column]);
|
||
if (data_length > max_width) {
|
||
max_width = data_length;
|
||
}
|
||
}
|
||
return max(max_width, table->column_width[column]);
|
||
}
|
||
|
||
void add_char_to_cell(TableInfo *table, int row, int column, char c) {
|
||
if (row >= table->current_height || column >= table->current_width ||
|
||
row < 0 || column < 0) {
|
||
return;
|
||
}
|
||
int data_length = strlen(table->data[row][column]);
|
||
if (data_length < MAX_DATA_LENGTH - 1) {
|
||
table->data[row][column][data_length] = c;
|
||
table->data[row][column][data_length + 1] = '\0';
|
||
table->column_width[column] = get_max_width_in_a_column(table, column);
|
||
}
|
||
}
|
||
|
||
void del_char_from_cell(TableInfo *table, int row, int column) {
|
||
if (row >= table->current_height || column >= table->current_width ||
|
||
row < 0 || column < 0) {
|
||
return;
|
||
}
|
||
int data_length = strlen(table->data[row][column]);
|
||
if (data_length > 0) {
|
||
table->data[row][column][data_length - 1] = '\0';
|
||
table->column_width[column] = get_max_width_in_a_column(table, column);
|
||
}
|
||
}
|
||
|
||
// 返回 1 代表响应成功
|
||
// 返回 0 代表响应失败
|
||
int handleKeyPress(int key, TableInfo *table) {
|
||
int status = 0;
|
||
if (key == 224) { // 特殊键
|
||
key = getch(); // 获取特殊键码
|
||
if (key == KEY_LEFT_ARROW) {
|
||
if (select_mode) {
|
||
// 选择模式,0,0是左上角,0,1 0,2 0,3 代表每行行号 1,0 2,0 3,0
|
||
// 代表每列列号
|
||
if (current_y == 0) {
|
||
if (current_x > 1)
|
||
current_x--;
|
||
else
|
||
current_x = table->current_width;
|
||
}
|
||
if (current_x == 0) {
|
||
current_y = 0;
|
||
current_x = table->current_width;
|
||
}
|
||
status = 1;
|
||
} else {
|
||
if (current_x > 0) {
|
||
current_x--;
|
||
} else if (current_x == 0) {
|
||
if (current_y == -1) {
|
||
current_x = FUNCTION_NUM - 1;
|
||
} else {
|
||
current_x = table->current_width - 1;
|
||
}
|
||
}
|
||
status = 1;
|
||
}
|
||
}
|
||
if (key == KEY_RIGHT_ARROW) {
|
||
if (select_mode) {
|
||
if (current_y == 0) {
|
||
if (current_x < table->current_width)
|
||
current_x++;
|
||
else
|
||
current_x = 1;
|
||
}
|
||
if (current_x == 0) {
|
||
current_y = 0;
|
||
current_x = 1;
|
||
}
|
||
status = 1;
|
||
} else {
|
||
if (current_y == -1) {
|
||
current_x = (current_x + 1) % FUNCTION_NUM;
|
||
} else {
|
||
current_x = (current_x + 1) % table->current_width;
|
||
}
|
||
status = 1;
|
||
}
|
||
}
|
||
if (key == KEY_UP_ARROW) {
|
||
if (select_mode) {
|
||
if (current_x == 0) {
|
||
if (current_y > 1)
|
||
current_y--;
|
||
else
|
||
current_y = table->current_height;
|
||
}
|
||
if (current_y == 0) {
|
||
current_x = 0;
|
||
current_y = table->current_height;
|
||
}
|
||
status = 1;
|
||
} else {
|
||
if (current_y > 0) {
|
||
current_y--;
|
||
} else if (current_y == 0) {
|
||
current_y = -1;
|
||
current_x = min(FUNCTION_NUM - 1, current_x);
|
||
} else if (current_y == -1) {
|
||
current_y = table->current_height - 1;
|
||
current_x = min(table->current_width - 1, current_x);
|
||
}
|
||
status = 1;
|
||
}
|
||
}
|
||
if (key == KEY_DOWN_ARROW) {
|
||
if (select_mode) {
|
||
if (current_x == 0) {
|
||
if (current_y < table->current_height)
|
||
current_y++;
|
||
else
|
||
current_y = 1;
|
||
}
|
||
if (current_y == 0) {
|
||
current_x = 0;
|
||
current_y = 1;
|
||
}
|
||
status = 1;
|
||
} else {
|
||
if (current_y < table->current_height - 1 && current_y >= 0) {
|
||
current_y++;
|
||
} else if (current_y == table->current_height - 1) {
|
||
// TO FUNCTIONS AREA
|
||
current_y = -1;
|
||
current_x = min(FUNCTION_NUM - 1, current_x);
|
||
} else if (current_y == -1) {
|
||
current_y = 0;
|
||
current_x = min(table->current_width - 1, current_x);
|
||
}
|
||
status = 1;
|
||
}
|
||
}
|
||
} else {
|
||
// ctrl + c
|
||
if (key == 3) {
|
||
alive = 0;
|
||
message = "Bye!";
|
||
status = 1;
|
||
}
|
||
// ctrl + s
|
||
if (key == 19) {
|
||
save_table_to_file("table.dat", *table);
|
||
message = "Saved!";
|
||
status = 1;
|
||
}
|
||
if (select_mode) {
|
||
// ENTER
|
||
if (key == KEY_ENTER) {
|
||
end_select_index(table);
|
||
status = 1;
|
||
}
|
||
// ESC
|
||
if (key == KEY_ESC) {
|
||
select_mode = 0;
|
||
current_y = -1;
|
||
current_x = select_entry;
|
||
message = "Canceled!";
|
||
status = 1;
|
||
}
|
||
} else {
|
||
// 判断 key 是可打印字符
|
||
if (key >= 32 && key <= 126) {
|
||
add_char_to_cell(table, current_y, current_x, key);
|
||
status = 1;
|
||
}
|
||
// 退格键
|
||
if (key == 8) {
|
||
del_char_from_cell(table, current_y, current_x);
|
||
status = 1;
|
||
}
|
||
// ENTER
|
||
if (key == KEY_ENTER) {
|
||
if (current_y == -1) {
|
||
if (current_x == 0) {
|
||
save_table_to_file("table.dat", *table);
|
||
message = "Saved!";
|
||
}
|
||
if (current_x == 1) {
|
||
*table = load_table_from_file("table.dat");
|
||
message = "Loaded!";
|
||
}
|
||
if (current_x == 2) {
|
||
start_select_index(2);
|
||
}
|
||
if (current_x == 3) {
|
||
start_select_index(3);
|
||
}
|
||
if (current_x == 4) {
|
||
start_select_index(4);
|
||
}
|
||
if (current_x == 5) {
|
||
start_select_index(5);
|
||
}
|
||
if (current_x == 6) {
|
||
start_select_index(6);
|
||
}
|
||
if (current_x == 7) {
|
||
alive = 0;
|
||
message = "Bye!";
|
||
}
|
||
} else {
|
||
// 如果以 = 开头
|
||
if (table->data[current_y][current_x][0] == '=') {
|
||
if (!check_valid_formatter(table, current_x,
|
||
current_y)) {
|
||
message = "Not a valid formatter!";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
int debug = 0;
|
||
if (debug) {
|
||
char *tmp_message = (char *)malloc(sizeof(char) * MAX_MESSAGE_LENGTH);
|
||
sprintf(tmp_message, "x: %d, y: %d", current_x, current_y);
|
||
message = tmp_message;
|
||
}
|
||
return status;
|
||
}
|
||
|
||
int main() {
|
||
TableInfo table;
|
||
int load_from_file = 0;
|
||
|
||
if (is_data_file_exist()) {
|
||
char tmp;
|
||
printf("Load from file? ([Y]/n): ");
|
||
scanf("%c", &tmp);
|
||
if (tmp == 'n' || tmp == 'N') {
|
||
load_from_file = 0;
|
||
} else {
|
||
load_from_file = 1;
|
||
}
|
||
}
|
||
if (load_from_file) {
|
||
table = load_table_from_file("table.dat");
|
||
} else {
|
||
printf("Let's create a table!\n");
|
||
int width = 0, height = 0;
|
||
int column_width = 0;
|
||
while (width <= 0 || width > MAX_COLUMN) {
|
||
printf("Input width (1-%d): ", MAX_COLUMN);
|
||
scanf("%d", &width);
|
||
}
|
||
while (height <= 0 || height > MAX_ROW) {
|
||
printf("Input height (1-%d): ", MAX_ROW);
|
||
scanf("%d", &height);
|
||
}
|
||
while (column_width <= 0 || column_width > MAX_COLUMN_WIDTH) {
|
||
printf("Input column width (1-%d): ", MAX_COLUMN_WIDTH);
|
||
scanf("%d", &column_width);
|
||
}
|
||
|
||
init_table(width, height, column_width, &table);
|
||
}
|
||
setCell(&table, 0, 0, "Hello");
|
||
|
||
while (alive) {
|
||
printTable(&table);
|
||
// drawGUI(currentSelection);
|
||
|
||
int keyPressed = getch(); // 获取键盘输入
|
||
handleKeyPress(keyPressed, &table);
|
||
|
||
// tick = (tick + 1) % MAX_TICK;
|
||
}
|
||
|
||
int save_to_file = 0;
|
||
char tmp;
|
||
printf("Save to file? ([Y]/n): ");
|
||
scanf("%c", &tmp);
|
||
if (tmp == 'n' || tmp == 'N') {
|
||
save_to_file = 0;
|
||
} else {
|
||
save_to_file = 1;
|
||
}
|
||
if (save_to_file) {
|
||
save_table_to_file("table.dat", table);
|
||
}
|
||
return 0;
|
||
}
|