1394 lines
36 KiB
C
1394 lines
36 KiB
C
#define _DEFAULT_SOURCE
|
|
#include <dirent.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
#include "btk/btk.h"
|
|
|
|
/* for filesystem navigation */
|
|
/* change depending on your system */
|
|
#define NAME_SIZE 255
|
|
#define PATH_SIZE 4096
|
|
|
|
/* buffer increments */
|
|
#define DIR_BUFFER_INC 100
|
|
#define DATA_BUFFER_INC 2
|
|
|
|
#define READ_SIZE 2048
|
|
#define TEXT_SIZE 4096
|
|
#define ITEM_SIZE 256
|
|
|
|
#define TAG_COL 0
|
|
#define UID_COL 1
|
|
#define NAME_COL 2
|
|
#define DATA_COLS_N 9 /* excludes id, filename and tag */
|
|
|
|
enum tag_type {
|
|
TAG_NONE = 0,
|
|
TAG_STRAY = 1U << 0,
|
|
TAG_NEW = 1U << 1,
|
|
TAG_DEL = 1U << 2,
|
|
TAG_EDITED = 1U << 3,
|
|
TAG_VISIBILITY = 1U << 4
|
|
};
|
|
|
|
enum status {
|
|
STATUS_NONE,
|
|
STATUS_ERROR,
|
|
STATUS_LATEST,
|
|
STATUS_EDITED,
|
|
STATUS_BUSY
|
|
};
|
|
|
|
enum dir_mode {
|
|
DIR_FILES = 1U << 0,
|
|
DIR_HIDDEN = 1U << 1
|
|
};
|
|
|
|
typedef struct {
|
|
char uid[ITEM_SIZE];
|
|
char filename[ITEM_SIZE];
|
|
char misc[DATA_COLS_N][ITEM_SIZE];
|
|
char notes[TEXT_SIZE];
|
|
unsigned int notes_w;
|
|
} data_entry_t;
|
|
|
|
/* window creation functions */
|
|
void build_entry_form ();
|
|
void build_file_picker ();
|
|
void build_main_window ();
|
|
void build_settings ();
|
|
|
|
/* functions */
|
|
void clean_string_copy (char *, char *, unsigned int, int);
|
|
int cmp_str_for_qsort (const void *, const void*);
|
|
void entry_form_apply ();
|
|
void entry_form_close ();
|
|
void entry_form_open ();
|
|
int file_exists ();
|
|
void file_picker_close ();
|
|
void file_picker_open (int);
|
|
void file_picker_open_entry ();
|
|
void file_picker_open_open ();
|
|
void file_picker_open_new ();
|
|
void file_picker_select ();
|
|
int find_dir_spot (char *, char *);
|
|
char* get_data_item (unsigned int, unsigned int);
|
|
void hotpot_close ();
|
|
void hotpot_load ();
|
|
void hotpot_reload ();
|
|
void hotpot_sync ();
|
|
void hotpot_unload ();
|
|
void move_dir (int);
|
|
void open_ext_dir ();
|
|
void open_ext_entry (int);
|
|
void quit ();
|
|
int parse_dir (char *, int);
|
|
void push_entry (int, data_entry_t);
|
|
void settings_close ();
|
|
void settings_open ();
|
|
void set_activity_status (int, int);
|
|
void set_entry_tag_col (unsigned int, int);
|
|
void set_main_win_states (int);
|
|
void set_file_picker_states (int);
|
|
void str_to_lower_case (char *);
|
|
void toggle_del_tag ();
|
|
void toggle_col (int, btk_arg_t);
|
|
void toggle_hidden (int, btk_arg_t);
|
|
void toggle_notes (int, btk_arg_t);
|
|
void toggle_visibility_tag ();
|
|
void update_select_data (int);
|
|
|
|
/* btk windows */
|
|
btk_session_t *session;
|
|
btk_window_t *entry_form;
|
|
btk_window_t *file_picker;
|
|
btk_window_t *main_win;
|
|
btk_window_t *settings;
|
|
btk_window_t *windows[4];
|
|
|
|
/* btk important cells */
|
|
btk_cell_t *table_cell;
|
|
btk_cell_t *dir_list_cell;
|
|
btk_cell_t *notes_view_cell;
|
|
btk_cell_t *file_select_cell;
|
|
btk_cell_t *activity_cell;
|
|
btk_cell_t *edited_note_cell;
|
|
unsigned int table_cell_id;
|
|
unsigned int dir_list_cell_id;
|
|
unsigned int notes_view_cell_id;
|
|
unsigned int file_select_cell_id;
|
|
unsigned int activity_cell_id;
|
|
unsigned int edited_note_cell_id;
|
|
|
|
/* file navigation */
|
|
char dir_current[PATH_SIZE];
|
|
char *dir_list = NULL;
|
|
int *dir_spot = NULL;
|
|
unsigned int dir_list_n = 0;
|
|
int nav_select = -1;
|
|
int nav_mode;
|
|
|
|
/* hotpot data */
|
|
int file_picker_mode;
|
|
char open_dir[PATH_SIZE] = "";
|
|
int hotpot_open = 0;
|
|
char *data = NULL;
|
|
char *data_notes = NULL;
|
|
int *data_tags = NULL;
|
|
int *data_spot = NULL;
|
|
char *data_rename = NULL;
|
|
unsigned int data_n = 0;
|
|
unsigned int data_buffer_n = 0;
|
|
unsigned int last_uid = 0;
|
|
|
|
/* selected data */
|
|
int select_data = -1;
|
|
char select_note[TEXT_SIZE];
|
|
|
|
/* edited data */
|
|
char edited_uid[ITEM_SIZE];
|
|
char edited_filename[ITEM_SIZE];
|
|
char edited_misc[DATA_COLS_N][ITEM_SIZE];
|
|
char edited_note[TEXT_SIZE];
|
|
|
|
/* misc gui stuff */
|
|
char status_open_file[PATH_SIZE + NAME_SIZE];
|
|
char status_files_n[15];
|
|
char status_activity[9];
|
|
char misc_titles[DATA_COLS_N][ITEM_SIZE];
|
|
char misc_switches[DATA_COLS_N][ITEM_SIZE];
|
|
unsigned int data_cols_cw[DATA_COLS_N + 3] = {1, 1, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2};
|
|
int data_cols_ena[DATA_COLS_N + 3] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
|
char data_header[DATA_COLS_N + 3][ITEM_SIZE] = {
|
|
"TAGS",
|
|
"UID",
|
|
"FILENAME",
|
|
"TOPICS",
|
|
"AUTHORS",
|
|
"INSTITUTIONS",
|
|
"PUBLISHER",
|
|
"YEAR",
|
|
"VOL",
|
|
"NO",
|
|
"PAGES",
|
|
"ACCESSED"
|
|
};
|
|
|
|
/* misc */
|
|
btk_arg_t dummy_arg = {.i = 0, .f = 0.0f, .c = NULL, .p = NULL};
|
|
|
|
/*******************************************************************/
|
|
|
|
void
|
|
build_entry_form()
|
|
{
|
|
entry_form = btk_window_create(session->x_con,
|
|
session->x_scr,
|
|
session->x_vis,
|
|
8, 6 + DATA_COLS_N,
|
|
4, 3 + DATA_COLS_N,
|
|
100, 0,
|
|
10 + 2 * DATA_COLS_N,
|
|
entry_form_close);
|
|
btk_window_set_name(entry_form, "hotpot - entry form");
|
|
|
|
edited_note_cell_id = 0;
|
|
edited_note_cell = &(entry_form->cells[edited_note_cell_id]);
|
|
btk_cell_set_editor(edited_note_cell, 2, 2 + DATA_COLS_N, 6, 4, (char*)&edited_note, TEXT_SIZE);
|
|
|
|
btk_cell_set_mark (&(entry_form->cells[1]), 0, 0, 2, BTK_JUSTIFY_RIGHT, "uid :");
|
|
btk_cell_set_mark (&(entry_form->cells[2]), 0, 1, 2, BTK_JUSTIFY_RIGHT, "filename :");
|
|
btk_cell_set_mark (&(entry_form->cells[3]), 2, 0, 6, BTK_JUSTIFY_LEFT, edited_uid);
|
|
btk_cell_set_input (&(entry_form->cells[4]), 2, 1, 6, (char*)edited_filename, NAME_SIZE);
|
|
btk_cell_set_mark (&(entry_form->cells[5]), 0, 2 + DATA_COLS_N, 2, BTK_JUSTIFY_RIGHT, "notes :");
|
|
btk_cell_set_empty (&(entry_form->cells[6]), 0, 3 + DATA_COLS_N, 2, 1);
|
|
btk_cell_set_button (&(entry_form->cells[7]), 0, 4 + DATA_COLS_N, 2, "apply", entry_form_apply);
|
|
btk_cell_set_button (&(entry_form->cells[8]), 0, 5 + DATA_COLS_N, 2, "close", entry_form_close);
|
|
|
|
/* generate input fields for misc data */
|
|
for (int i = 0; i < DATA_COLS_N; i++) {
|
|
|
|
strcpy(misc_titles[i], data_header[i + 3]);
|
|
str_to_lower_case(misc_titles[i]);
|
|
strcat(misc_titles[i], " :");
|
|
|
|
btk_cell_set_mark (&(entry_form->cells[9 + i]), 0, 2 + i, 2, BTK_JUSTIFY_RIGHT, misc_titles[i]);
|
|
btk_cell_set_input (&(entry_form->cells[10 + DATA_COLS_N + i]), 2, 2 + i, 6, (char*)edited_misc[i], NAME_SIZE);
|
|
}
|
|
}
|
|
|
|
void
|
|
build_file_picker()
|
|
{
|
|
file_picker = btk_window_create(session->x_con,
|
|
session->x_scr,
|
|
session->x_vis,
|
|
4, 9,
|
|
2, 2,
|
|
0, 300,
|
|
5,
|
|
file_picker_close);
|
|
btk_window_set_name(file_picker, "hotpot - file picker");
|
|
|
|
dir_list_cell_id = 0;
|
|
dir_list_cell = &(file_picker->cells[dir_list_cell_id]);
|
|
btk_cell_set_list (dir_list_cell,
|
|
0, 1, 4, 5,
|
|
&dir_list,
|
|
&dir_list_n,
|
|
NAME_SIZE,
|
|
NULL, NULL,
|
|
&dir_spot,
|
|
move_dir,
|
|
set_file_picker_states);
|
|
|
|
file_select_cell_id = 1;
|
|
file_select_cell = &(file_picker->cells[file_select_cell_id]);
|
|
btk_cell_set_button (file_select_cell, 0, 7, 4, "select", file_picker_select);
|
|
|
|
btk_cell_set_mark (&(file_picker->cells[2]), 0, 0, 4, BTK_JUSTIFY_RIGHT, (char*)&dir_current);
|
|
btk_cell_set_switch (&(file_picker->cells[3]), 0, 6, 4, "show hidden", toggle_hidden, dummy_arg);
|
|
btk_cell_set_button (&(file_picker->cells[4]), 0, 8, 4, "cancel", file_picker_close);
|
|
}
|
|
|
|
void
|
|
build_main_window()
|
|
{
|
|
main_win = btk_window_create(session->x_con,
|
|
session->x_scr,
|
|
session->x_vis,
|
|
13, 16,
|
|
4, 7,
|
|
400, 0,
|
|
21,
|
|
quit);
|
|
btk_window_set_name(main_win, "hotpot");
|
|
|
|
table_cell_id = 0;
|
|
table_cell = &(main_win->cells[table_cell_id]);
|
|
btk_cell_set_table(table_cell,
|
|
3, 0, 10, 15,
|
|
(char*)data_header,
|
|
&data,
|
|
ITEM_SIZE,
|
|
DATA_COLS_N + 3,
|
|
&data_n,
|
|
(int*)data_cols_ena,
|
|
data_cols_cw,
|
|
2,
|
|
NULL, NULL,
|
|
&data_spot,
|
|
open_ext_entry,
|
|
update_select_data);
|
|
|
|
strcpy(select_note, "");
|
|
notes_view_cell_id = 1;
|
|
notes_view_cell = &(main_win->cells[notes_view_cell_id]);
|
|
btk_cell_set_editor(notes_view_cell,
|
|
3, 9, 10, 6,
|
|
select_note,
|
|
TEXT_SIZE);
|
|
main_win->cells[notes_view_cell_id].state |= BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[notes_view_cell_id].state |= BTK_CELL_STATE_HIDDEN;
|
|
|
|
activity_cell_id = 18;
|
|
activity_cell = &(main_win->cells[activity_cell_id]);
|
|
btk_cell_set_mark (activity_cell,
|
|
11, 15, 2,
|
|
BTK_JUSTIFY_RIGHT,
|
|
(char*)&status_activity);
|
|
|
|
btk_cell_set_button (&(main_win->cells[2]), 0, 0, 3, "open", file_picker_open_open);
|
|
btk_cell_set_button (&(main_win->cells[3]), 0, 1, 3, "new", file_picker_open_new);
|
|
btk_cell_set_button (&(main_win->cells[4]), 0, 2, 3, "sync", hotpot_sync);
|
|
btk_cell_set_button (&(main_win->cells[5]), 0, 3, 3, "view directory", open_ext_dir);
|
|
btk_cell_set_button (&(main_win->cells[6]), 0, 4, 3, "reload", hotpot_reload);
|
|
btk_cell_set_button (&(main_win->cells[7]), 0, 5, 3, "close", hotpot_close);
|
|
btk_cell_set_button (&(main_win->cells[8]), 0, 6, 3, "quit", quit);
|
|
btk_cell_set_empty (&(main_win->cells[9]), 0, 7, 3, 1);
|
|
btk_cell_set_button (&(main_win->cells[10]), 0, 8, 3, "add file", file_picker_open_entry);
|
|
btk_cell_set_button (&(main_win->cells[11]), 0, 9, 3, "edit entry", entry_form_open);
|
|
btk_cell_set_button (&(main_win->cells[12]), 0, 10, 3, "tag for deletion", toggle_del_tag);
|
|
btk_cell_set_button (&(main_win->cells[19]), 0, 11, 3, "tag for visibility", toggle_visibility_tag);
|
|
btk_cell_set_button (&(main_win->cells[20]), 0, 12, 3, "export citation", NULL);
|
|
btk_cell_set_empty (&(main_win->cells[13]), 0, 13, 3, 1);
|
|
btk_cell_set_switch (&(main_win->cells[14]), 0, 14, 3, "show notes", toggle_notes, dummy_arg);
|
|
btk_cell_set_button (&(main_win->cells[15]), 0, 15, 3, "settings", settings_open);
|
|
btk_cell_set_mark (&(main_win->cells[16]), 3, 15, 6, BTK_JUSTIFY_RIGHT, (char*)&status_open_file);
|
|
btk_cell_set_mark (&(main_win->cells[17]), 9, 15, 2, BTK_JUSTIFY_RIGHT, (char*)&status_files_n);
|
|
|
|
main_win->cells[15].state |= BTK_CELL_STATE_ON;
|
|
main_win->cells[20].state |= BTK_CELL_STATE_DISABLED;
|
|
set_main_win_states(0);
|
|
}
|
|
|
|
void
|
|
build_settings()
|
|
{
|
|
settings = btk_window_create(session->x_con,
|
|
session->x_scr,
|
|
session->x_vis,
|
|
3, 3 + DATA_COLS_N,
|
|
-1, -1,
|
|
0, 0,
|
|
3 + DATA_COLS_N,
|
|
settings_close);
|
|
btk_window_set_name(settings, "hotpot - settings");
|
|
|
|
btk_arg_t col_arg= {.i = TAG_COL};
|
|
|
|
btk_cell_set_switch (&(settings->cells[0]), 0, 0, 3, "show tags", toggle_col, col_arg);
|
|
btk_cell_set_empty (&(settings->cells[1 + DATA_COLS_N]), 0, 1 + DATA_COLS_N, 3, 1);
|
|
btk_cell_set_button (&(settings->cells[2 + DATA_COLS_N]), 0, 2 + DATA_COLS_N, 3, "close", settings_close);
|
|
|
|
settings->cells[0].state |= BTK_CELL_STATE_ON;
|
|
|
|
/* generate col toggles for misc data */
|
|
for (int i = 0; i < DATA_COLS_N; i++) {
|
|
|
|
sprintf(misc_switches[i], "show %s", data_header[i + 3]);
|
|
str_to_lower_case(misc_switches[i]);
|
|
|
|
btk_arg_t col_arg = {.i = i + 3};
|
|
btk_cell_set_switch (&(settings->cells[1 + i]), 0, 1 + i, 3, misc_switches[i], toggle_col, col_arg);
|
|
settings->cells[1 + i].state |= BTK_CELL_STATE_ON;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
int
|
|
main()
|
|
{
|
|
getcwd(dir_current, PATH_SIZE);
|
|
strcat(dir_current, "/");
|
|
|
|
/* btk init */
|
|
session = btk_open();
|
|
build_entry_form();
|
|
build_file_picker();
|
|
build_main_window();
|
|
build_settings();
|
|
windows[0] = main_win;
|
|
windows[1] = file_picker;
|
|
windows[2] = entry_form;
|
|
windows[3] = settings;
|
|
|
|
btk_map(session, main_win);
|
|
btk_loop(session, windows, 4);
|
|
|
|
btk_close(session);
|
|
|
|
quit();
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************************************************/
|
|
|
|
void
|
|
clean_string_copy(char* dest, char* src, unsigned int max_size, int del_newline)
|
|
{
|
|
if (!max_size)
|
|
return;
|
|
|
|
char mid[max_size];
|
|
|
|
strncpy(mid, src, max_size);
|
|
if (del_newline)
|
|
*strchr(mid, '\n') = '\0';
|
|
mid[max_size - 1] = '\0';
|
|
strcpy(dest, mid);
|
|
}
|
|
|
|
int
|
|
cmp_str_for_qsort(const void *a, const void *b)
|
|
{
|
|
return strcmp((char*)a, (char*)b);
|
|
}
|
|
|
|
/* check if any data changed, copy it and update status if so */
|
|
void
|
|
entry_form_apply()
|
|
{
|
|
int changed = 0;
|
|
|
|
if (strcmp(edited_filename, get_data_item(NAME_COL, select_data))) {
|
|
strcpy(data_rename + select_data * ITEM_SIZE, get_data_item(NAME_COL, select_data));
|
|
strcpy(get_data_item(NAME_COL, select_data), edited_filename);
|
|
changed = 1;
|
|
}
|
|
|
|
for (int i = 0; i < DATA_COLS_N; i++) {
|
|
if (strcmp(edited_misc[i], get_data_item(i + 3, select_data))) {
|
|
strcpy(get_data_item(i + 3, select_data), edited_misc[i]);
|
|
changed = 1;
|
|
}
|
|
}
|
|
if (strcmp(edited_note, select_note)) {
|
|
strcpy(data_notes + select_data * TEXT_SIZE, edited_note);
|
|
strcpy(select_note, edited_note);
|
|
btk_cell_editor_update_text(notes_view_cell);
|
|
changed = 1;
|
|
}
|
|
|
|
if (changed) {
|
|
data_tags[select_data] |= TAG_EDITED;
|
|
set_entry_tag_col(select_data, data_tags[select_data]);
|
|
set_activity_status(STATUS_EDITED, 1);
|
|
btk_window_redraw(main_win);
|
|
}
|
|
}
|
|
|
|
void
|
|
entry_form_open()
|
|
{
|
|
if (select_data < 0 || select_data >= data_n)
|
|
return;
|
|
|
|
strcpy(edited_note, select_note);
|
|
btk_cell_editor_reset_caret(edited_note_cell);
|
|
|
|
strcpy(edited_uid, get_data_item(1, select_data));
|
|
strcpy(edited_filename, get_data_item(2, select_data));
|
|
btk_cell_input_reset_caret(&(entry_form->cells[4]));
|
|
|
|
for (int i = 0; i < DATA_COLS_N; i++) {
|
|
strcpy(edited_misc[i], get_data_item(i + 3, select_data));
|
|
btk_cell_input_reset_caret(&(entry_form->cells[10 + DATA_COLS_N + i]));
|
|
}
|
|
|
|
btk_cell_editor_update_text(edited_note_cell);
|
|
btk_window_disable(main_win);
|
|
btk_map(session, entry_form);
|
|
}
|
|
|
|
void
|
|
entry_form_close()
|
|
{
|
|
btk_window_enable(main_win);
|
|
btk_unmap(session, entry_form);
|
|
}
|
|
|
|
/* checks if currently selected file in the file picker
|
|
* exists in the open hotpot directory */
|
|
int
|
|
file_exists()
|
|
{
|
|
DIR *d;
|
|
struct dirent *dir;
|
|
|
|
d = opendir(open_dir);
|
|
if (!d) {
|
|
printf("ERROR - couldn't read directory");
|
|
return 0;
|
|
}
|
|
|
|
while ((dir = readdir(d))) {
|
|
if (!strcmp(dir->d_name, dir_list + nav_select * NAME_SIZE))
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
file_picker_close()
|
|
{
|
|
btk_window_enable(main_win);
|
|
btk_unmap(session, file_picker);
|
|
}
|
|
|
|
void
|
|
file_picker_open(int mode)
|
|
{
|
|
btk_cell_list_deselect(dir_list_cell);
|
|
set_file_picker_states(-1);
|
|
|
|
file_picker_mode = mode;
|
|
if (!file_picker_mode) {
|
|
nav_mode |= DIR_FILES;
|
|
} else {
|
|
nav_mode &= ~DIR_FILES;
|
|
}
|
|
|
|
btk_window_disable(main_win);
|
|
btk_map(session, file_picker);
|
|
parse_dir(dir_current, nav_mode);
|
|
}
|
|
|
|
void file_picker_open_entry() { file_picker_open(0); }
|
|
void file_picker_open_open() { file_picker_open(1); }
|
|
void file_picker_open_new() { file_picker_open(2); }
|
|
|
|
void
|
|
file_picker_select()
|
|
{
|
|
if (nav_select < 0 || nav_select >= dir_list_n) {
|
|
printf("ERROR -> tried to open out of bound selection\n");
|
|
return;
|
|
}
|
|
|
|
switch(file_picker_mode) {
|
|
|
|
/* copy selected file into open hotpot directory, then add it to data */
|
|
case 0:;
|
|
/* compose command */
|
|
char cmd[12 + 2 * PATH_SIZE + NAME_SIZE];
|
|
sprintf(cmd,
|
|
"cp -n \'%s%s\' \'%s\'",
|
|
dir_current,
|
|
dir_list + nav_select * NAME_SIZE,
|
|
open_dir);
|
|
system(cmd);
|
|
/* create new entry */
|
|
data_entry_t new_entry;
|
|
new_entry.notes_w = 0;
|
|
new_entry.notes[0] = '\0';
|
|
new_entry.uid[0] = '\0';
|
|
for (int i = 0; i < DATA_COLS_N; i++)
|
|
new_entry.misc[i][0] = '\0';
|
|
strcpy(new_entry.filename, dir_list + nav_select * NAME_SIZE);
|
|
push_entry(TAG_NEW, new_entry);
|
|
/* update window */
|
|
set_activity_status(STATUS_EDITED, 0);
|
|
set_entry_tag_col(data_n - 1, data_tags[data_n - 1]);
|
|
set_main_win_states(1);
|
|
break;
|
|
|
|
/* open hotpot */
|
|
case 1:
|
|
strcpy(open_dir, dir_current);
|
|
strcat(open_dir, dir_list + nav_select * NAME_SIZE);
|
|
hotpot_load();
|
|
break;
|
|
|
|
/* create hotpot file, then open it */
|
|
case 2:
|
|
strcpy(open_dir, dir_current);
|
|
strcat(open_dir, dir_list + nav_select * NAME_SIZE);
|
|
char hotpot_file[PATH_SIZE + NAME_SIZE];
|
|
strcpy(hotpot_file, open_dir);
|
|
strcat(hotpot_file, "/.htpt");
|
|
FILE *f = fopen(hotpot_file, "w");
|
|
if (!f) {
|
|
set_activity_status(STATUS_ERROR, 1);
|
|
printf("ERROR - couldn't create new hotpot file");
|
|
return;
|
|
}
|
|
fclose(f);
|
|
hotpot_load();
|
|
break;
|
|
}
|
|
|
|
file_picker_close();
|
|
set_main_win_states(1);
|
|
}
|
|
|
|
/* returns the hilight color index of the directory */
|
|
int
|
|
find_dir_spot(char *search_dir, char *sub_dir)
|
|
{
|
|
char search_path[PATH_SIZE];
|
|
strcpy(search_path, search_dir);
|
|
strcat(search_path, sub_dir);
|
|
strcat(search_path, "/");
|
|
|
|
DIR *d;
|
|
struct dirent *dir;
|
|
struct stat file_stats;
|
|
char file_path[PATH_SIZE + NAME_SIZE];
|
|
|
|
d = opendir(search_path);
|
|
if (!d) {
|
|
printf("ERROR - couldn't read directory");
|
|
return 0;
|
|
}
|
|
|
|
while ((dir = readdir(d))) {
|
|
strcpy(file_path, search_path);
|
|
strcat(file_path, dir->d_name);
|
|
stat(file_path, &file_stats);
|
|
if ((file_stats.st_mode & S_IFMT) != S_IFDIR) {
|
|
if (strcmp(dir->d_name, ".htpt") == 0) {
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
return 2;
|
|
}
|
|
|
|
char*
|
|
get_data_item(unsigned int col, unsigned int row)
|
|
{
|
|
return data + ITEM_SIZE * (col + row * (DATA_COLS_N + 3));
|
|
}
|
|
|
|
void
|
|
hotpot_close()
|
|
{
|
|
hotpot_unload();
|
|
select_data = -1;
|
|
strcpy(select_note, "");
|
|
strcpy(open_dir, "");
|
|
|
|
set_main_win_states(1);
|
|
}
|
|
|
|
void
|
|
hotpot_load()
|
|
{
|
|
set_activity_status(STATUS_BUSY, 1);
|
|
|
|
char hotpot_file[PATH_SIZE + NAME_SIZE];
|
|
strcpy(hotpot_file, open_dir);
|
|
strcat(hotpot_file, "/.htpt");
|
|
|
|
FILE *f = fopen(hotpot_file, "r");
|
|
if (!f) {
|
|
printf("ERROR - couldn't read hotpot file\n");
|
|
set_activity_status(STATUS_ERROR, 1);
|
|
return;
|
|
}
|
|
|
|
hotpot_unload();
|
|
|
|
/* arrays preparation for on the go resizing */
|
|
data_buffer_n = DATA_BUFFER_INC;
|
|
data = malloc(data_buffer_n * ITEM_SIZE * (DATA_COLS_N + 3));
|
|
data_notes = malloc(data_buffer_n * TEXT_SIZE);
|
|
data_tags = malloc(data_buffer_n * sizeof(int));
|
|
data_spot = malloc(data_buffer_n * sizeof(int));
|
|
data_rename = malloc(data_buffer_n * ITEM_SIZE); /* used for syncing later */
|
|
|
|
data_entry_t entry_read;
|
|
char line_read[READ_SIZE];
|
|
char *last_newline;
|
|
int in_section = 0, col = 0, w = 0;
|
|
|
|
/* get lastest used uid on the first line */
|
|
/* if it is not present it will be regenerated after the rest of the file has
|
|
* been parsed */
|
|
if (fgets(line_read, READ_SIZE, f) && line_read[0] == '-') {
|
|
last_uid = strtol(line_read + 1, NULL, 16);
|
|
} else {
|
|
last_uid = 0; /* to be regenerated */
|
|
}
|
|
|
|
/* parse rest of .htpt file */
|
|
while (fgets(line_read, READ_SIZE, f)) {
|
|
switch (line_read[0]) {
|
|
|
|
/* open section, reset entry_read */
|
|
case '[':
|
|
if (in_section)
|
|
break;
|
|
in_section = 1;
|
|
col = 0;
|
|
w = 0;
|
|
entry_read.notes_w = 0;
|
|
entry_read.notes[0] = '\0';
|
|
entry_read.uid[0] = '\0';
|
|
entry_read.filename[0] = '\0';
|
|
for (int i = 0; i < DATA_COLS_N; i++)
|
|
entry_read.misc[i][0] = '\0';
|
|
break;
|
|
|
|
/* close section, push entry_read to data */
|
|
case ']':
|
|
if (!in_section)
|
|
break;
|
|
in_section = 0;
|
|
last_newline = strrchr(entry_read.notes, '\n');
|
|
if (last_newline) /* remove last unecessary newline */
|
|
*last_newline = '\0';
|
|
push_entry(TAG_STRAY, entry_read);
|
|
break;
|
|
|
|
/* get uid */
|
|
case '-':
|
|
if (!in_section)
|
|
break;
|
|
clean_string_copy(entry_read.uid, line_read + 1, ITEM_SIZE, 1);
|
|
break;
|
|
|
|
/* get filename */
|
|
case '+':
|
|
if (!in_section)
|
|
break;
|
|
clean_string_copy(entry_read.filename, line_read + 1, ITEM_SIZE, 1);
|
|
break;
|
|
|
|
/* get other data */
|
|
case '.':
|
|
if (!in_section || col >= DATA_COLS_N)
|
|
break;
|
|
clean_string_copy(entry_read.misc[col], line_read + 1, ITEM_SIZE, 1);
|
|
col++;
|
|
break;
|
|
|
|
/* get notes on multiple lines until section close or reaching TEXT_SIZE
|
|
* character limit */
|
|
case '*':
|
|
if (!in_section)
|
|
break;
|
|
w = strlen(line_read + 1);
|
|
if (entry_read.notes_w + w >= TEXT_SIZE) {
|
|
w = TEXT_SIZE - entry_read.notes_w;
|
|
} else {
|
|
strncat(entry_read.notes, line_read + 1, w);
|
|
}
|
|
entry_read.notes_w += w;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
fclose(f);
|
|
|
|
/* regenerate uid if needed */
|
|
if (!last_uid) {
|
|
for (int i = 0; i < data_n; i++)
|
|
if (last_uid < strtol(get_data_item(UID_COL, i), NULL, 16))
|
|
last_uid = strtol(get_data_item(UID_COL, i), NULL, 16);
|
|
}
|
|
|
|
/* parse all files in hotpot directory and match them to parsed data */
|
|
DIR *d = opendir(open_dir);
|
|
struct dirent *dir;
|
|
struct stat file_stats;
|
|
char file_path[PATH_SIZE + NAME_SIZE];
|
|
int found = 0;
|
|
int new_files = 0;
|
|
int n = data_n;
|
|
int is_dir;
|
|
|
|
data_entry_t dummy_entry;
|
|
dummy_entry.uid[0] = '\0';
|
|
dummy_entry.notes[0] = '\0';
|
|
dummy_entry.notes_w = 0;
|
|
for (int i = 0; i < DATA_COLS_N; i++)
|
|
dummy_entry.misc[i][0] = '\0';
|
|
|
|
/* scan found files */
|
|
while ((dir = readdir(d))) {
|
|
found = 0;
|
|
strcpy(file_path, open_dir);
|
|
strcat(file_path, dir->d_name);
|
|
stat(file_path, &file_stats);
|
|
is_dir = (file_stats.st_mode & S_IFMT) == S_IFDIR ? 1 : 0;
|
|
//printf("%i\t%s\n", is_dir, dir->d_name); TODO fix directory detection
|
|
if (is_dir || dir->d_name[0] == '.') {
|
|
continue;
|
|
}
|
|
for (int i = 0; i < n; i++) {
|
|
if (strcmp(dir->d_name, get_data_item(NAME_COL, i)) == 0) {
|
|
data_tags[i] = TAG_NONE;
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
/* if file not found, create new entry */
|
|
if (!found) {
|
|
clean_string_copy(dummy_entry.filename, dir->d_name, ITEM_SIZE, 0);
|
|
push_entry(TAG_NEW, dummy_entry);
|
|
new_files = 1;
|
|
}
|
|
}
|
|
|
|
/* set tag values in data */
|
|
for (int i = 0; i < data_n; i++) {
|
|
set_entry_tag_col(i, data_tags[i]);
|
|
}
|
|
|
|
btk_cell_table_deselect(table_cell);
|
|
strcpy(select_note, "");
|
|
set_activity_status((new_files ? STATUS_EDITED : STATUS_LATEST), 1);
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
hotpot_reload()
|
|
{
|
|
hotpot_unload();
|
|
select_data = -1;
|
|
strcpy(select_note, "");
|
|
|
|
hotpot_load();
|
|
|
|
set_main_win_states(1);
|
|
}
|
|
|
|
void
|
|
hotpot_sync()
|
|
{
|
|
set_activity_status(STATUS_BUSY, 1);
|
|
|
|
char hotpot_file[PATH_SIZE + NAME_SIZE];
|
|
strcpy(hotpot_file, open_dir);
|
|
strcat(hotpot_file, "/.htpt");
|
|
|
|
FILE *f = fopen(hotpot_file, "w");
|
|
if (!f) {
|
|
printf("ERROR - couldn't write hotpot file\n");
|
|
set_activity_status(STATUS_ERROR, 1);
|
|
return;
|
|
}
|
|
|
|
/* output last uid */
|
|
fprintf(f, "-%X\n\n", last_uid);
|
|
|
|
/* output rows of data */
|
|
char *note_token;
|
|
char note[TEXT_SIZE];
|
|
for (int i = 0; i < data_n; i++) {
|
|
|
|
if ((data_tags[i] & TAG_DEL))
|
|
continue;
|
|
|
|
fprintf(f, "[\n");
|
|
|
|
fprintf(f, "-%s\n", get_data_item(UID_COL, i));
|
|
fprintf(f, "+%s\n", get_data_item(NAME_COL, i));
|
|
for (int j = 0; j < DATA_COLS_N; j++)
|
|
fprintf(f, ".%s\n", get_data_item(j + 3, i));
|
|
|
|
// TODO
|
|
/*
|
|
strcpy(note, data_notes + i * TEXT_SIZE);
|
|
char *lim = strchr(note, '\n');
|
|
while (lim) {
|
|
*lim = '\0';
|
|
printf("%lu >> \'%s\'\n", strlen(note), note);
|
|
fprintf(f, "*%s\n", note);
|
|
strcpy(note, ++lim);
|
|
lim = strchr(note, '\n');
|
|
}
|
|
*/
|
|
|
|
strcpy(note, data_notes + i * TEXT_SIZE);
|
|
note_token = strtok(note, "\n");
|
|
while (note_token) {
|
|
fprintf(f, "*%s\n", note_token);
|
|
note_token = strtok(NULL, "\n");
|
|
}
|
|
|
|
fprintf(f, "]\n\n");
|
|
}
|
|
fclose(f);
|
|
|
|
/* rename edited files if those are not stray entries */
|
|
char cmd_mv[11 + 2 * (PATH_SIZE + NAME_SIZE)];
|
|
for (int i = 0; i < data_n; i++) {
|
|
if (!(data_tags[i] & TAG_STRAY) && strcmp(data_rename + i * ITEM_SIZE, "")) {
|
|
sprintf(cmd_mv,
|
|
"mv \'%s/%s\' \'%s/%s\'",
|
|
open_dir,
|
|
data_rename + i * ITEM_SIZE,
|
|
open_dir,
|
|
get_data_item(NAME_COL, i));
|
|
system(cmd_mv);
|
|
}
|
|
}
|
|
|
|
/* delete rows with DEL tag by shifting down */
|
|
int c = 0;
|
|
char mid[TEXT_SIZE]; /* just to get rid of pointer overlap warning */
|
|
char cmd_rm[5 + PATH_SIZE + NAME_SIZE];
|
|
for (int i = 0; i < data_n; i++) {
|
|
if (c) {
|
|
data_tags[i - c] = data_tags[i];
|
|
strcpy(mid, data_notes + i * TEXT_SIZE);
|
|
strcpy(data_notes + (i - c) * TEXT_SIZE, mid);
|
|
for (int j = 0; j < DATA_COLS_N + 3; j++)
|
|
strcpy(get_data_item(j, i - c), get_data_item(j, i));
|
|
}
|
|
if ((data_tags[i] & TAG_DEL)) {
|
|
if (!(data_tags[i] & TAG_STRAY)) {
|
|
sprintf(cmd_rm,
|
|
"rm \'%s/%s\'",
|
|
open_dir,
|
|
get_data_item(NAME_COL, i));
|
|
system(cmd_rm);
|
|
}
|
|
c++;
|
|
}
|
|
}
|
|
data_n -= c;
|
|
|
|
/* remove EDIT and NEW tags */
|
|
for (int i = 0; i < data_n; i++) {
|
|
data_tags[i] &= ~(TAG_EDITED | TAG_NEW);
|
|
}
|
|
|
|
/* update tag values in data */
|
|
for (int i = 0; i < data_n; i++) {
|
|
set_entry_tag_col(i, data_tags[i]);
|
|
}
|
|
|
|
set_activity_status(STATUS_LATEST, 0);
|
|
btk_window_redraw(main_win);
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
hotpot_unload()
|
|
{
|
|
if (data_n) {
|
|
free(data);
|
|
free(data_tags);
|
|
free(data_spot);
|
|
free(data_notes);
|
|
free(data_rename);
|
|
data_n = 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
move_dir(int dir_sel)
|
|
{
|
|
if (dir_sel < 0 || !dir_spot[dir_sel])
|
|
return;
|
|
|
|
/* if first item selected ("..") go one dir up, unless at / */
|
|
if (!dir_sel) {
|
|
if (strlen(dir_current) <= 1)
|
|
return;
|
|
dir_current[strlen(dir_current) - 1] = '\0';
|
|
*(strrchr(dir_current, '/')) = '\0';
|
|
} else {
|
|
char dir_sel_name[PATH_SIZE];
|
|
strcpy(dir_sel_name, dir_list + dir_sel * NAME_SIZE);
|
|
strcat(dir_current, dir_sel_name);
|
|
}
|
|
|
|
strcat(dir_current, "/");
|
|
parse_dir(dir_current, nav_mode);
|
|
btk_window_redraw_cell(file_picker, dir_list_cell_id);
|
|
btk_window_redraw_cell(file_picker, 2);
|
|
|
|
if (dir_sel) {
|
|
btk_cell_list_deselect(dir_list_cell);
|
|
set_file_picker_states(-1);
|
|
}
|
|
}
|
|
|
|
void
|
|
open_ext_dir()
|
|
{
|
|
char *args[PATH_SIZE]={"./EXEC", open_dir, NULL};
|
|
int pid = fork();
|
|
|
|
if (pid == 0) {
|
|
execvp("xdg-open", args);
|
|
} else if (pid < 0) {
|
|
printf("ERROR - couldn't open hotpot directory in file explorer\n");
|
|
}
|
|
}
|
|
|
|
void
|
|
open_ext_entry(int sel)
|
|
{
|
|
if (sel < 0)
|
|
return;
|
|
|
|
char file[PATH_SIZE + ITEM_SIZE];
|
|
strcpy(file, open_dir);
|
|
strcat(file, "/");
|
|
strcat(file, get_data_item(NAME_COL, sel));
|
|
|
|
char *args[PATH_SIZE]={"./EXEC", file, NULL};
|
|
int pid = fork();
|
|
|
|
if (pid == 0) {
|
|
execvp("xdg-open", args);
|
|
} else if (pid < 0) {
|
|
printf("ERROR - couldn't open item externaly\n");
|
|
}
|
|
}
|
|
|
|
int
|
|
parse_dir(char *dir_path, int mode)
|
|
{
|
|
DIR *d = opendir(dir_path);
|
|
if (!d) {
|
|
printf("ERROR - couldn't read directory");
|
|
return 1;
|
|
}
|
|
|
|
struct dirent *dir;
|
|
struct stat file_stats;
|
|
char file_path[PATH_SIZE + NAME_SIZE];
|
|
unsigned int dir_buffer_n = DIR_BUFFER_INC;
|
|
int c = 0;
|
|
int is_dir;
|
|
|
|
if (dir_list_n) {
|
|
free(dir_list);
|
|
free(dir_spot);
|
|
}
|
|
|
|
dir_list_n = 0;
|
|
dir_list = malloc(dir_buffer_n * NAME_SIZE);
|
|
dir_spot = malloc(dir_buffer_n * sizeof(int));
|
|
|
|
while ((dir = readdir(d))) {
|
|
sprintf(file_path, "%s%s", dir_path, dir->d_name);
|
|
stat(file_path, &file_stats);
|
|
is_dir = (file_stats.st_mode & S_IFMT) == S_IFDIR ? 1 : 0;
|
|
if (((mode & DIR_FILES) || is_dir) && c &&
|
|
((mode & DIR_HIDDEN) || dir->d_name[0] != '.' || c < 2)) {
|
|
strcpy(dir_list + dir_list_n * NAME_SIZE, dir->d_name);
|
|
if (is_dir) /* adding '/' to dir items to easily detect them when sorting */
|
|
strcat(dir_list + dir_list_n * NAME_SIZE, "/");
|
|
dir_spot[dir_list_n] = 0;
|
|
dir_list_n++;
|
|
}
|
|
c++;
|
|
if (dir_list_n >= dir_buffer_n - 1) {
|
|
dir_buffer_n += DIR_BUFFER_INC;
|
|
dir_spot = realloc(dir_spot, dir_buffer_n * sizeof(int));
|
|
dir_list = realloc(dir_list, dir_buffer_n * NAME_SIZE);
|
|
}
|
|
}
|
|
|
|
/* sort dir list and set hilights */
|
|
char *a;
|
|
qsort(dir_list, dir_list_n, NAME_SIZE, cmp_str_for_qsort);
|
|
for (int i = 0; i < dir_list_n; i++) {
|
|
a = strchr(dir_list + i * NAME_SIZE, '/');
|
|
if (a) {
|
|
*a = '\0';
|
|
dir_spot[i] = find_dir_spot(dir_path, dir_list + i * NAME_SIZE);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
push_entry(int tag, data_entry_t entry)
|
|
{
|
|
if (!data) {
|
|
printf("ERROR - tried to push entry into NULL data array\n");
|
|
return;
|
|
}
|
|
|
|
if (data_n >= data_buffer_n - 1) {
|
|
data_buffer_n += DATA_BUFFER_INC;
|
|
data = realloc(data, data_buffer_n * ITEM_SIZE * (DATA_COLS_N + 3));
|
|
data_notes = realloc(data_notes, data_buffer_n * TEXT_SIZE);
|
|
data_tags = realloc(data_tags, data_buffer_n * sizeof(int));
|
|
data_spot = realloc(data_spot, data_buffer_n * sizeof(int));
|
|
data_rename = realloc(data_rename, data_buffer_n * ITEM_SIZE);
|
|
}
|
|
|
|
if (!strcmp(entry.uid, "")) {
|
|
char new_uid[64];
|
|
sprintf(new_uid, "%X", ++last_uid);
|
|
strcpy(get_data_item(UID_COL, data_n), new_uid);
|
|
} else {
|
|
strcpy(get_data_item(UID_COL, data_n), entry.uid);
|
|
}
|
|
|
|
data_tags[data_n] = tag;
|
|
strcpy(data_rename + data_n * ITEM_SIZE, "");
|
|
strcpy(get_data_item(NAME_COL, data_n), entry.filename);
|
|
for (int i = 0; i < DATA_COLS_N; i++)
|
|
strcpy(get_data_item(i + 3, data_n), entry.misc[i]);
|
|
strcpy(data_notes + data_n * TEXT_SIZE, entry.notes);
|
|
|
|
data_n++;
|
|
}
|
|
|
|
void
|
|
quit()
|
|
{
|
|
hotpot_unload();
|
|
if (dir_list_n) {
|
|
free(dir_list);
|
|
free(dir_spot);
|
|
}
|
|
|
|
btk_window_destroy(entry_form);
|
|
btk_window_destroy(file_picker);
|
|
btk_window_destroy(main_win);
|
|
btk_window_destroy(settings);
|
|
btk_close(session);
|
|
|
|
exit(0);
|
|
}
|
|
|
|
void
|
|
settings_close()
|
|
{
|
|
btk_window_enable(main_win);
|
|
btk_unmap(session, settings);
|
|
}
|
|
|
|
void
|
|
settings_open()
|
|
{
|
|
btk_window_disable(main_win);
|
|
btk_map(session, settings);
|
|
}
|
|
|
|
void
|
|
set_activity_status(int status, int redraw)
|
|
{
|
|
switch (status) {
|
|
case STATUS_NONE:
|
|
strcpy(status_activity, "n/a");
|
|
activity_cell->state |= BTK_CELL_STATE_DISABLED;
|
|
activity_cell->state &= ~BTK_CELL_STATE_BELL;
|
|
activity_cell->state &= ~BTK_CELL_STATE_ON;
|
|
break;
|
|
case STATUS_ERROR:
|
|
strcpy(status_activity, "error");
|
|
activity_cell->state &= ~BTK_CELL_STATE_DISABLED;
|
|
activity_cell->state |= BTK_CELL_STATE_BELL;
|
|
activity_cell->state &= ~BTK_CELL_STATE_ON;
|
|
break;
|
|
case STATUS_LATEST:
|
|
strcpy(status_activity, "synced");
|
|
activity_cell->state &= ~BTK_CELL_STATE_DISABLED;
|
|
activity_cell->state &= ~BTK_CELL_STATE_BELL;
|
|
activity_cell->state &= ~BTK_CELL_STATE_ON;
|
|
break;
|
|
case STATUS_EDITED:
|
|
strcpy(status_activity, "unsynced");
|
|
activity_cell->state &= ~BTK_CELL_STATE_DISABLED;
|
|
activity_cell->state &= ~BTK_CELL_STATE_BELL;
|
|
activity_cell->state |= BTK_CELL_STATE_ON;
|
|
break;
|
|
case STATUS_BUSY:
|
|
strcpy(status_activity, "busy");
|
|
activity_cell->state &= ~BTK_CELL_STATE_DISABLED;
|
|
activity_cell->state |= BTK_CELL_STATE_BELL;
|
|
activity_cell->state &= ~BTK_CELL_STATE_ON;
|
|
break;
|
|
}
|
|
|
|
if (redraw)
|
|
btk_window_redraw_cell(main_win, activity_cell_id);
|
|
}
|
|
|
|
void
|
|
set_edit_tag()
|
|
{
|
|
if (select_data < 0 || select_data >= data_n) {
|
|
printf("ERROR - can't tag out of bounds selection\n");
|
|
return;
|
|
}
|
|
|
|
data_tags[select_data] |= TAG_DEL;
|
|
btk_window_redraw_cell(main_win, table_cell_id);
|
|
}
|
|
|
|
void
|
|
set_entry_tag_col(unsigned int id, int tag)
|
|
{
|
|
if (tag & TAG_DEL) {
|
|
strcpy(get_data_item(TAG_COL, id), "DEL");
|
|
data_spot[id] = 1;
|
|
} else if (tag & TAG_VISIBILITY) {
|
|
strcpy(get_data_item(TAG_COL, id), "FOCUS");
|
|
data_spot[id] = 4;
|
|
} else if (tag & TAG_EDITED){
|
|
strcpy(get_data_item(TAG_COL, id), "EDIT");
|
|
data_spot[id] = 1;
|
|
} else if (tag & TAG_STRAY){
|
|
strcpy(get_data_item(TAG_COL, id), "STRAY");
|
|
data_spot[id] = 3;
|
|
} else if (tag & TAG_NEW){
|
|
strcpy(get_data_item(TAG_COL, id), "NEW");
|
|
data_spot[id] = 2;
|
|
} else {
|
|
strcpy(get_data_item(TAG_COL, id), "");
|
|
data_spot[id] = 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
set_file_picker_states(int sel)
|
|
{
|
|
nav_select = sel;
|
|
|
|
if (sel < 1) { /* separate to avoid segfault */
|
|
file_select_cell->state |= BTK_CELL_STATE_DISABLED;
|
|
btk_window_redraw_cell(file_picker, file_select_cell_id);
|
|
return;
|
|
}
|
|
|
|
switch (file_picker_mode) {
|
|
case 0:;
|
|
char forbidden_path[PATH_SIZE];
|
|
strcpy(forbidden_path, open_dir);
|
|
strcat(forbidden_path, "/");
|
|
if(!dir_spot[sel] && strcmp(dir_current, forbidden_path) != 0 && !file_exists()) {
|
|
file_select_cell->state &= ~(BTK_CELL_STATE_DISABLED);
|
|
} else {
|
|
file_select_cell->state |= BTK_CELL_STATE_DISABLED;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (dir_spot[sel] == 1) {
|
|
file_select_cell->state &= ~(BTK_CELL_STATE_DISABLED);
|
|
} else {
|
|
file_select_cell->state |= BTK_CELL_STATE_DISABLED;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (dir_spot[sel] == 1) {
|
|
file_select_cell->state |= BTK_CELL_STATE_DISABLED;
|
|
} else {
|
|
file_select_cell->state &= ~(BTK_CELL_STATE_DISABLED);
|
|
}
|
|
break;
|
|
}
|
|
|
|
btk_window_redraw_cell(file_picker, file_select_cell_id);
|
|
}
|
|
|
|
void
|
|
set_main_win_states(int redraw)
|
|
{
|
|
if (!(strcmp(open_dir, ""))) {
|
|
main_win->cells[4].state |= BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[5].state |= BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[6].state |= BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[7].state |= BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[10].state |= BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[16].state |= BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[17].state |= BTK_CELL_STATE_DISABLED;
|
|
strcpy(status_open_file, "no hotpot opened");
|
|
strcpy(status_files_n, "n/a entries");
|
|
set_activity_status(STATUS_NONE, redraw);
|
|
} else {
|
|
main_win->cells[4].state &= ~BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[5].state &= ~BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[6].state &= ~BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[7].state &= ~BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[10].state &= ~BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[16].state &= ~BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[17].state &= ~BTK_CELL_STATE_DISABLED;
|
|
strcpy(status_open_file, open_dir);
|
|
sprintf(status_files_n, "%i entries", data_n);
|
|
}
|
|
|
|
if (data_n < 1 || select_data < 0) {
|
|
main_win->cells[11].state |= BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[12].state |= BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[19].state |= BTK_CELL_STATE_DISABLED;
|
|
} else {
|
|
main_win->cells[11].state &= ~BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[12].state &= ~BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[19].state &= ~BTK_CELL_STATE_DISABLED;
|
|
}
|
|
|
|
if (redraw)
|
|
btk_window_redraw(main_win);
|
|
}
|
|
|
|
void
|
|
str_to_lower_case(char *str)
|
|
{
|
|
for (int i = 0; str[i] != '\0'; i++)
|
|
if(str[i] >= 'A' && str[i] <= 'Z')
|
|
str[i] += 32;
|
|
}
|
|
|
|
void
|
|
toggle_col(int val, btk_arg_t arg)
|
|
{
|
|
data_cols_ena[arg.i] = val;
|
|
btk_cell_table_update_geometry(table_cell);
|
|
btk_window_redraw_cell(main_win, table_cell_id);
|
|
}
|
|
|
|
void
|
|
toggle_del_tag()
|
|
{
|
|
if (select_data < 0 || select_data >= data_n) {
|
|
printf("ERROR - can't tag out of bounds selection\n");
|
|
return;
|
|
}
|
|
|
|
data_tags[select_data] ^= TAG_DEL;
|
|
set_entry_tag_col(select_data, data_tags[select_data]);
|
|
set_activity_status(STATUS_EDITED, 1);
|
|
btk_window_redraw_cell(main_win, table_cell_id);
|
|
}
|
|
|
|
void
|
|
toggle_hidden(int i, btk_arg_t arg)
|
|
{
|
|
if (i) {
|
|
nav_mode |= DIR_HIDDEN;
|
|
} else {
|
|
nav_mode &= ~DIR_HIDDEN;
|
|
}
|
|
parse_dir(dir_current, nav_mode);
|
|
btk_window_redraw_cell(file_picker, dir_list_cell_id);
|
|
}
|
|
|
|
void
|
|
toggle_notes(int val, btk_arg_t arg)
|
|
{
|
|
if (val) {
|
|
table_cell->ca.h = 9;
|
|
notes_view_cell->state &= ~BTK_CELL_STATE_HIDDEN;
|
|
} else {
|
|
table_cell->ca.h = 15;
|
|
notes_view_cell->state |= BTK_CELL_STATE_HIDDEN;
|
|
}
|
|
btk_window_update_cell_area(main_win, table_cell);
|
|
btk_window_redraw(main_win);
|
|
}
|
|
|
|
void
|
|
toggle_visibility_tag()
|
|
{
|
|
if (select_data < 0 || select_data >= data_n) {
|
|
printf("ERROR - can't tag out of bounds selection\n");
|
|
return;
|
|
}
|
|
|
|
data_tags[select_data] ^= TAG_VISIBILITY;
|
|
set_entry_tag_col(select_data, data_tags[select_data]);
|
|
btk_window_redraw_cell(main_win, table_cell_id);
|
|
}
|
|
|
|
void
|
|
update_select_data(int sel)
|
|
{
|
|
select_data = sel;
|
|
if (sel > data_n)
|
|
select_data = -1;
|
|
|
|
if (select_data < 0) {
|
|
strcpy(select_note, "");
|
|
main_win->cells[11].state |= BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[12].state |= BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[19].state |= BTK_CELL_STATE_DISABLED;
|
|
} else {
|
|
strcpy(select_note,data_notes + sel * TEXT_SIZE);
|
|
main_win->cells[11].state &= ~BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[12].state &= ~BTK_CELL_STATE_DISABLED;
|
|
main_win->cells[19].state &= ~BTK_CELL_STATE_DISABLED;
|
|
}
|
|
|
|
btk_cell_editor_update_text(notes_view_cell);
|
|
btk_window_redraw_cell(main_win, notes_view_cell_id);
|
|
btk_window_redraw_cell(main_win, 11);
|
|
btk_window_redraw_cell(main_win, 12);
|
|
btk_window_redraw_cell(main_win, 19);
|
|
}
|