Index: exposurses.c ================================================================== --- exposurses.c +++ exposurses.c @@ -30,11 +30,10 @@ "12", "13", "14", "15", "16", - NULL }; char *iso_array[] = { "50", "100", @@ -41,14 +40,14 @@ "200", "400", "800", "1600", "3200", - NULL }; char *shutter_array[] = { + "OVER", "1/1000", "1/500", "1/250", "1/125", "1/60", @@ -56,23 +55,24 @@ "1/15", "1/8", "1/4", "1/2", "1", - NULL + "UNDER", }; char *aperture_array[] = { + "UNDER", "f/1.4", "f/2", "f/2.8", "f/4", "f/5.6", "f/8", "f/11", "f/16", - NULL + "OVER", }; ITEM **exposure_items; ITEM **iso_items; ITEM **shutter_items; @@ -85,17 +85,19 @@ WINDOW *iso_win; WINDOW *shutter_win; WINDOW *aperture_win; void selection(char *name); -void add_menu(char **array, ITEM **items, MENU *men, WINDOW *win, int n, int xpos, char *title); void remove_menu(ITEM **items, MENU *men, int n); void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color); +MENU *add_menu(ITEM **items); +WINDOW *add_window(int xpos, char *title); +ITEM **add_item(char **array, int n); int exposure(int iso); double shutter(int exposure, double aperture); double aperture(int exposure, double shutter); -int nearest_match(double x, int menu); +int nearest_match(double x, int menu, int n_array); double fraction_to_double(char *fraction); /* No one will ever need more than 9 bytes! */ char exposure_sel[9] = ""; char iso_sel[9] = ""; char shutter_sel[9] = ""; @@ -126,15 +128,40 @@ /* Can't really avoid finding array sizes here */ n_exposure = ARRAY_SIZE(exposure_array); n_iso = ARRAY_SIZE(iso_array); n_shutter = ARRAY_SIZE(shutter_array); n_aperture = ARRAY_SIZE(aperture_array); - add_menu(exposure_array, exposure_items, exposure_menu, exposure_win, n_exposure, 4, "EV"); - add_menu(iso_array, iso_items, iso_menu, iso_win, n_iso, 45, "ISO"); - add_menu(shutter_array, shutter_items, shutter_menu, shutter_win, n_shutter, 86, "Shutter"); - add_menu(aperture_array, aperture_items, aperture_menu, aperture_win, n_aperture, 127, "Aperture"); - + /* http://stackoverflow.com/a/2620158/208793 */ + exposure_items = add_item(exposure_array, n_exposure); + iso_items = add_item(iso_array, n_iso); + aperture_items = add_item(aperture_array, n_aperture); + shutter_items = add_item(shutter_array, n_shutter); + exposure_menu = add_menu(exposure_items); + iso_menu = add_menu(iso_items); + shutter_menu = add_menu(shutter_items); + aperture_menu = add_menu(aperture_items); + exposure_win = add_window(4, "EV"); + iso_win = add_window(45, "ISO"); + shutter_win = add_window(86, "Shutter"); + aperture_win = add_window(127, "Aperture"); + /* Don't know how to avoid the repition below */ + set_menu_win(exposure_menu, exposure_win); + set_menu_win(iso_menu, iso_win); + set_menu_win(shutter_menu, shutter_win); + set_menu_win(aperture_menu, aperture_win); + set_menu_sub(exposure_menu, derwin(exposure_win, 6, 38, 3, 1)); + set_menu_sub(iso_menu, derwin(iso_win, 6, 38, 3, 1)); + set_menu_sub(shutter_menu, derwin(shutter_win, 6, 38, 3, 1)); + set_menu_sub(aperture_menu, derwin(aperture_win, 6, 38, 3, 1)); + post_menu(exposure_menu); + post_menu(iso_menu); + post_menu(shutter_menu); + post_menu(aperture_menu); + wrefresh(exposure_win); + wrefresh(iso_win); + wrefresh(shutter_win); + wrefresh(aperture_win); attron(COLOR_PAIR(2)); mvprintw(LINES - 2, 0, "Select EV"); /*mvprintw(LINES - 2, 0, "Select ISO and then one of Shutter/Aperture to calculate other of Shutter/Aperture");*/ mvprintw(LINES - 1, 0, "Arrow keys to navigate, Enter to select, Q to exit"); attroff(COLOR_PAIR(2)); @@ -173,118 +200,143 @@ cur = current_item(*menu); p = item_userptr(cur); /* Learning notes - Don't understand this bit */ /* Is this a function pointer? */ p((char *)item_name(cur)); - - switch (selection_counter) { - case 1: { /* Exposure selected */ - selection_counter += 1; - menu_counter += 1; - move(LINES - 2, 0); - clrtoeol(); - mvprintw(LINES - 2, 0, "Select ISO"); - refresh(); - menu = &iso_menu; - win = &iso_win; - } - break; - case 2: { /* ISO Selected */ - selection_counter += 1; - menu_counter += 1; - move(LINES - 2, 0); - clrtoeol(); - mvprintw(LINES - 2, 0, "Select Shutter or Aperture"); - refresh(); - menu = &shutter_menu; - win = &shutter_win; - } - break; - case 3: { /* Shutter or Aperture selected */ - if (strcmp("", shutter_sel) == 0) { - char aperture_sel_[4] = ""; - strncpy(aperture_sel_, aperture_sel+2, 3); - /* Using menu_driver to go up/down to force refresh and correct highlighting */ - menu_driver(shutter_menu, REQ_SCR_UPAGE); - menu_driver(shutter_menu, REQ_SCR_DPAGE); - /* There is probably a nicer way to format the below */ - set_menu_pattern( - shutter_menu, - shutter_array[nearest_match( - shutter(exposure(atoi(iso_sel)), strtod(aperture_sel_, NULL)), - 2 - )] - ); - menu_driver(shutter_menu, REQ_DOWN_ITEM); - menu_driver(shutter_menu, REQ_UP_ITEM); - wrefresh(shutter_win); - } - if (strcmp("", aperture_sel) == 0) { - menu_driver(aperture_menu, REQ_SCR_UPAGE); - menu_driver(aperture_menu, REQ_SCR_DPAGE); - set_menu_pattern( - aperture_menu, - aperture_array[nearest_match( - aperture(exposure(atoi(iso_sel)), fraction_to_double(shutter_sel)), - 3 - )] - ); - menu_driver(aperture_menu, REQ_DOWN_ITEM); - menu_driver(aperture_menu, REQ_UP_ITEM); - wrefresh(aperture_win); - } - /* clear the selections for next time */ - strcpy(iso_sel, ""); - strcpy(shutter_sel, ""); - strcpy(aperture_sel, ""); - /* And set defaults back to start */ - selection_counter = 1; - menu_counter = 1; - menu = &exposure_menu; - win = &exposure_win; - move(LINES - 2, 0); - clrtoeol(); - mvprintw(LINES - 2, 0, "Select EV"); - refresh(); - } - break; - } - } - break; - } - wrefresh(win); + /* need to igore over/under if selected, probably easier than try to prevent selection */ + if (!((strcmp("OVER", shutter_sel) == 0) + || (strcmp("UNDER", shutter_sel) == 0) + || (strcmp("OVER", aperture_sel) == 0) + || (strcmp("UNDER", aperture_sel) == 0))) { + switch (selection_counter) { + case 1: { /* Exposure selected */ + selection_counter += 1; + menu_counter += 1; + move(LINES - 2, 0); + clrtoeol(); + mvprintw(LINES - 2, 0, "Select ISO"); + refresh(); + menu = &iso_menu; + win = &iso_win; + } + break; + case 2: { /* ISO Selected */ + selection_counter += 1; + menu_counter += 1; + move(LINES - 2, 0); + clrtoeol(); + mvprintw(LINES - 2, 0, "Select Shutter or Aperture"); + refresh(); + menu = &shutter_menu; + win = &shutter_win; + } + break; + case 3: { /* Shutter or Aperture selected */ + if (strcmp("", shutter_sel) == 0) { + char aperture_sel_[4] = ""; + strncpy(aperture_sel_, aperture_sel+2, 3); + /* Using menu_driver to go up/down to force refresh and correct highlighting */ + menu_driver(shutter_menu, REQ_SCR_UPAGE); + menu_driver(shutter_menu, REQ_SCR_DPAGE); + /* There is probably a nicer way to format the below */ + set_menu_pattern( + shutter_menu, + shutter_array[nearest_match( + shutter(exposure(atoi(iso_sel)), strtod(aperture_sel_, NULL)), + 3, + n_shutter + )] + ); + menu_driver(shutter_menu, REQ_DOWN_ITEM); + menu_driver(shutter_menu, REQ_UP_ITEM); + wrefresh(shutter_win); + } + if (strcmp("", aperture_sel) == 0) { + menu_driver(aperture_menu, REQ_SCR_UPAGE); + menu_driver(aperture_menu, REQ_SCR_DPAGE); + set_menu_pattern( + aperture_menu, + aperture_array[nearest_match( + aperture(exposure(atoi(iso_sel)), fraction_to_double(shutter_sel)), + 4, + n_aperture + )] + ); + menu_driver(aperture_menu, REQ_DOWN_ITEM); + menu_driver(aperture_menu, REQ_UP_ITEM); + wrefresh(aperture_win); + } + /* clear the selections for next time */ + strcpy(iso_sel, ""); + strcpy(shutter_sel, ""); + strcpy(aperture_sel, ""); + /* And set defaults back to start */ + selection_counter = 1; + menu_counter = 1; + menu = &exposure_menu; + win = &exposure_win; + move(LINES - 2, 0); + clrtoeol(); + mvprintw(LINES - 2, 0, "Select EV"); + refresh(); + } + break; + } + } + /* If over/under need to clear selection so know which is blank + * when a proper selection is made */ + if ((strcmp("OVER", shutter_sel) == 0) || (strcmp("UNDER", shutter_sel) == 0)) { + strcpy(shutter_sel, ""); + } + if ((strcmp("OVER", aperture_sel) == 0) || (strcmp("UNDER", aperture_sel) == 0)) { + strcpy(aperture_sel, ""); + } + } + break; + } + wrefresh(*win); } /* Unpost and free all the memory taken up */ remove_menu(exposure_items, exposure_menu, n_exposure); remove_menu(iso_items, iso_menu, n_iso); remove_menu(shutter_items, shutter_menu, n_shutter); remove_menu(aperture_items, aperture_menu, n_aperture); endwin(); } -void add_menu(char **array, ITEM **items, MENU *men, WINDOW *win, int n, int xpos, char *title) { +ITEM **add_item(char **array, int n) { int i; + ITEM **local_items; - items = (ITEM **)calloc(n, sizeof(ITEM *)); + local_items = (ITEM **)calloc(n, sizeof(ITEM *)); for(i = 0; i= fraction_to_double(shutter_array[1])/2) { /* diff is greater than diff of next one down minus max/min */ + diff_idx = 0; + } + } + if (diff_idx == n_array-2) { + if (diff >= fraction_to_double(shutter_array[n_array-2])*2) { + diff_idx = n_array-1; + } } break; - case 3: - for ( n = 1; aperture_array[n] != NULL; ++n ) { + case 4: + for ( n = 2; n < n_array-1; ++n ) { strncpy(array_value_str, aperture_array[n]+2, 4); array_value_db = strtod(array_value_str, NULL); if (fabs(array_value_db - x) < diff) { diff_idx = n; diff = fabs(array_value_db - x); } } + /* Apertures similarly. Although progression is fiddlier.*/ + if (diff_idx == 1) { + strncpy(array_value_str, aperture_array[1]+2, 4); + array_value_db = strtod(array_value_str, NULL); + if (diff >= array_value_db/sqrt(2.0)) { /* diff is greater than diff of next one down minus max/min */ + diff_idx = 0; + } + } + if (diff_idx == n_array-2) { + strncpy(array_value_str, aperture_array[n_array-2]+2, 4); + array_value_db = strtod(array_value_str, NULL); + if (diff >= array_value_db*sqrt(2.0)) { + diff_idx = n_array-1; + } + } + break; } return diff_idx; }