moved code here. still needs to update gh

This commit is contained in:
klein panic
2025-02-24 15:18:44 -05:00
parent 9ca9f577a4
commit 2726432fe1
106 changed files with 4816 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
# Compiler and Flags
CC = gcc
CFLAGS = -Wall -Wextra -std=c11 -g
LDFLAGS = -lncurses
# Source Files
SRCS = main.c
OBJS = $(SRCS:.c=.o)
# Output Binary
TARGET = calendar
# Default Target
all: $(TARGET)
# Build Target
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS)
# Object Files
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# Clean Target
clean:
rm -f $(OBJS) $(TARGET)
# Run Target
run: $(TARGET)
./$(TARGET)
# Phony Targets
.PHONY: all clean run

BIN
ncursescalander/backup/calendar Executable file

Binary file not shown.

View File

@@ -0,0 +1,326 @@
#include <ncurses.h>
#include <string.h>
#include <time.h>
#define MAX_TITLE_LEN 50
#define MAX_CALENDAR_LEN 30
#define MAX_NOTES_LEN 256
void draw_calendar(int month, int year, int selected_day);
void draw_day_view(int *day, int *month, int *year);
void open_add_event_tui();
void open_repeat_tui();
int main() {
int ch, month, year, day = 1;
time_t now;
struct tm *local;
// Initialize ncurses
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
start_color();
init_pair(1, COLOR_RED, COLOR_BLACK); // Red color pair for the current time
// Get current date
now = time(NULL);
local = localtime(&now);
month = local->tm_mon + 1;
year = local->tm_year + 1900;
day = local->tm_mday;
// Main loop
while ((ch = getch()) != 'q') {
bool redraw = false;
switch (ch) {
case KEY_LEFT:
case 'j':
if (day > 1) {
day--;
redraw = true;
}
break;
case KEY_RIGHT:
case 'k':
if (day < 31) { // Simplified for demo purposes
day++;
redraw = true;
}
break;
case 'a': // 'a' for "Add Event"
open_add_event_tui();
redraw = true;
break;
case '\n': // Enter key to open the day view
draw_day_view(&day, &month, &year);
redraw = true;
break;
}
if (redraw) {
clear();
mvprintw(0, 0, "Calendar View - Press 'a' to Add Event");
draw_calendar(month, year, day);
refresh();
}
}
// End ncurses mode
endwin();
return 0;
}
void draw_calendar(int month, int year, int selected_day) {
mvprintw(1, 0, "Month: %d, Year: %d", month, year);
mvprintw(2, 0, "Su Mo Tu We Th Fr Sa");
// Placeholder for calendar drawing
for (int i = 1; i <= 30; i++) { // Simplified example for 30 days
if (i == selected_day) {
attron(A_REVERSE); // Highlight the selected day
}
mvprintw(3 + (i / 7), (i % 7) * 3, "%2d", i);
if (i == selected_day) {
attroff(A_REVERSE);
}
}
}
void draw_day_view(int *day, int *month, int *year) {
time_t now;
struct tm *local;
int ch;
bool redraw = true;
while (true) {
if (redraw) {
clear();
mvprintw(0, 0, "Day View");
mvprintw(1, 0, "Date: %02d-%02d-%04d", *day, *month, *year);
// Draw the hours of the day
for (int i = 0; i < 24; i++) {
mvprintw(i + 3, 0, "%02d:00 |", i);
mvhline(i + 3, 8, ' ', COLS - 8);
}
now = time(NULL);
local = localtime(&now);
if (local->tm_mday == *day && (local->tm_mon + 1) == *month && (local->tm_year + 1900) == *year) {
int current_hour = local->tm_hour;
int current_minute = local->tm_min;
attron(COLOR_PAIR(1)); // Red color
mvhline(current_hour + 3, 8, '-', COLS - 8);
mvprintw(current_hour + 3, 0, "%02d:%02d |", current_hour, current_minute);
attroff(COLOR_PAIR(1));
}
refresh();
redraw = false;
}
nodelay(stdscr, TRUE); // Make getch non-blocking
ch = getch();
if (ch == 'q') break; // Exit to Calendar View
if (ch == KEY_LEFT || ch == 'j') {
if (*day > 1) {
(*day)--;
} else {
if (*month > 1) {
(*month)--;
} else {
*month = 12;
(*year)--;
}
*day = 31; // Simplified for demo purposes
}
redraw = true;
} else if (ch == KEY_RIGHT || ch == 'k') {
if (*day < 31) { // Simplified for demo purposes
(*day)++;
} else {
*day = 1;
if (*month < 12) {
(*month)++;
} else {
*month = 1;
(*year)++;
}
}
redraw = true;
}
napms(1000);
}
nodelay(stdscr, FALSE);
}
void open_add_event_tui() {
char title[MAX_TITLE_LEN] = "";
char calendar[MAX_CALENDAR_LEN] = "";
char notes[MAX_NOTES_LEN] = "";
int ch;
bool all_day = false;
int start_day = 1, end_day = 1;
int start_hour = 9, start_minute = 0;
int end_hour = 10, end_minute = 0;
int repeat_option = 0;
char repeat_options[4][20] = {"Never", "Every Day", "Every Week", "Custom"};
int cursor_pos = 0;
while (true) {
clear();
mvprintw(0, 0, "Add New Event");
// Title input
mvprintw(2, 0, "Title: ");
if (cursor_pos == 0) attron(A_REVERSE);
mvprintw(2, 7, title);
if (cursor_pos == 0) attroff(A_REVERSE);
// All-day toggle
mvprintw(4, 0, "All Day: ");
if (cursor_pos == 1) attron(A_REVERSE);
mvprintw(4, 9, all_day ? "[X]" : "[ ]");
if (cursor_pos == 1) attroff(A_REVERSE);
// Start day and time
mvprintw(6, 0, "Start Day: %02d", start_day);
mvprintw(7, 0, "Start Time: ");
if (cursor_pos == 2) attron(A_REVERSE);
mvprintw(7, 12, "%02d:%02d", start_hour, start_minute);
if (cursor_pos == 2) attroff(A_REVERSE);
// End day and time
mvprintw(9, 0, "End Day: %02d", end_day);
mvprintw(10, 0, "End Time: ");
if (cursor_pos == 3) attron(A_REVERSE);
mvprintw(10, 10, "%02d:%02d", end_hour, end_minute);
if (cursor_pos == 3) attroff(A_REVERSE);
// Repeat options
mvprintw(12, 0, "Repeat: ");
if (cursor_pos == 4) attron(A_REVERSE);
mvprintw(12, 8, repeat_options[repeat_option]);
if (cursor_pos == 4) attroff(A_REVERSE);
// Calendar name input
mvprintw(14, 0, "Calendar: ");
if (cursor_pos == 5) attron(A_REVERSE);
mvprintw(14, 10, calendar);
if (cursor_pos == 5) attroff(A_REVERSE);
// Notes input
mvprintw(16, 0, "Notes: ");
if (cursor_pos == 6) attron(A_REVERSE);
mvprintw(17, 0, notes);
if (cursor_pos == 6) attroff(A_REVERSE);
// Instructions
mvprintw(19, 0, "Press 'q' to cancel, 's' to save");
refresh();
ch = getch();
if (ch == 'q') break; // Exit without saving
if (ch == 's') {
// Here, you would normally save the event
break;
}
// Handle navigation
if (ch == KEY_DOWN || ch == 'j') {
cursor_pos = (cursor_pos + 1) % 7;
} else if (ch == KEY_UP || ch == 'k') {
cursor_pos = (cursor_pos - 1 + 7) % 7;
}
// Handle specific field input
if (cursor_pos == 0 && ch != KEY_DOWN && ch != KEY_UP && ch != 's' && ch != 'q') {
int len = strlen(title);
if (ch == KEY_BACKSPACE || ch == 127) {
if (len > 0) title[len - 1] = '\0';
} else if (len < MAX_TITLE_LEN - 1) {
title[len] = ch;
title[len + 1] = '\0';
}
} else if (cursor_pos == 1 && (ch == ' ' || ch == '\n')) {
all_day = !all_day;
} else if (cursor_pos == 2 && (ch == ' ' || ch == '\n')) {
// Placeholder: Handle start day and time input
} else if (cursor_pos == 3 && (ch == ' ' || ch == '\n')) {
// Placeholder: Handle end day and time input
} else if (cursor_pos == 4 && (ch == ' ' || ch == '\n')) {
// Open repeat TUI
open_repeat_tui();
} else if (cursor_pos == 5 && ch != KEY_DOWN && ch != KEY_UP && ch != 's' && ch != 'q') {
int len = strlen(calendar);
if (ch == KEY_BACKSPACE || ch == 127) {
if (len > 0) calendar[len - 1] = '\0';
} else if (len < MAX_CALENDAR_LEN - 1) {
calendar[len] = ch;
calendar[len + 1] = '\0';
}
} else if (cursor_pos == 6 && ch != KEY_DOWN && ch != KEY_UP && ch != 's' && ch != 'q') {
int len = strlen(notes);
if (ch == KEY_BACKSPACE || ch == 127) {
if (len > 0) notes[len - 1] = '\0';
} else if (len < MAX_NOTES_LEN - 1) {
notes[len] = ch;
notes[len + 1] = '\0';
}
}
}
}
void open_repeat_tui() {
int ch;
int cursor_pos = 0;
while (true) {
clear();
mvprintw(0, 0, "Repeat Options");
mvprintw(2, 0, "1. Never");
if (cursor_pos == 0) attron(A_REVERSE);
mvprintw(2, 10, "Select");
if (cursor_pos == 0) attroff(A_REVERSE);
mvprintw(4, 0, "2. Every Day");
if (cursor_pos == 1) attron(A_REVERSE);
mvprintw(4, 10, "Select");
if (cursor_pos == 1) attroff(A_REVERSE);
mvprintw(6, 0, "3. Every Week");
if (cursor_pos == 2) attron(A_REVERSE);
mvprintw(6, 10, "Select");
if (cursor_pos == 2) attroff(A_REVERSE);
mvprintw(8, 0, "4. Custom");
if (cursor_pos == 3) attron(A_REVERSE);
mvprintw(8, 10, "Select");
if (cursor_pos == 3) attroff(A_REVERSE);
mvprintw(10, 0, "Press 'q' to return");
refresh();
ch = getch();
if (ch == 'q') break; // Return to the add event TUI
if (ch == KEY_DOWN || ch == 'j') {
cursor_pos = (cursor_pos + 1) % 4;
} else if (ch == KEY_UP || ch == 'k') {
cursor_pos = (cursor_pos - 1 + 4) % 4;
} else if (ch == '\n') {
// Here, you would handle selection logic
break; // Return after selection for now
}
}
}

