// Compilation command: // - release: gcc task_tracker.c -Wall -O2 -m64 -lncurses -o task_tracker.x64 // - debug : gcc task_tracker.c -Wall -g3 -m64 -lncurses -o task_tracker.x64 #include #include #include #include #include #include #define STR_(X) #X // Convert to string. #define STR(X) STR_(X) // Force argument expansions before converting to string. #define MAX_TASK_NAME 127 #define FIRST_DAY_OF_WEEK 1 // (0-6, Sunday = 0) #define LOG_FILE_NAME "log.txt" #define DB_FILE_NAME "database.bin" struct task_event { char* name; time_t start; time_t end; }; struct task_info { uint32_t hash; // uint32_t time[sizeof(DAYS_OF_WEEK)]; // #define DAYS_ON_WEEK sizeof(DAYS_OF_WEEK) // uint32_t time[DAYS_ON_WEEK]; uint32_t time[7]; char name[MAX_TASK_NAME+1]; // Allow space for null termination char. }; const char* DB_FILE_SIGNATURE = "TTBF:1.0"; const uint8_t FILE_SIGNATURE_SIZE = sizeof(DB_FILE_SIGNATURE); const size_t TASK_INFO_SIZE = sizeof(struct task_info); const char* DAYS_OF_WEEK[] = { "sun", "mon", "tue", "wed", "thu", "fri", "sat" }; const uint8_t DAYS_ON_WEEK = sizeof(DAYS_OF_WEEK)/sizeof(char*); struct task_info* tasks = NULL; uint32_t tasks_count = 0; uint32_t tasks_capacity = 0; int selected_task = -1; char** tasks_names = NULL; uint32_t tasks_names_size = 0; uint32_t tasks_names_capacity = 0; char* replace_char(char* string, char find, char replace){ char *idx = string; while((idx = strchr(idx, find)) != NULL) { *idx = replace; *idx++; } return string; } void print_task(const struct task_info* task) { printf("name: '%s'\n", task->name); printf("hash: '%" PRIu32 "'\n", task->hash); printf("t[0]: '%" PRIu32 "'\n", task->time[0]); printf("t[1]: '%" PRIu32 "'\n", task->time[1]); printf("t[2]: '%" PRIu32 "'\n", task->time[2]); printf("t[3]: '%" PRIu32 "'\n", task->time[3]); printf("t[4]: '%" PRIu32 "'\n", task->time[4]); printf("t[5]: '%" PRIu32 "'\n", task->time[5]); printf("t[6]: '%" PRIu32 "'\n", task->time[6]); } void store_database(const struct task_info* database, uint32_t number_of_entries) { const char* DB_FILE_SIGNATURE = "TTBF:1.0"; const uint8_t FILE_SIGNATURE_SIZE = sizeof(DB_FILE_SIGNATURE); const size_t TASK_INFO_SIZE = sizeof(struct task_info); FILE* file = fopen("./" DB_FILE_NAME, "w"); fwrite(DB_FILE_SIGNATURE, sizeof(char), FILE_SIGNATURE_SIZE, file); fwrite(&number_of_entries, sizeof(number_of_entries), 1, file); fwrite(database, TASK_INFO_SIZE, number_of_entries, file); fclose(file); } uint32_t load_database(struct task_info** database) { const char* DB_FILE_SIGNATURE = "TTBF:1.0"; const uint8_t FILE_SIGNATURE_SIZE = sizeof(DB_FILE_SIGNATURE); const size_t TASK_INFO_SIZE = sizeof(struct task_info); FILE* file = fopen("./" DB_FILE_NAME, "r"); char file_signature[FILE_SIGNATURE_SIZE]; fread(&file_signature, sizeof(char), FILE_SIGNATURE_SIZE, file); if (strncmp(file_signature, DB_FILE_SIGNATURE, FILE_SIGNATURE_SIZE) != 0) { printf("Invalid file signature.\n"); return 0; } fprintf(stderr, "-4\n"); uint32_t number_of_entries; fread(&number_of_entries, sizeof(number_of_entries), 1, file); fprintf(stderr, "number of entries: %" PRIu32 "\n", number_of_entries); fprintf(stderr, "pointer_value: %p : *%p\n", database, *database); *database = calloc(number_of_entries, TASK_INFO_SIZE); fprintf(stderr, "pointer_value: %p : *%p\n", database, *database); fread(*database, TASK_INFO_SIZE, number_of_entries, file); fclose(file); print_task(*database); return number_of_entries; } void export_database(const struct task_info* database, uint32_t number_of_entries) { #define DB_CSV_FILE_NAME "database.csv" // TODO Add offset for FIRST_DAY_OF_WEEK FILE* file = fopen("./" DB_CSV_FILE_NAME, "w"); fprintf(file, "%s,%s,%s,%s,%s,%s,%s,%s\n", "task", DAYS_OF_WEEK[(0+FIRST_DAY_OF_WEEK)%DAYS_ON_WEEK], DAYS_OF_WEEK[(1+FIRST_DAY_OF_WEEK)%DAYS_ON_WEEK], DAYS_OF_WEEK[(2+FIRST_DAY_OF_WEEK)%DAYS_ON_WEEK], DAYS_OF_WEEK[(3+FIRST_DAY_OF_WEEK)%DAYS_ON_WEEK], DAYS_OF_WEEK[(4+FIRST_DAY_OF_WEEK)%DAYS_ON_WEEK], DAYS_OF_WEEK[(5+FIRST_DAY_OF_WEEK)%DAYS_ON_WEEK], DAYS_OF_WEEK[(6+FIRST_DAY_OF_WEEK)%DAYS_ON_WEEK] ); for (uint32_t idx = 0; idx < number_of_entries; idx++) { const struct task_info* task = &database[idx]; fprintf(file, "%s,%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 ",%" PRIu32 "\n", task->name, task->time[0], task->time[1], task->time[2], task->time[3], task->time[4], task->time[5], task->time[6] ); } fclose(file); } uint32_t CRC32(const uint8_t data[], size_t data_length) { static const uint32_t crc32_table[] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; uint32_t crc32 = 0xFFFFFFFFu; for (size_t i = 0; i < data_length; i++) { const uint32_t lookupIndex = (crc32 ^ data[i]) & 0xff; crc32 = (crc32 >> 8) ^ crc32_table[lookupIndex]; } // Finalize the CRC-32 value by inverting all the bits crc32 ^= 0xFFFFFFFFu; return crc32; } uint32_t hash_string(const char* string) { size_t data_length = strlen(string); uint8_t* data = (uint8_t*)string; return CRC32(data, data_length); } void add_task(char* name) { // Exit if task has already been added. uint32_t name_hash = CRC32((uint8_t*)name, sizeof(name)); for (uint32_t idx = 0; idx < tasks_count; idx++) { if (name_hash == tasks[idx].hash && strcmp(name, tasks[idx].name) == 0) { return; } } // Expand tasks capacity if required. if (tasks_count >= tasks_capacity) { tasks_capacity = tasks_capacity == 0 ? 16 : tasks_capacity << 1; tasks = realloc(tasks, sizeof(struct task_info) * tasks_capacity); } // Add new task entry. struct task_info* new_task = &tasks[tasks_count]; memset(new_task, '0', sizeof(struct task_info)); strncpy(new_task->name, name, MAX_TASK_NAME); new_task->name[MAX_TASK_NAME] = '\0'; printf(">>> %s\n", new_task->name); // TODO debug new_task->hash = name_hash; tasks_count++; } void add_task_event(char* name, uint64_t start, uint64_t end) { // TODO Missing the task_event array. } void prototype() { /////////////////////////////////////////////////////////////////////////// // Get current day of the week. time_t now_ut = time(NULL); uint8_t week_day = localtime(&now_ut)->tm_wday; printf("# current day of the week: %d\n", week_day); /////////////////////////////////////////////////////////////////////////// // Store database from memory to binary file. struct task_info task; memset(&task, '0', TASK_INFO_SIZE); strncpy(task.name, "TASK-00 : Sample task name.", MAX_TASK_NAME+1); task.time[0] = 0; task.time[1] = 10; task.time[2] = 11; task.time[3] = 12; task.time[4] = 333; task.time[5] = 555; task.time[6] = 777; task.hash = hash_string(task.name); print_task(&task); store_database(&task, 1); /////////////////////////////////////////////////////////////////////////// // Store database from memory to binary file. struct task_info* task_dest = NULL; uint32_t number_of_entries = load_database(&task_dest); print_task(task_dest); fprintf(stderr, ">>>>> %" PRIu32 "\n", number_of_entries); free(task_dest); /////////////////////////////////////////////////////////////////////////// // Export database to CSV file. export_database(&task, 1); return; const char* csv_head = "task_name,start,end"; const char* csv_line[] = { "PI-0000,1659479138,1659482738", "PI-0001,1659479127,1659482727", "XPTO-01 : testing long name,1659379138,1659382738", "XPTO-01 : testing long nameXPTO-01 : testing long nameXPTO-01 : testing long nameXPTO-01 : testing long nameXPTO-01 : testing long nameXPTO-01 : testing long nameXPTO-01 : testing long nameXPTO-01 : testing long name,123,124", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb:cccccccccccccccccccccccccccccc:ddddddddddddddddddddddddddddddddddddd:eeeeeeeeeeeeeeeeeeeeee:fffffffffffffffffff,123,456", "Olá vamos cantar uma canção.,1659279127,1659282727", "[ TST-00 á],1659579138,1659582738", "[ XPTO- 01,1659179127,1659182727", "[ TST-00 á],1659479138,1659482738", "[ XPTO- 01,1659429127,1659482727", "[ TST-00 á],1658479138,1658482738", "[ XPTO- 01,1659669127,1659672727", "[ TST-00 á],1658879138,1658882738", "[ XPTO- 01,1656579127,1656582727", "[ TST-00 á],1659439138,1659492738", "[ XPTO- 01,1655579127,1655682727", "[ TST-00 á],1657679138,1657782738", "[ XPTO- 01,1658179127,1658382727", "[ TST-00 á],1651479138,1651482738", "[ XPTO- 01,1659479127,1659482727", "[ TST-00 á],1659079138,1659082738", "[ XPTO- 01,1659379127,1659382727", }; // const char* csv_line = "1659479138,1659482738"; // const char* csv_line = "zZ[ ã ]Yy,123"; // char name[] = { 'a', 'b', 'c', '\0' }; char* name; uint64_t start; uint64_t end; printf("--- --- àè.ªãº.éá --- ---\n"); ////////////////////////////////////////////////// // TODO Use this to parse the tasks names. TODO // // TODO WIP TODO WIP TODO WIP TODO const char* task_info_A = "Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vel turpis nunc eget lorem. Non pulvinar neque laoreet suspendisse interdum consectetur libero id,165147,14790,9138,1,2,3,4"; const char* task_info_B = "Lorem,165147,14790,9138,1,2,3,4"; #define COISA #define SPACER "%*[^,]" const char* format = "%" STR(MAX_TASK_NAME) "[^,]" SPACER ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32; // struct task_info task_A; // sscanf(task_info_A, format, // task_A.name, // &task_A.time[0], // &task_A.time[1], // &task_A.time[2], // &task_A.time[3], // &task_A.time[4], // &task_A.time[5], // &task_A.time[6] // ); // TODO WIP const char* format_X = "%" STR(MAX_TASK_NAME) "[^,]"; struct task_info task_A; sscanf(task_info_A, format_X, task_A.name ); // TODO WIP const char* format_Y = "%*[^,],%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32; sscanf(task_info_A, format_Y, &task_A.time[0], &task_A.time[1], &task_A.time[2], &task_A.time[3], &task_A.time[4], &task_A.time[5], &task_A.time[6] ); // TODO WIP // struct task_info task_B; // sscanf(task_info_B,format, // task_B.name, // &task_B.time[0], // &task_B.time[1], // &task_B.time[2], // &task_B.time[3], // &task_B.time[4], // &task_B.time[5], // &task_B.time[6] // ); // TODO WIP struct task_info task_B; sscanf(task_info_B,format_X, task_B.name ); // TODO WIP sscanf(task_info_B,format_Y, &task_B.time[0], &task_B.time[1], &task_B.time[2], &task_B.time[3], &task_B.time[4], &task_B.time[5], &task_B.time[6] ); // TODO WIP printf("--------------------------------------------------\n"); printf("name: '%s'\n", task_A.name); printf("t[0]: '%d'\n", task_A.time[0]); printf("t[1]: '%d'\n", task_A.time[1]); printf("t[2]: '%d'\n", task_A.time[2]); printf("t[3]: '%d'\n", task_A.time[3]); printf("t[4]: '%d'\n", task_A.time[4]); printf("t[5]: '%d'\n", task_A.time[5]); printf("t[6]: '%d'\n", task_A.time[6]); printf("name: '%s'\n", task_B.name); printf("t[0]: '%d'\n", task_B.time[0]); printf("t[1]: '%d'\n", task_B.time[1]); printf("t[2]: '%d'\n", task_B.time[2]); printf("t[3]: '%d'\n", task_B.time[3]); printf("t[4]: '%d'\n", task_B.time[4]); printf("t[5]: '%d'\n", task_B.time[5]); printf("t[6]: '%d'\n", task_B.time[6]); printf("--------------------------------------------------\n"); /////////////////////////////////////////////////////////////// uint32_t lines_count = sizeof(csv_line)/sizeof(char*); for (uint32_t idx = 0; idx < lines_count; idx++) { // TODO The following sscanf is allocating memory for the name... we should remove it. // uint32_t max_task_name // TODO The m modifier requires us to free the memory returned. sscanf(csv_line[idx], "%" STR(MAX_TASK_NAME) "m[^,\n],%" SCNu64 ",%" SCNu64, &name, &start, &end); // TODO WIP add_task(name); // printf("bazinga: %s : %d : %d\n", name, start, end); // printf("bazinga: %s : %.19s : %.19s\n", name, ctime(&start), ctime(&end)); printf("bazonga: %s\n", tasks[tasks_count-1].name); } printf("### ### --------- ### ###\n"); // tasks_names = // Free tasks names. for (uint32_t idx = tasks_names_size; idx > 0; idx--) { printf("> %s\n", tasks_names[idx-1]); // @dam TODO debug free(tasks_names[idx-1]); } free(tasks_names); return; // tasks_names = malloc( ... time_t x = time(NULL); // x = (time_t)((1U << 32) - 1); printf("%s\n", ctime(&x)); x = x<<1; printf("%s\n", ctime(&x)); x += 1; printf("%s\n", ctime(&x)); x = x<<1; printf("%s\n", ctime(&x)); x = x<<1; printf("%s\n", ctime(&x)); x = x<<1; printf("%s\n", ctime(&x)); x = x<<1; printf("%s\n", ctime(&x)); } void draw_table() { struct task_info asd; } void draw_header() { const char *table_headers[] = { "Task", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Total" }; const int table_headers_size = sizeof(table_headers)/sizeof(char*); int row,col; /* to store the number of rows and the number of colums of the screen */ initscr(); /* start the curses mode */ getmaxyx(stdscr,row,col); /* get the number of rows and columns */ mvaddch(0, 0, ACS_ULCORNER); for (int idx = 0; idx < table_headers_size; idx++) { if (idx > 0) { addch(ACS_TTEE); // printw(" %c", ACS_PLUS); } addch(ACS_HLINE); printw(" %s ", table_headers[idx]); addch(ACS_HLINE); } int cursor_y, cursor_x; getyx(stdscr, cursor_y, cursor_x); for (int idx = cursor_x; idx < col-1; idx++) { addch(ACS_HLINE); } addch(ACS_URCORNER); } void draw_footer() { const char *app_name = "Task Tracker"; const char *app_version = "v1.0"; int row, col; /* to store the number of rows and the number of colums of the screen */ initscr(); /* start the curses mode */ getmaxyx(stdscr,row,col); /* get the number of rows and columns */ printw("Row %d", row); mvaddch(row-1, 0, ACS_LLCORNER); addch(' '); printw(app_name); addch(' '); for (int idx = strlen(app_name) + 3; idx < col - strlen(app_version) - 3; idx ++) { addch(ACS_HLINE); } addch(' '); printw(app_version); addch(' '); addch(ACS_LRCORNER); } WINDOW *create_newwin(int height, int width, int starty, int startx); void destroy_win(WINDOW *local_win); int main(int argc, char *argv[]) { prototype(); return 0; WINDOW *my_win; int startx, starty, width, height; int ch; initscr(); /* Start curses mode */ cbreak(); /* Line buffering disabled, Pass on * everty thing to me */ keypad(stdscr, TRUE); /* I need that nifty F1 */ curs_set(0); // Set cursor invisible. height = 3; width = 10; starty = (LINES - height) / 2; /* Calculating for a center placement */ startx = (COLS - width) / 2; /* of the window */ printw("Press F1 to exit"); refresh(); my_win = create_newwin(height, width, starty, startx); int rows; int colums; ch = KEY_RESIZE; do { switch(ch) { case KEY_RESIZE: erase(); break; case KEY_LEFT: destroy_win(my_win); my_win = create_newwin(height, width, starty,--startx); break; case KEY_RIGHT: destroy_win(my_win); my_win = create_newwin(height, width, starty,++startx); break; case KEY_UP: destroy_win(my_win); my_win = create_newwin(height, width, --starty,startx); break; case KEY_DOWN: destroy_win(my_win); my_win = create_newwin(height, width, ++starty,startx); break; } draw_header(); draw_table(); draw_footer(); } while((ch = getch()) != KEY_F(1)); endwin(); return 0; } WINDOW *create_newwin(int height, int width, int starty, int startx) { WINDOW *local_win; local_win = newwin(height, width, starty, startx); box(local_win, 0 , 0); /* 0, 0 gives default characters * for the vertical and horizontal * lines */ wrefresh(local_win); /* Show that box */ return local_win; } void destroy_win(WINDOW *local_win) { /* box(local_win, ' ', ' '); : This won't produce the desired * result of erasing the window. It will leave it's four corners * and so an ugly remnant of window. */ wborder(local_win, ' ', ' ', ' ',' ',' ',' ',' ',' '); /* The parameters taken are * 1. win: the window on which to operate * 2. ls: character to be used for the left side of the window * 3. rs: character to be used for the right side of the window * 4. ts: character to be used for the top side of the window * 5. bs: character to be used for the bottom side of the window * 6. tl: character to be used for the top left corner of the window * 7. tr: character to be used for the top right corner of the window * 8. bl: character to be used for the bottom left corner of the window * 9. br: character to be used for the bottom right corner of the window */ wrefresh(local_win); delwin(local_win); }