2016-04-18 04:25:36 -04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <limits.h>
|
2020-05-04 18:14:41 -04:00
|
|
|
//#include "fixed.h"
|
2016-04-18 04:25:36 -04:00
|
|
|
#include "calc.h"
|
|
|
|
|
2020-05-04 18:14:41 -04:00
|
|
|
static inline int8_t tokenCount() {
|
|
|
|
return sizeof(tokens) / sizeof(tokens[0]);
|
2016-04-18 04:25:36 -04:00
|
|
|
}
|
|
|
|
|
2020-05-04 18:14:41 -04:00
|
|
|
static inline char* getToken(int8_t n) {
|
|
|
|
return tokens[n % tokenCount()];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Currently selected button, starts on '('
|
|
|
|
static int8_t selected_token = 1;
|
2016-04-18 04:25:36 -04:00
|
|
|
|
2020-05-04 18:14:41 -04:00
|
|
|
// Update the current code text with the contents of `mytext`,
|
|
|
|
// and add the current selected_token to the end
|
2016-04-18 04:25:36 -04:00
|
|
|
static void updateText()
|
|
|
|
{
|
|
|
|
strcpy(temptext, mytext);
|
2020-05-03 17:00:45 -04:00
|
|
|
|
2020-05-04 18:14:41 -04:00
|
|
|
const char *token = getToken(selected_token);
|
|
|
|
if(token[0] == ' ') {
|
2016-04-18 04:25:36 -04:00
|
|
|
strcat(temptext, "_");
|
2020-05-04 18:14:41 -04:00
|
|
|
} else if(token[0] == '\n') {
|
|
|
|
strcat(temptext, "\\n");
|
2016-04-18 04:25:36 -04:00
|
|
|
} else {
|
2020-05-04 18:14:41 -04:00
|
|
|
strcat(temptext, token);
|
2016-04-18 04:25:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
text_layer_set_text(s_input_text_layer, temptext);
|
|
|
|
}
|
|
|
|
|
2020-05-03 17:00:45 -04:00
|
|
|
// Button handler
|
2016-04-18 04:25:36 -04:00
|
|
|
static void up_down_handler(ClickRecognizerRef recognizer, void *context){
|
2020-05-04 18:14:41 -04:00
|
|
|
// Change current token
|
|
|
|
if(click_recognizer_get_button_id(recognizer) == BUTTON_ID_DOWN)
|
|
|
|
selected_token++;
|
|
|
|
else
|
|
|
|
selected_token--;
|
2016-04-18 04:25:36 -04:00
|
|
|
|
2020-05-04 18:14:41 -04:00
|
|
|
// If selected token is outside of range, wrap around
|
|
|
|
if(selected_token < 0)
|
|
|
|
selected_token = tokenCount() - 1;
|
|
|
|
else if(selected_token >= tokenCount())
|
|
|
|
selected_token = 0;
|
|
|
|
|
|
|
|
updateText();
|
2016-04-18 04:25:36 -04:00
|
|
|
}
|
|
|
|
|
2020-05-04 18:14:41 -04:00
|
|
|
// Backspace if possible, otherwise close the app
|
2020-05-03 21:24:36 -04:00
|
|
|
static void back_handler(ClickRecognizerRef recognizer, void *context) {
|
|
|
|
if(mytext[0] == '\0') {
|
|
|
|
window_stack_remove(window_stack_get_top_window(), true);
|
|
|
|
} else {
|
2020-05-04 18:14:41 -04:00
|
|
|
int8_t i = 0;
|
2020-05-03 21:24:36 -04:00
|
|
|
while(mytext[++i] != '\0') { ; }
|
|
|
|
mytext[i-1] = '\0';
|
|
|
|
updateText();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-18 04:25:36 -04:00
|
|
|
// Adds the current string to the main string
|
|
|
|
static void enter(){
|
|
|
|
strcat(mytext, getToken(selected_token));
|
|
|
|
selected_token = 0;
|
|
|
|
updateText();
|
|
|
|
}
|
|
|
|
|
2020-05-04 18:14:41 -04:00
|
|
|
// Calculate result, display it and reset
|
2016-04-18 04:25:36 -04:00
|
|
|
static void calculate(){
|
2020-05-03 17:00:45 -04:00
|
|
|
Object obj = parseEval(mytext, &env);
|
2020-05-04 10:03:35 -04:00
|
|
|
char temp[MAX_LENGTH-2] = "";
|
2020-05-04 18:14:41 -04:00
|
|
|
|
2020-05-04 10:03:35 -04:00
|
|
|
stringObj(temp, &obj);
|
|
|
|
snprintf(resulttext, MAX_LENGTH, "R:%s", temp);
|
2020-05-03 17:00:45 -04:00
|
|
|
selected_token = 0;
|
2020-05-03 21:24:36 -04:00
|
|
|
text_layer_set_text(s_result_text_layer, resulttext);
|
2016-04-18 04:25:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Button press handler
|
|
|
|
static void select_handler(ClickRecognizerRef recognizer, void *context){
|
|
|
|
if(selected_token == sizeof(tokens) / sizeof(tokens[0]) - 1)
|
|
|
|
calculate();
|
|
|
|
else
|
|
|
|
enter();
|
|
|
|
}
|
|
|
|
|
2020-05-05 19:21:54 -04:00
|
|
|
static void long_select_handler(ClickRecognizerRef recognizer, void *context){
|
|
|
|
persist_write_string(current_code, temptext);
|
|
|
|
window_stack_pop(true);
|
|
|
|
}
|
|
|
|
|
2016-04-18 04:25:36 -04:00
|
|
|
static void click_config_provider(void *context) {
|
|
|
|
// Register click handlers
|
|
|
|
window_single_repeating_click_subscribe(BUTTON_ID_UP, 100, up_down_handler);
|
|
|
|
window_single_repeating_click_subscribe(BUTTON_ID_DOWN, 100, up_down_handler);
|
|
|
|
window_single_click_subscribe(BUTTON_ID_SELECT, select_handler);
|
2020-05-05 19:21:54 -04:00
|
|
|
window_long_click_subscribe(BUTTON_ID_SELECT, 500, long_select_handler, NULL);
|
2020-05-03 21:24:36 -04:00
|
|
|
window_single_click_subscribe(BUTTON_ID_BACK, back_handler);
|
2016-04-18 04:25:36 -04:00
|
|
|
}
|
|
|
|
|
2020-05-05 19:21:54 -04:00
|
|
|
static uint16_t get_num_rows_callback(MenuLayer *menu_layer,
|
|
|
|
uint16_t section_index, void *context) {
|
|
|
|
return NUM_ROWS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void draw_row_callback(GContext *ctx, const Layer *cell_layer,
|
|
|
|
MenuIndex *cell_index, void *context) {
|
|
|
|
static char s_buff[16];
|
|
|
|
snprintf(s_buff, sizeof(s_buff), "Script %d", 1 + (int)cell_index->row);
|
|
|
|
|
|
|
|
// Draw this row's index
|
|
|
|
menu_cell_basic_draw(ctx, cell_layer, s_buff, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int16_t get_cell_height_callback(struct MenuLayer *menu_layer,
|
|
|
|
MenuIndex *cell_index, void *context) {
|
|
|
|
const int16_t cell_height = 44;
|
|
|
|
return cell_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
void code_window_push() {
|
|
|
|
if(!s_code_window) {
|
|
|
|
s_code_window = window_create();
|
|
|
|
WindowHandlers wh = {
|
|
|
|
.load = code_window_load,
|
|
|
|
.unload = code_window_unload };
|
|
|
|
window_set_window_handlers(s_code_window, wh);
|
|
|
|
}
|
|
|
|
window_stack_push(s_code_window, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void select_callback(struct MenuLayer *menu_layer,
|
|
|
|
MenuIndex *cell_index, void *context)
|
|
|
|
{
|
|
|
|
current_code = cell_index->row;
|
|
|
|
code_window_push();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void menu_load(Window *window)
|
|
|
|
{
|
|
|
|
Layer *window_layer = window_get_root_layer(window);
|
|
|
|
GRect bounds = layer_get_bounds(window_layer);
|
|
|
|
|
|
|
|
s_menu_layer = menu_layer_create(bounds);
|
|
|
|
menu_layer_set_click_config_onto_window(s_menu_layer, window);
|
|
|
|
#if defined(PBL_COLOR)
|
|
|
|
menu_layer_set_normal_colors(s_menu_layer, GColorBlack, GColorWhite);
|
|
|
|
menu_layer_set_highlight_colors(s_menu_layer, GColorDukeBlue, GColorWhite);
|
|
|
|
#endif
|
|
|
|
menu_layer_set_callbacks(s_menu_layer, NULL, (MenuLayerCallbacks) {
|
|
|
|
.get_num_rows = get_num_rows_callback,
|
|
|
|
.draw_row = draw_row_callback,
|
|
|
|
.get_cell_height = get_cell_height_callback,
|
|
|
|
.select_click = select_callback,
|
|
|
|
});
|
|
|
|
layer_add_child(window_layer, menu_layer_get_layer(s_menu_layer));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void menu_unload(Window *window)
|
|
|
|
{
|
|
|
|
menu_layer_destroy(s_menu_layer);
|
|
|
|
}
|
|
|
|
|
|
|
|
void code_window_load(Window *window)
|
|
|
|
{
|
|
|
|
Layer *window_layer = window_get_root_layer(window);
|
|
|
|
GRect bounds = layer_get_bounds(window_layer);
|
2020-05-04 18:14:41 -04:00
|
|
|
|
2016-04-18 04:25:36 -04:00
|
|
|
// Register click config provider
|
2020-05-05 19:21:54 -04:00
|
|
|
window_set_click_config_provider(s_code_window, click_config_provider);
|
2016-04-18 04:25:36 -04:00
|
|
|
|
|
|
|
// Input text layer setup
|
2020-05-05 19:21:54 -04:00
|
|
|
// GRect text_bounds = GRect(6, 6, 132, 127);
|
|
|
|
s_input_text_layer = text_layer_create(bounds);
|
2016-04-18 04:25:36 -04:00
|
|
|
text_layer_set_text(s_input_text_layer, getToken(1));
|
2020-05-03 21:24:36 -04:00
|
|
|
text_layer_set_font(s_input_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD));
|
2020-05-05 19:21:54 -04:00
|
|
|
layer_add_child(window_get_root_layer(s_code_window), text_layer_get_layer(s_input_text_layer));
|
2016-04-18 04:25:36 -04:00
|
|
|
|
2020-05-03 21:24:36 -04:00
|
|
|
// Result text layer setup
|
|
|
|
GRect result_bounds = GRect(6, 128, 132, 132);
|
|
|
|
s_result_text_layer = text_layer_create(result_bounds);
|
|
|
|
text_layer_set_text(s_result_text_layer, "R: ");
|
|
|
|
text_layer_set_font(s_result_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_28_BOLD));
|
|
|
|
text_layer_set_text_alignment(s_result_text_layer, GTextAlignmentRight);
|
2020-05-05 19:21:54 -04:00
|
|
|
layer_add_child(window_get_root_layer(s_code_window), text_layer_get_layer(s_result_text_layer));
|
2020-05-03 21:24:36 -04:00
|
|
|
|
2016-04-18 04:25:36 -04:00
|
|
|
// Push the window, setting the window animation to 'true'
|
2020-05-05 19:21:54 -04:00
|
|
|
window_stack_push(s_code_window, true);
|
2020-05-04 18:14:41 -04:00
|
|
|
|
|
|
|
// If possible, load the previous code text
|
2020-05-05 19:21:54 -04:00
|
|
|
if(persist_exists(current_code)) {
|
|
|
|
persist_read_string(current_code, mytext, SMAX_LENGTH);
|
2020-05-04 18:14:41 -04:00
|
|
|
updateText();
|
|
|
|
}
|
2016-04-18 04:25:36 -04:00
|
|
|
}
|
|
|
|
|
2020-05-05 19:21:54 -04:00
|
|
|
void code_window_unload(Window *window)
|
|
|
|
{
|
2020-05-04 18:14:41 -04:00
|
|
|
// Save the current code text
|
2020-05-05 19:21:54 -04:00
|
|
|
persist_write_string(current_code, temptext);
|
2016-04-18 04:25:36 -04:00
|
|
|
|
2020-05-05 19:21:54 -04:00
|
|
|
text_layer_destroy(s_result_text_layer);
|
|
|
|
text_layer_destroy(s_input_text_layer);
|
|
|
|
|
|
|
|
window_destroy(window);
|
|
|
|
s_code_window = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void init(void) {
|
|
|
|
env = defaultEnv();
|
|
|
|
s_menu_window = window_create();
|
|
|
|
window_set_window_handlers(s_menu_window, (WindowHandlers) {
|
|
|
|
.load = menu_load,
|
|
|
|
.unload = menu_unload
|
|
|
|
});
|
|
|
|
window_stack_push(s_menu_window, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void deinit(void) {
|
2020-05-04 18:14:41 -04:00
|
|
|
deleteEnv(&env);
|
|
|
|
text_layer_destroy(s_input_text_layer);
|
2020-05-05 19:21:54 -04:00
|
|
|
window_destroy(s_menu_window);
|
2016-04-18 04:25:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int main(void) {
|
|
|
|
init();
|
|
|
|
app_event_loop();
|
|
|
|
deinit();
|
|
|
|
}
|