Binary file not shown.

View File

@@ -0,0 +1,26 @@
# Makefile for ncurses calendar app
CC = gcc
CFLAGS = -Wall -Wextra -I../include
LDFLAGS = -lncurses -lsqlite3
SRC_DIR = ../src
BUILD_DIR = ../build
SRC_FILES = $(wildcard $(SRC_DIR)/*.c)
OBJ_FILES = $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(SRC_FILES))
TARGET = calendar_app
all: $(TARGET)
$(TARGET): $(OBJ_FILES)
$(CC) -o $@ $^ $(LDFLAGS)
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) -c -o $@ $<
clean:
rm -f $(BUILD_DIR)/*.o $(TARGET)
.PHONY: all clean

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,29 @@
#ifndef ADD_EVENT_H
#define ADD_EVENT_H
#include <sqlite3.h>
#include <stdbool.h>
#define MAX_TITLE_LEN 50
#define MAX_CALENDAR_LEN 30
#define MAX_NOTES_LEN 256
#define MAX_DATE_LEN 50
typedef struct {
char title[MAX_TITLE_LEN];
bool all_day;
char start_date[MAX_DATE_LEN];
char end_date[MAX_DATE_LEN];
int start_hour, start_minute;
int end_hour, end_minute;
int repeat_option;
char calendar[MAX_CALENDAR_LEN];
char notes[MAX_NOTES_LEN];
} Event;
Event *create_event();
void save_event_to_db(sqlite3 *db, Event *event);
sqlite3* open_database();
void open_add_event_tui(sqlite3 *db);
#endif

View File

@@ -0,0 +1,8 @@
#ifndef CALENDAR_H
#define CALENDAR_H
int is_leap_year(int year);
int days_in_month(int month, int year);
void draw_calendar(int month, int year, int selected_day);
#endif

View File

@@ -0,0 +1,7 @@
#ifndef DAY_VIEW_H
#define DAY_VIEW_H
void draw_day_view(int *day, int *month, int *year);
#endif

View File

@@ -0,0 +1,7 @@
#ifndef REPEAT_TUI_H
#define REPEAT_TUI_H
void open_repeat_tui();
#endif

View File

@@ -0,0 +1,292 @@
#include "add_event.h"
#include "repeat_tui.h"
#include <ncurses.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <limits.h>
#include <libgen.h>
#include <stdio.h>
#include <sqlite3.h>
#include <unistd.h>
// Create and initialize a new event
Event *create_event() {
Event *event = (Event *)malloc(sizeof(Event));
if (event) {
memset(event, 0, sizeof(Event));
strcpy(event->start_date, "01/01/2000");
strcpy(event->end_date, "01/01/2000");
event->start_hour = 9;
event->start_minute = 0;
event->end_hour = 10;
event->end_minute = 0;
event->repeat_option = 0;
}
return event;
}
// Function to open the SQLite database
sqlite3* open_database() {
char path[PATH_MAX];
char base_dir[PATH_MAX];
char db_path[PATH_MAX];
// Get the current working directory
if (getcwd(path, sizeof(path)) != NULL) {
printf("Current working directory: %s\n", path);
// Go up one directory level to the 'ncursescalander' directory
strncpy(base_dir, path, sizeof(base_dir));
dirname(base_dir);
printf("Base directory (one level up): %s\n", base_dir);
// Calculate required size
int required_size = snprintf(NULL, 0, "%s/databases/calendar_database.db", base_dir) + 1;
if (required_size > (int)sizeof(db_path)) { // Cast to int for comparison
fprintf(stderr, "Error: Path length exceeds buffer size.\n");
return NULL;
}
// Construct the final path to the database file
snprintf(db_path, sizeof(db_path), "%s/databases/calendar_database.db", base_dir);
printf("Final database path: %s\n", db_path);
sqlite3 *db;
if (sqlite3_open(db_path, &db)) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return NULL;
} else {
printf("Opened database successfully\n");
return db;
}
} else {
perror("getcwd() error");
return NULL;
}
}
// Function to save an event to the SQLite database
void save_event_to_db(sqlite3 *db, Event *event) {
// Set default values if necessary
if (strlen(event->title) == 0) {
strcpy(event->title, "Untitled");
}
if (strlen(event->calendar) == 0) {
strcpy(event->calendar, "");
}
if (strlen(event->notes) == 0) {
strcpy(event->notes, "");
}
// Prepare SQL statement
char *sql = "INSERT INTO events (title, all_day, start_date, end_date, start_time, end_time, repeat_option, calendar, notes) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);";
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, sql, -1, &stmt, 0) == SQLITE_OK) {
// Bind values to SQL statement
sqlite3_bind_text(stmt, 1, event->title, -1, SQLITE_STATIC);
sqlite3_bind_int(stmt, 2, event->all_day);
sqlite3_bind_text(stmt, 3, event->start_date, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 4, event->end_date, -1, SQLITE_STATIC);
// Format time as HH:MM
char start_time[6];
snprintf(start_time, sizeof(start_time), "%02d:%02d", event->start_hour, event->start_minute);
sqlite3_bind_text(stmt, 5, start_time, -1, SQLITE_STATIC);
char end_time[6];
snprintf(end_time, sizeof(end_time), "%02d:%02d", event->end_hour, event->end_minute);
sqlite3_bind_text(stmt, 6, end_time, -1, SQLITE_STATIC);
sqlite3_bind_int(stmt, 7, event->repeat_option);
sqlite3_bind_text(stmt, 8, event->calendar, -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 9, event->notes, -1, SQLITE_STATIC);
// Execute the SQL statement
if (sqlite3_step(stmt) != SQLITE_DONE) {
fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
} else {
printf("Event saved successfully.\n");
}
sqlite3_finalize(stmt);
} else {
fprintf(stderr, "SQL error: %s\n", sqlite3_errmsg(db));
}
}
// Function to display the Add Event TUI and handle user input
void open_add_event_tui(sqlite3 *db) {
Event *event = create_event();
int ch;
int cursor_pos = 0;
bool exit = false;
while (!exit) {
clear();
mvprintw(0, 0, "Add New Event");
// Title input
mvprintw(2, 0, "Title: ");
if (cursor_pos == 0) attron(A_REVERSE);
mvprintw(2, 7, event->title);
if (cursor_pos == 0) attroff(A_REVERSE);
// All-day toggle
mvprintw(4, 0, "All Day: ");
if (cursor_pos == 1) attron(A_REVERSE);
mvprintw(4, 9, event->all_day ? "[X]" : "[ ]");
if (cursor_pos == 1) attroff(A_REVERSE);
// Start date input
mvprintw(6, 0, "Start Date: ");
if (cursor_pos == 2) attron(A_REVERSE);
mvprintw(6, 12, event->start_date);
if (cursor_pos == 2) attroff(A_REVERSE);
// End date input
mvprintw(8, 0, "End Date: ");
if (cursor_pos == 3) attron(A_REVERSE);
mvprintw(8, 10, event->end_date);
if (cursor_pos == 3) attroff(A_REVERSE);
// Start time input
mvprintw(10, 0, "Start Time: ");
if (cursor_pos == 4) attron(A_REVERSE);
mvprintw(10, 12, "%02d:%02d", event->start_hour, event->start_minute);
if (cursor_pos == 4) attroff(A_REVERSE);
// End time input
mvprintw(12, 0, "End Time: ");
if (cursor_pos == 5) attron(A_REVERSE);
mvprintw(12, 10, "%02d:%02d", event->end_hour, event->end_minute);
if (cursor_pos == 5) attroff(A_REVERSE);
// Repeat options
mvprintw(14, 0, "Repeat: ");
if (cursor_pos == 6) attron(A_REVERSE);
mvprintw(14, 8, "Choose..."); // Display the repeat choice interactively
if (cursor_pos == 6) attroff(A_REVERSE);
// Calendar name input
mvprintw(16, 0, "Calendar: ");
if (cursor_pos == 7) attron(A_REVERSE);
mvprintw(16, 10, event->calendar);
if (cursor_pos == 7) attroff(A_REVERSE);
// Notes input
mvprintw(18, 0, "Notes: ");
if (cursor_pos == 8) attron(A_REVERSE);
mvprintw(19, 0, event->notes);
if (cursor_pos == 8) attroff(A_REVERSE);
// Instructions
mvprintw(21, 0, "Esc: Cancel Ctrl+S: Save");
refresh();
ch = getch();
switch (ch) {
case 27: // ESC to cancel
exit = true;
break;
case 19: // Ctrl+S to save (^S)
save_event_to_db(db, event);
exit = true; // Return to calendar view after saving
break;
case KEY_DOWN: // Navigate down
cursor_pos = (cursor_pos + 1) % 9;
break;
case KEY_UP: // Navigate up
cursor_pos = (cursor_pos - 1 + 9) % 9;
break;
case KEY_LEFT:
case 'j': // Decrease minute
if (cursor_pos == 4) {
event->start_minute = (event->start_minute > 0) ? event->start_minute - 1 : 59;
} else if (cursor_pos == 5) {
event->end_minute = (event->end_minute > 0) ? event->end_minute - 1 : 59;
}
break;
case KEY_RIGHT:
case 'k': // Increase minute
if (cursor_pos == 4) {
event->start_minute = (event->start_minute < 59) ? event->start_minute + 1 : 0;
} else if (cursor_pos == 5) {
event->end_minute = (event->end_minute < 59) ? event->end_minute + 1 : 0;
}
break;
case KEY_SLEFT:
case 'h': // Decrease hour (Shift+Left or 'h')
if (cursor_pos == 4) {
event->start_hour = (event->start_hour > 0) ? event->start_hour - 1 : 23;
} else if (cursor_pos == 5) {
event->end_hour = (event->end_hour > 0) ? event->end_hour - 1 : 23;
}
break;
case KEY_SRIGHT:
case 'l': // Increase hour (Shift+Right or 'l')
if (cursor_pos == 4) {
event->start_hour = (event->start_hour < 23) ? event->start_hour + 1 : 0;
} else if (cursor_pos == 5) {
event->end_hour = (event->end_hour < 23) ? event->end_hour + 1 : 0;
}
break;
case ' ':
case '\n':
if (cursor_pos == 1) {
event->all_day = !event->all_day;
} else if (cursor_pos == 6) {
open_repeat_tui(); // Placeholder for opening the repeat TUI
}
break;
default:
if (cursor_pos == 0 && ch != KEY_DOWN && ch != KEY_UP) {
int len = strlen(event->title);
if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) {
event->title[len - 1] = '\0';
} else if (isprint(ch) && len < MAX_TITLE_LEN - 1) {
event->title[len] = ch;
event->title[len + 1] = '\0';
}
} else if (cursor_pos == 2 && ch != KEY_DOWN && ch != KEY_UP) {
int len = strlen(event->start_date);
if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) {
event->start_date[len - 1] = '\0';
} else if (isprint(ch) && len < MAX_DATE_LEN - 1) {
event->start_date[len] = ch;
event->start_date[len + 1] = '\0';
}
} else if (cursor_pos == 3 && ch != KEY_DOWN && ch != KEY_UP) {
int len = strlen(event->end_date);
if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) {
event->end_date[len - 1] = '\0';
} else if (isprint(ch) && len < MAX_DATE_LEN - 1) {
event->end_date[len] = ch;
event->end_date[len + 1] = '\0';
}
} else if (cursor_pos == 7 && ch != KEY_DOWN && ch != KEY_UP) {
int len = strlen(event->calendar);
if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) {
event->calendar[len - 1] = '\0';
} else if (isprint(ch) && len < MAX_CALENDAR_LEN - 1) {
event->calendar[len] = ch;
event->calendar[len + 1] = '\0';
}
} else if (cursor_pos == 8 && ch != KEY_DOWN && ch != KEY_UP) {
int len = strlen(event->notes);
if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) {
event->notes[len - 1] = '\0';
} else if (isprint(ch) && len < MAX_NOTES_LEN - 1) {
event->notes[len] = ch;
event->notes[len + 1] = '\0';
}
}
break;
}
}
free(event); // Free the allocated memory
}

View File

@@ -0,0 +1,225 @@
#include "add_event.h"
#include "repeat_tui.h"
#include <ncurses.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX_TITLE_LEN 50
#define MAX_CALENDAR_LEN 30
#define MAX_NOTES_LEN 256
#define MAX_DATE_LEN 50
typedef struct {
char title[MAX_TITLE_LEN];
bool all_day;
char start_date[MAX_DATE_LEN];
char end_date[MAX_DATE_LEN];
int start_hour, start_minute;
int end_hour, end_minute;
int repeat_option;
char calendar[MAX_CALENDAR_LEN];
char notes[MAX_NOTES_LEN];
} Event;
Event *create_event() {
Event *event = (Event *)malloc(sizeof(Event));
if (event) {
memset(event, 0, sizeof(Event));
strcpy(event->start_date, "01/01/2000");
strcpy(event->end_date, "01/01/2000");
event->start_hour = 9;
event->start_minute = 0;
event->end_hour = 10;
event->end_minute = 0;
event->repeat_option = 0;
}
return event;
}
void save_event(Event *event) {
FILE *file = fopen("events.txt", "a");
if (file) {
fprintf(file, "Title: %s\nAll Day: %d\nStart Date: %s\nEnd Date: %s\nStart: %02d:%02d\nEnd: %02d:%02d\nRepeat: %d\nCalendar: %s\nNotes: %s\n\n",
event->title, event->all_day, event->start_date, event->end_date, event->start_hour, event->start_minute,
event->end_hour, event->end_minute, event->repeat_option, event->calendar, event->notes);
fclose(file);
} else {
mvprintw(23, 0, "Error saving event!"); // Error message
refresh();
getch(); // Pause to let the user see the error
}
}
void open_add_event_tui() {
Event *event = create_event();
int ch;
int cursor_pos = 0;
bool exit = false;
while (!exit) {
clear();
mvprintw(0, 0, "Add New Event");
// Title input
mvprintw(2, 0, "Title: ");
if (cursor_pos == 0) attron(A_REVERSE);
mvprintw(2, 7, event->title);
if (cursor_pos == 0) attroff(A_REVERSE);
// All-day toggle
mvprintw(4, 0, "All Day: ");
if (cursor_pos == 1) attron(A_REVERSE);
mvprintw(4, 9, event->all_day ? "[X]" : "[ ]");
if (cursor_pos == 1) attroff(A_REVERSE);
// Start date input
mvprintw(6, 0, "Start Date: ");
if (cursor_pos == 2) attron(A_REVERSE);
mvprintw(6, 12, event->start_date);
if (cursor_pos == 2) attroff(A_REVERSE);
// End date input
mvprintw(8, 0, "End Date: ");
if (cursor_pos == 3) attron(A_REVERSE);
mvprintw(8, 10, event->end_date);
if (cursor_pos == 3) attroff(A_REVERSE);
// Start time input
mvprintw(10, 0, "Start Time: ");
if (cursor_pos == 4) attron(A_REVERSE);
mvprintw(10, 12, "%02d:%02d", event->start_hour, event->start_minute);
if (cursor_pos == 4) attroff(A_REVERSE);
// End time input
mvprintw(12, 0, "End Time: ");
if (cursor_pos == 5) attron(A_REVERSE);
mvprintw(12, 10, "%02d:%02d", event->end_hour, event->end_minute);
if (cursor_pos == 5) attroff(A_REVERSE);
// Repeat options
mvprintw(14, 0, "Repeat: ");
if (cursor_pos == 6) attron(A_REVERSE);
mvprintw(14, 8, "Choose..."); // Display the repeat choice interactively
if (cursor_pos == 6) attroff(A_REVERSE);
// Calendar name input
mvprintw(16, 0, "Calendar: ");
if (cursor_pos == 7) attron(A_REVERSE);
mvprintw(16, 10, event->calendar);
if (cursor_pos == 7) attroff(A_REVERSE);
// Notes input
mvprintw(18, 0, "Notes: ");
if (cursor_pos == 8) attron(A_REVERSE);
mvprintw(19, 0, event->notes);
if (cursor_pos == 8) attroff(A_REVERSE);
// Instructions
mvprintw(21, 0, "Esc: Cancel Ctrl+S: Save");
refresh();
ch = getch();
switch (ch) {
case 27: // ESC to cancel
exit = true;
break;
case 19: // Ctrl+S to save (^S)
save_event(event);
exit = true; // Return to calendar view after saving
break;
case KEY_DOWN: // Navigate down
cursor_pos = (cursor_pos + 1) % 9;
break;
case KEY_UP: // Navigate up
cursor_pos = (cursor_pos - 1 + 9) % 9;
break;
case KEY_LEFT:
case 'j': // Decrease minute
if (cursor_pos == 4) {
event->start_minute = (event->start_minute > 0) ? event->start_minute - 1 : 59;
} else if (cursor_pos == 5) {
event->end_minute = (event->end_minute > 0) ? event->end_minute - 1 : 59;
}
break;
case KEY_RIGHT:
case 'k': // Increase minute
if (cursor_pos == 4) {
event->start_minute = (event->start_minute < 59) ? event->start_minute + 1 : 0;
} else if (cursor_pos == 5) {
event->end_minute = (event->end_minute < 59) ? event->end_minute + 1 : 0;
}
break;
case KEY_SLEFT:
case 'h': // Decrease hour (Shift+Left or 'h')
if (cursor_pos == 4) {
event->start_hour = (event->start_hour > 0) ? event->start_hour - 1 : 23;
} else if (cursor_pos == 5) {
event->end_hour = (event->end_hour > 0) ? event->end_hour - 1 : 23;
}
break;
case KEY_SRIGHT:
case 'l': // Increase hour (Shift+Right or 'l')
if (cursor_pos == 4) {
event->start_hour = (event->start_hour < 23) ? event->start_hour + 1 : 0;
} else if (cursor_pos == 5) {
event->end_hour = (event->end_hour < 23) ? event->end_hour + 1 : 0;
}
break;
case ' ':
case '\n':
if (cursor_pos == 1) {
event->all_day = !event->all_day;
} else if (cursor_pos == 6) {
open_repeat_tui(); // Placeholder for opening the repeat TUI
}
break;
default:
if (cursor_pos == 0 && ch != KEY_DOWN && ch != KEY_UP) {
int len = strlen(event->title);
if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) {
event->title[len - 1] = '\0';
} else if (isprint(ch) && len < MAX_TITLE_LEN - 1) {
event->title[len] = ch;
event->title[len + 1] = '\0';
}
} else if (cursor_pos == 2 && ch != KEY_DOWN && ch != KEY_UP) {
int len = strlen(event->start_date);
if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) {
event->start_date[len - 1] = '\0';
} else if (isprint(ch) && len < MAX_DATE_LEN - 1) {
event->start_date[len] = ch;
event->start_date[len + 1] = '\0';
}
} else if (cursor_pos == 3 && ch != KEY_DOWN && ch != KEY_UP) {
int len = strlen(event->end_date);
if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) {
event->end_date[len - 1] = '\0';
} else if (isprint(ch) && len < MAX_DATE_LEN - 1) {
event->end_date[len] = ch;
event->end_date[len + 1] = '\0';
}
} else if (cursor_pos == 7 && ch != KEY_DOWN && ch != KEY_UP) {
int len = strlen(event->calendar);
if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) {
event->calendar[len - 1] = '\0';
} else if (isprint(ch) && len < MAX_CALENDAR_LEN - 1) {
event->calendar[len] = ch;
event->calendar[len + 1] = '\0';
}
} else if (cursor_pos == 8 && ch != KEY_DOWN && ch != KEY_UP) {
int len = strlen(event->notes);
if ((ch == KEY_BACKSPACE || ch == 127) && len > 0) {
event->notes[len - 1] = '\0';
} else if (isprint(ch) && len < MAX_NOTES_LEN - 1) {
event->notes[len] = ch;
event->notes[len + 1] = '\0';
}
}
break;
}
}
free(event); // Free the allocated memory
}

View File

@@ -0,0 +1,56 @@
#include "calendar.h"
#include <ncurses.h>
// Function to determine if a year is a leap year
int is_leap_year(int year) {
if (year % 4 == 0) {
if (year % 100 == 0) {
if (year % 400 == 0)
return 1;
else
return 0;
} else
return 1;
} else
return 0;
}
// Function to get the number of days in a given month and year
int days_in_month(int month, int year) {
switch (month) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
return 31;
case 4: case 6: case 9: case 11:
return 30;
case 2:
if (is_leap_year(year))
return 29;
else
return 28;
default:
return 30; // Fallback, though we shouldn't hit this
}
}
void draw_calendar(int month, int year, int selected_day) {
int days = days_in_month(month, year);
// Adjust selected_day if it exceeds the number of days in the month
if (selected_day > days) {
selected_day = days;
}
mvprintw(1, 0, "Month: %d, Year: %d", month, year);
mvprintw(2, 0, "Su Mo Tu We Th Fr Sa");
// Placeholder for calendar drawing
for (int i = 1; i <= days; i++) {
if (i == selected_day) {
attron(A_REVERSE); // Highlight the selected day
}
mvprintw(3 + (i / 7), (i % 7) * 3, "%2d", i);
if (i == selected_day) {
attroff(A_REVERSE);
}
}
}

View File

@@ -0,0 +1,127 @@
#include "day_view.h"
#include <ncurses.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#define MAX_TITLE_LEN 50
typedef struct {
char title[MAX_TITLE_LEN];
int start_hour;
int start_minute;
int end_hour;
int end_minute;
int event_day;
int event_month;
int event_year;
} DisplayEvent;
void load_events(DisplayEvent *events, int *count, int day, int month, int year) {
FILE *file = fopen("events.txt", "r");
if (file) {
char line[256];
int current_day, current_month, current_year;
while (fgets(line, sizeof(line), file)) {
if (sscanf(line, "Date: %d-%d-%d", &current_day, &current_month, &current_year) == 3) {
if (current_day == day && current_month == month && current_year == year) {
fgets(line, sizeof(line), file);
sscanf(line, "Start: %02d:%02d", &events[*count].start_hour, &events[*count].start_minute);
fgets(line, sizeof(line), file);
sscanf(line, "End: %02d:%02d", &events[*count].end_hour, &events[*count].end_minute);
fgets(line, sizeof(line), file);
sscanf(line, "Title: %49[^\n]", events[*count].title);
events[*count].event_day = current_day;
events[*count].event_month = current_month;
events[*count].event_year = current_year;
(*count)++;
}
}
}
fclose(file);
}
}
void draw_day_view(int *day, int *month, int *year) {
time_t now;
struct tm *local;
int ch;
bool redraw = true;
DisplayEvent events[10];
int event_count = 0;
load_events(events, &event_count, *day, *month, *year);
while (true) {
if (redraw) {
clear();
mvprintw(0, 0, "Day View");
mvprintw(1, 0, "Date: %02d-%02d-%04d", *day, *month, *year);
// Draw the hours of the day
for (int i = 0; i < 24; i++) {
mvprintw(i + 3, 0, "%02d:00 |", i);
mvhline(i + 3, 8, ' ', COLS - 8);
}
// Display events
for (int i = 0; i < event_count; i++) {
mvprintw(events[i].start_hour + 3, 10, "%s", events[i].title);
mvhline(events[i].start_hour + 3, 10 + strlen(events[i].title), '-', COLS - 20);
}
now = time(NULL);
local = localtime(&now);
if (local->tm_mday == *day && (local->tm_mon + 1) == *month && (local->tm_year + 1900) == *year) {
int current_hour = local->tm_hour;
int current_minute = local->tm_min;
attron(COLOR_PAIR(1)); // Red color
mvhline(current_hour + 3, 8, '-', COLS - 8);
mvprintw(current_hour + 3, 0, "%02d:%02d |", current_hour, current_minute);
attroff(COLOR_PAIR(1));
}
refresh();
redraw = false;
}
nodelay(stdscr, TRUE); // Make getch non-blocking
ch = getch();
if (ch == 'q') break; // Exit to Calendar View
if (ch == KEY_LEFT || ch == 'j') {
if (*day > 1) {
(*day)--;
} else {
if (*month > 1) {
(*month)--;
} else {
*month = 12;
(*year)--;
}
*day = 31; // Simplified for demo purposes
}
redraw = true;
} else if (ch == KEY_RIGHT || ch == 'k') {
if (*day < 31) { // Simplified for demo purposes
(*day)++;
} else {
*day = 1;
if (*month < 12) {
(*month)++;
} else {
*month = 1;
(*year)++;
}
}
redraw = true;
}
napms(1000);
}
nodelay(stdscr, FALSE);
}

106
ncursescalander/src/main.c Normal file
View File

@@ -0,0 +1,106 @@
#include <ncurses.h>
#include <string.h>
#include <time.h>
#include "calendar.h"
#include "day_view.h"
#include "add_event.h"
int main() {
int ch, month, year, day = 1;
time_t now;
struct tm *local;
// Open the SQLite database
sqlite3 *db = open_database();
if (db == NULL) {
return 1; // Exit if the database can't be opened
}
// Initialize ncurses
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
start_color();
init_pair(1, COLOR_RED, COLOR_BLACK); // Red color pair for the current time
// Get current date
now = time(NULL);
local = localtime(&now);
month = local->tm_mon + 1;
year = local->tm_year + 1900;
day = local->tm_mday;
// Main loop
while ((ch = getch()) != 'q') {
int days_in_current_month = days_in_month(month, year);
bool redraw = false;
switch (ch) {
case KEY_LEFT:
case 'j':
if (day > 1) {
day--;
redraw = true;
}
break;
case KEY_RIGHT:
case 'k':
if (day < days_in_current_month) {
day++;
redraw = true;
}
break;
case 'a': // 'a' for "Add Event"
open_add_event_tui(db); // Pass the database connection here
redraw = true;
break;
case '\n': // Enter key to open the day view
draw_day_view(&day, &month, &year);
redraw = true;
break;
case 'h': // 'h' for previous month
case KEY_SLEFT: // Left Shift for previous month
if (month > 1) {
month--;
} else {
month = 12;
year--;
}
// Adjust the day if it exceeds the number of days in the new month
if (day > days_in_month(month, year)) {
day = days_in_month(month, year);
}
redraw = true;
break;
case 'l': // 'l' for next month
case KEY_SRIGHT: // Right Shift for next month
if (month < 12) {
month++;
} else {
month = 1;
year++;
}
// Adjust the day if it exceeds the number of days in the new month
if (day > days_in_month(month, year)) {
day = days_in_month(month, year);
}
redraw = true;
break;
}
if (redraw) {
clear();
mvprintw(0, 0, "Calendar View - Press 'a' to Add Event");
draw_calendar(month, year, day);
refresh();
}
}
// Close the SQLite database connection
sqlite3_close(db);
// End ncurses mode
endwin();
return 0;
}

View File

@@ -0,0 +1,48 @@
#include <ncurses.h>
#include "repeat_tui.h"
void open_repeat_tui() {
int ch;
int cursor_pos = 0;
while (true) {
clear();
mvprintw(0, 0, "Repeat Options");
mvprintw(2, 0, "1. Never");
if (cursor_pos == 0) attron(A_REVERSE);
mvprintw(2, 10, "Select");
if (cursor_pos == 0) attroff(A_REVERSE);
mvprintw(4, 0, "2. Every Day");
if (cursor_pos == 1) attron(A_REVERSE);
mvprintw(4, 10, "Select");
if (cursor_pos == 1) attroff(A_REVERSE);
mvprintw(6, 0, "3. Every Week");
if (cursor_pos == 2) attron(A_REVERSE);
mvprintw(6, 10, "Select");
if (cursor_pos == 2) attroff(A_REVERSE);
mvprintw(8, 0, "4. Every Other Day");
if (cursor_pos == 3) attron(A_REVERSE);
mvprintw(8, 18, "Select");
if (cursor_pos == 3) attroff(A_REVERSE);
mvprintw(10, 0, "Press 'q' to return");
refresh();
ch = getch();
if (ch == 'q') break; // Return to the add event TUI
if (ch == KEY_DOWN || ch == 'j') {
cursor_pos = (cursor_pos + 1) % 4;
} else if (ch == KEY_UP || ch == 'k') {
cursor_pos = (cursor_pos - 1 + 4) % 4;
} else if (ch == '\n') {
// Here, you would handle selection logic
break; // Return after selection for now
}
}
}