From: Christian Heller Date: Sun, 15 Sep 2013 04:14:41 +0000 (+0200) Subject: Strongly overhauled keybinding managemment. Window-specific keybindings and a window... X-Git-Tag: tce~963 X-Git-Url: https://plomlompom.com/repos/%7B%7B%20web_path%20%7D%7D/decks/%7B%7Bdb.prefix%7D%7D/%7B%7Bprefix%7D%7D/templates?a=commitdiff_plain;h=550d22ec0c3f530f5d317746f3f7e75251a1de4b;p=plomrogue Strongly overhauled keybinding managemment. Window-specific keybindings and a window keybinding configuration view are now available. Changed lots of stuff peripheral to this issue here and there, too. --- diff --git a/README b/README index 457ed7a..8a73d7f 100644 --- a/README +++ b/README @@ -1,20 +1,19 @@ plomrogue ========= -plomlompom tries to build his own roguelike. Currently, it doesn't do -much interesting, apart from managing some ncurses windows in a bizarre -fashion. +plomlompom tries to build his own roguelike. Currently, it doesn't do much +interesting, apart from managing keybindings and some ncurses windows in a +bizarre fashion. -You can move around a player and meet a number of different enemies. -They move randomly and will only accidentally hit you. You have 5 -hitpoints to lose before death; they have either 1, 3 or 9. Your score -grows by killing enemies, to the amount of hitpoints each killed enemy -started with. +You can move around a player and meet a number of different enemies. They move +randomly and will only accidentally hit you. You have 5 hitpoints to lose before +death; they have either 1, 3 or 9. Your score grows by killing enemies, to the +amount of hitpoints each killed enemy started with. The map get generated randomly, too. -There is only one save file (named "savefile"), and it gets overwritten -each new turn. To start over with a new world, delete it. +There is only one save file (named "savefile"), and it gets overwritten each new +turn. To start over with a new world, delete it. Install/run ----------- @@ -26,46 +25,27 @@ cd plomrogue make ./roguelike -Default keybindings -------------------- - -Q quit -F1 toggle keybinding editing window -F2 toggle map window -F3 toggle info window -F4 toggle log window - -LEFT scroll windows pad left -RIGHT scroll windows pad right -> cycle window selection forwards -< cycle window selection backwards -y shift window forwards -Y shift window backwards -* grow window horizontally -_ shrink window horizontally -+ grow window vertically -- shrink window vertically -r reload window configuration -z toggle window configuration view -h toggle whether window height is saved as positive or negative -n toggle whether window width is saved as positive or negative -m save window configuration - -w scroll map up -x scroll map down -a scroll map left -d scroll map right -s center map on player -W move player up -X move player down -A move player left -D move player right -S next turn / wait - -K save current keybindings -UP navigate selection upwards in keybinding editing window -DOWN navigate selection downwards in keybinding editing window -RETURN modify keybinding selected in keybinding editing window +Keybindings and window configuration +------------------------------------ + +In the default window configuration, globally available keybinings are shown at +game start in the three windows on the left of the screen. The lower two windows +describe keybindings / actions only available in a window's window configuration +views -- hit "w" (per default keybindings) to switch the selected / "active" +window to a view that allows changing its geometry. One further hit on "w" +switches the window to a view that lists keybindings available specifically for +that window -- such as for map scrolling actions in the "map" window. All +keybindings can be changed. + +What actions are available globally or only in specific windows can be further +manipulated by editing the files config/keybindings_global and +config/windows/Win_* that map keycodes to commands to the respective keybinding +repositories. While keybindings_global contains merely a list of keycode command +mappings, the Win_* files start with the name of the windows to be configured, +followed by a one-character line for internal use (mapping the window to one of +several internally available window content drawing functions), followed by two +lines describing the window's designated height and width, and only then an +optional list of keybindings specific to that window. Replay game recording --------------------- diff --git a/config/commands b/config/commands index 10d452c..0798687 100644 --- a/config/commands +++ b/config/commands @@ -1,34 +1,45 @@ 1 quit quit -2 save_keys save keys -3 scrl_l scroll pad left -4 scrl_r scroll pad right -5 keys_d keys nav down -6 keys_u keys nav up -7 keys_m keys mod -8 to_keywin toggle keys window -9 to_mapwin toggle map window -10 to_infowin toggle info window -11 to_logwin toggle log window -12 cyc_win_f cycle forwards -13 cyc_win_b cycle backwards -14 shift_f shift forwards -15 shift_b shift backwards -16 grow_h grow horizontally -17 shri_h shrink horizontally -18 grow_v grow vertically -19 shri_v shrink vertically -20 map_u map up -21 map_d map down -22 map_l map left -23 map_r map right -24 map_c map center player -25 player_u player up -26 player_d player down -27 player_l player left -28 player_r player right -29 wait wait / next turn -30 reload_wins reload windows configuration -31 winconf toggle window configuration view -32 to_height_t toggle window height type -33 to_width_t toggle window width type -34 save_winconf save window configuration +2 wait wait / next turn +3 player_u player up +4 player_d player down +5 player_l player left +6 player_r player right +7 to_g_keywin toggle global keys window +8 to_mapwin toggle map window +9 to_infowin toggle info window +10 to_logwin toggle log window +11 to_wg_keywin toggle window geometry keys window +12 to_wk_keywin toggle window keybinding keys window +13 cyc_win_f cycle window selection forwards +14 winconf toggle window configuration view +15 cyc_win_b cycle window selection backwards +16 scrl_l scroll pad left +17 scrl_r scroll pad right +18 g_keys_d global keybindings nav down +19 g_keys_u global keybindings nav up +20 g_keys_m global keybindings modify +21 shift_f shift window forwards +22 shift_b shift window backwards +23 grow_h grow window horizontally +24 shri_h shrink window horizontally +25 grow_v grow window vertically +26 shri_v shrink window vertically +27 to_height_t toggle window height type +28 to_width_t toggle window width type +29 w_keys_d win keys nav down +30 w_keys_u win keys nav up +31 w_keys_m win keys mod +32 wg_keys_d win geometry config keybindings nav down +33 wg_keys_u win geometry config keybindings nav up +34 wg_keys_m win geometry config keybindings modify +35 wk_keys_d win keybindings config keybindings nav down +36 wk_keys_u win keybindings config keybindings nav up +37 wk_keys_m win keybindings config keybindings modify +38 reload_wins reload windows configuration +39 save_winconf save windows' configuration +40 save_keys save global keybindings +41 map_u map up +42 map_d map down +43 map_l map left +44 map_r map right +45 map_c map center player diff --git a/config/keybindings b/config/keybindings deleted file mode 100644 index b8ced54..0000000 --- a/config/keybindings +++ /dev/null @@ -1,34 +0,0 @@ -81 quit -119 map_u -120 map_d -97 map_l -100 map_r -115 map_c -87 player_u -88 player_d -65 player_l -68 player_r -83 wait -75 save_keys -258 keys_d -259 keys_u -10 keys_m -265 to_keywin -266 to_mapwin -267 to_infowin -268 to_logwin -62 cyc_win_f -60 cyc_win_b -121 shift_f -89 shift_b -42 grow_h -95 shri_h -43 grow_v -45 shri_v -260 scrl_l -261 scrl_r -114 reload_wins -122 winconf -104 to_height_t -110 to_width_t -109 save_winconf diff --git a/config/keybindings_global b/config/keybindings_global new file mode 100644 index 0000000..f272302 --- /dev/null +++ b/config/keybindings_global @@ -0,0 +1,20 @@ +81 quit +58 wait +107 player_u +106 player_d +104 player_l +108 player_r +265 to_g_keywin +266 to_wg_keywin +267 to_wk_keywin +268 to_mapwin +269 to_infowin +270 to_logwin +119 winconf +62 cyc_win_f +60 cyc_win_b +262 scrl_l +360 scrl_r +114 reload_wins +75 save_keys +87 save_winconf diff --git a/config/keybindings_wingeom b/config/keybindings_wingeom new file mode 100644 index 0000000..d322501 --- /dev/null +++ b/config/keybindings_wingeom @@ -0,0 +1,8 @@ +258 shift_f +259 shift_b +42 grow_h +95 shri_h +43 grow_v +45 shri_v +121 to_height_t +120 to_width_t diff --git a/config/keybindings_winkeys b/config/keybindings_winkeys new file mode 100644 index 0000000..8a15320 --- /dev/null +++ b/config/keybindings_winkeys @@ -0,0 +1,3 @@ +258 w_keys_d +259 w_keys_u +10 w_keys_m diff --git a/config/windows/Win_0 b/config/windows/Win_0 new file mode 100644 index 0000000..e79bdcd --- /dev/null +++ b/config/windows/Win_0 @@ -0,0 +1,7 @@ +Global keys +0 +-13 +29 +258 g_keys_d +259 g_keys_u +10 g_keys_m diff --git a/config/windows/Win_1 b/config/windows/Win_1 new file mode 100644 index 0000000..645c8c4 --- /dev/null +++ b/config/windows/Win_1 @@ -0,0 +1,7 @@ +Window geometry keys +1 +8 +29 +258 wg_keys_d +259 wg_keys_u +10 wg_keys_m diff --git a/config/windows/Win_2 b/config/windows/Win_2 new file mode 100644 index 0000000..c1d9448 --- /dev/null +++ b/config/windows/Win_2 @@ -0,0 +1,7 @@ +Window keybinding keys +2 +3 +29 +258 wk_keys_d +259 wk_keys_u +10 wk_keys_m diff --git a/config/windows/Win_k b/config/windows/Win_k deleted file mode 100644 index edfb283..0000000 --- a/config/windows/Win_k +++ /dev/null @@ -1,4 +0,0 @@ -Keys -k -0 -29 diff --git a/config/windows/Win_m b/config/windows/Win_m index 42ccf97..a3c38a9 100644 --- a/config/windows/Win_m +++ b/config/windows/Win_m @@ -2,3 +2,8 @@ Map m 0 -64 +259 map_u +258 map_d +260 map_l +261 map_r +46 map_c diff --git a/config/windows/toggle_order b/config/windows/toggle_order index 0b431e9..0ee8c5e 100644 --- a/config/windows/toggle_order +++ b/config/windows/toggle_order @@ -1 +1 @@ -kmil +012mil diff --git a/src/command_db.c b/src/command_db.c index 0bf7c84..d89319d 100644 --- a/src/command_db.c +++ b/src/command_db.c @@ -90,6 +90,10 @@ extern void init_command_db(struct World * world) uint8_t i = 0; while (fgets(line, linemax + 1, file)) { + if ('\n' == line[0] || 0 == line[0]) + { + break; + } cmds[i].id = atoi(strtok(line, " ")); copy_tokenized_string(world, &cmds[i].dsc_short, " "); copy_tokenized_string(world, &cmds[i].dsc_long, "\n"); diff --git a/src/control.c b/src/control.c index 842b710..a4479ce 100644 --- a/src/control.c +++ b/src/control.c @@ -6,7 +6,7 @@ * struct WinMeta */ #include "keybindings.h" /* for get_keycode_to_action(), save_keybindings(), - * move_keys_mod_selection(), keyswin_mod_key() + * move_keyb_mod_selection(), mod_selected_keyb() */ #include "map.h" /* for map_scroll(), map_center_player(), dir enum */ #include "main.h" /* for World struct */ @@ -21,6 +21,32 @@ +extern uint16_t get_available_keycode_to_action(struct World * world, + char * name) +{ + uint16_t keycode = get_keycode_to_action(world->kb_global.kbs, name); + if (0 != keycode || 0 == world->wmeta->active) + { + return keycode; + } + struct WinConf * wc = get_winconf_by_win(world, world->wmeta->active); + if (0 == wc->view) + { + keycode = get_keycode_to_action(wc->kb.kbs, name); + } + else if (1 == wc->view) + { + keycode = get_keycode_to_action(world->kb_wingeom.kbs, name); + } + else if (2 == wc->view) + { + keycode = get_keycode_to_action(world->kb_winkeys.kbs, name); + } + return keycode; +} + + + extern void record_control(int action, struct World * world) { if (is_command_id_shortdsc(world, action, "wait")) @@ -49,31 +75,101 @@ extern void record_control(int action, struct World * world) extern uint8_t player_control(int key, struct World * world) { - if (key == get_keycode_to_action(world->keybindings, "player_u")) + if (key == get_available_keycode_to_action(world, "player_u")) { move_player(world, NORTH); } - else if (key == get_keycode_to_action(world->keybindings, "player_r")) + else if (key == get_available_keycode_to_action(world, "player_r")) { move_player(world, EAST); } - else if (key == get_keycode_to_action(world->keybindings, "player_d")) + else if (key == get_available_keycode_to_action(world, "player_d")) { move_player(world, SOUTH); } - else if (key == get_keycode_to_action(world->keybindings, "player_l")) + else if (key == get_available_keycode_to_action(world, "player_l")) { move_player(world, WEST); } - else if (key == get_keycode_to_action(world->keybindings, "wait")) + else if (key == get_available_keycode_to_action(world, "wait")) { player_wait(world); } else { - return 1; + return 0; } - return 0; + return 1; +} + + + +extern uint8_t wingeom_control(int key, struct World * world) +{ + char * err_shift = "Trouble with shift_active_win() in wingeom_control()."; + char * err_resize = "Trouble with growshrink_active_window() in " + "wingeom_control()."; + if (key == get_available_keycode_to_action(world, "to_height_t")) + { + toggle_win_height_type(world, world->wmeta->active); + } + else if (key == get_available_keycode_to_action(world, "to_width_t")) + { + toggle_win_width_type(world, world->wmeta->active); + } + else if (key == get_available_keycode_to_action(world, "grow_h")) + { + exit_err(growshrink_active_window(world, '*'), world, err_resize); + } + else if (key == get_available_keycode_to_action(world, "shri_h")) + { + exit_err(growshrink_active_window(world, '_'), world, err_resize); + } + else if (key == get_available_keycode_to_action(world, "grow_v")) + { + exit_err(growshrink_active_window(world, '+'), world, err_resize); + } + else if (key == get_available_keycode_to_action(world, "shri_v")) + { + exit_err(growshrink_active_window(world, '-'), world, err_resize); + } + else if (key == get_available_keycode_to_action(world, "shift_f")) + { + exit_err(shift_active_win(world->wmeta, 'f'), world, err_shift); + } + else if (key == get_available_keycode_to_action(world, "shift_b")) + { + exit_err(shift_active_win(world->wmeta, 'b'), world, err_shift); + } + else + { + return 0; + } + return 1; +} + + + +extern uint8_t winkeyb_control(int key, struct World * world) +{ + struct WinConf * wc = get_winconf_by_win(world, world->wmeta->active); + if (key == get_available_keycode_to_action(world, "w_keys_u")) + { + move_keyb_mod_selection(&wc->kb, 'u'); + } + else if (key == get_available_keycode_to_action(world, "w_keys_d")) + { + move_keyb_mod_selection(&wc->kb, 'd'); + } + else if (key == get_available_keycode_to_action(world, "w_keys_m")) + { + mod_selected_keyb(world, &wc->kb); + } + else + { + return 0; + } + return 1; } @@ -81,127 +177,135 @@ extern uint8_t player_control(int key, struct World * world) extern uint8_t meta_control(int key, struct World * world) { struct WinMeta * win_meta = world->wmeta; - struct Win * win_keys = get_win_by_id(world, 'k'); /* Bad hardcoding. */ + struct Win * win_keys = get_win_by_id(world, '0'); /* Bad hardcoding. */ struct Win * win_map = get_win_by_id(world, 'm'); /* TODO: Replace. */ struct Win * win_info = get_win_by_id(world, 'i'); /* */ struct Win * win_log = get_win_by_id(world, 'l'); /* */ - char * err_toggle = "Trouble with toggle_window() in meta_keys()."; - char * err_shift = "Trouble with shift_active_win() in meta_keys()."; - char * err_resize = "Trouble with growshrink_active_window() in " - "meta_keys()."; - if (key == get_keycode_to_action(world->keybindings, "quit")) + char * err_toggle = "Trouble with toggle_window() in meta_control()."; + if (key == get_available_keycode_to_action(world, "quit")) { return 1; } - else if (key == get_keycode_to_action(world->keybindings, "scrl_r")) + else if (key == get_available_keycode_to_action(world, "winconf")) + { + toggle_winconfig(world, world->wmeta->active); + } + else if (key == get_available_keycode_to_action(world, "cyc_win_f")) + { + cycle_active_win(world->wmeta, 'f'); + } + else if (key == get_available_keycode_to_action(world, "cyc_win_b")) + { + cycle_active_win(world->wmeta, 'b'); + } + else if (key == get_available_keycode_to_action(world, "scrl_r")) { scroll_pad(win_meta, '+'); } - else if (key == get_keycode_to_action(world->keybindings, "scrl_l")) + else if (key == get_available_keycode_to_action(world, "scrl_l")) { scroll_pad(win_meta, '-'); } - else if (key == get_keycode_to_action(world->keybindings, "to_keywin")) + else if (key == get_available_keycode_to_action(world, "to_g_keywin")) { exit_err(toggle_window(win_meta, win_keys), world, err_toggle); } - else if (key == get_keycode_to_action(world->keybindings, "to_mapwin")) + else if (key == get_available_keycode_to_action(world, "to_wg_keywin")) { - exit_err(toggle_window(win_meta, win_map), world, err_toggle); + uint8_t test = toggle_window(win_meta, get_win_by_id(world, '1')); + exit_err(test, world, err_toggle); } - else if (key == get_keycode_to_action(world->keybindings, "to_infowin")) + else if (key == get_available_keycode_to_action(world, "to_wk_keywin")) { - exit_err(toggle_window(win_meta, win_info), world, err_toggle); + uint8_t test = toggle_window(win_meta, get_win_by_id(world, '2')); + exit_err(test, world, err_toggle); } - else if (key == get_keycode_to_action(world->keybindings, "to_logwin")) + else if (key == get_available_keycode_to_action(world, "to_mapwin")) { - exit_err(toggle_window(win_meta, win_log), world, err_toggle); + exit_err(toggle_window(win_meta, win_map), world, err_toggle); } - else if (key == get_keycode_to_action(world->keybindings, "cyc_win_f")) + else if (key == get_available_keycode_to_action(world, "to_infowin")) { - cycle_active_win(win_meta, 'f'); + exit_err(toggle_window(win_meta, win_info), world, err_toggle); } - else if (key == get_keycode_to_action(world->keybindings, "cyc_win_b")) + else if (key == get_available_keycode_to_action(world, "to_logwin")) { - cycle_active_win(win_meta, 'b'); + exit_err(toggle_window(win_meta, win_log), world, err_toggle); } - else if (key == get_keycode_to_action(world->keybindings, "shift_f")) + else if (key == get_available_keycode_to_action(world, "save_keys")) { - exit_err(shift_active_win(win_meta, 'f'), world, err_shift); + save_keybindings(world, "config/keybindings_global", + &world->kb_global); + save_keybindings(world, "config/keybindings_wingeom", + &world->kb_wingeom); + save_keybindings(world, "config/keybindings_winkeys", + &world->kb_winkeys); } - else if (key == get_keycode_to_action(world->keybindings, "shift_b")) + else if (key == get_available_keycode_to_action(world, "g_keys_u")) { - exit_err(shift_active_win(win_meta, 'b'), world, err_shift); + move_keyb_mod_selection(&world->kb_global, 'u'); } - else if (key == get_keycode_to_action(world->keybindings, "grow_h")) + else if (key == get_available_keycode_to_action(world, "g_keys_d")) { - exit_err(growshrink_active_window(world, '*'), world, err_resize); + move_keyb_mod_selection(&world->kb_global, 'd'); } - else if (key == get_keycode_to_action(world->keybindings, "shri_h")) + else if (key == get_available_keycode_to_action(world, "g_keys_m")) { - exit_err(growshrink_active_window(world, '_'), world, err_resize); + mod_selected_keyb(world, &world->kb_global); } - else if (key == get_keycode_to_action(world->keybindings, "grow_v")) + else if (key == get_available_keycode_to_action(world, "wg_keys_u")) { - exit_err(growshrink_active_window(world, '+'), world, err_resize); + move_keyb_mod_selection(&world->kb_wingeom, 'u'); } - else if (key == get_keycode_to_action(world->keybindings, "shri_v")) + else if (key == get_available_keycode_to_action(world, "wg_keys_d")) { - exit_err(growshrink_active_window(world, '-'), world, err_resize); + move_keyb_mod_selection(&world->kb_wingeom, 'd'); } - else if (key == get_keycode_to_action(world->keybindings, "save_keys")) + else if (key == get_available_keycode_to_action(world, "wg_keys_m")) { - save_keybindings(world); + mod_selected_keyb(world, &world->kb_wingeom); } - else if (key == get_keycode_to_action(world->keybindings, "keys_u")) + else if (key == get_available_keycode_to_action(world, "wk_keys_u")) { - move_keys_mod_selection(world, 'u'); + move_keyb_mod_selection(&world->kb_winkeys, 'u'); } - else if (key == get_keycode_to_action(world->keybindings, "keys_d")) + else if (key == get_available_keycode_to_action(world, "wk_keys_d")) { - move_keys_mod_selection(world, 'd'); + move_keyb_mod_selection(&world->kb_winkeys, 'd'); } - else if (key == get_keycode_to_action(world->keybindings, "keys_m")) + else if (key == get_available_keycode_to_action(world, "wk_keys_m")) { - keyswin_mod_key(world, win_meta); + mod_selected_keyb(world, &world->kb_winkeys); } - else if (key == get_keycode_to_action(world->keybindings, "map_u")) + else if (key == get_available_keycode_to_action(world, "map_u")) { map_scroll(world->map, NORTH, win_map->frame.size); } - else if (key == get_keycode_to_action(world->keybindings, "map_d")) + else if (key == get_available_keycode_to_action(world, "map_d")) { map_scroll(world->map, SOUTH, win_map->frame.size); } - else if (key == get_keycode_to_action(world->keybindings, "map_r")) + else if (key == get_available_keycode_to_action(world, "map_r")) { map_scroll(world->map, EAST, win_map->frame.size); } - else if (key == get_keycode_to_action(world->keybindings, "map_l")) + else if (key == get_available_keycode_to_action(world, "map_l")) { map_scroll(world->map, WEST, win_map->frame.size); } - else if (key == get_keycode_to_action(world->keybindings, "map_c")) + else if (key == get_available_keycode_to_action(world, "map_c")) { map_center_player(world->map, world->player, win_map->frame.size); } - else if (key == get_keycode_to_action(world->keybindings, "reload_wins")) + else if (key == get_available_keycode_to_action(world, "reload_wins")) { reload_win_config(world); } - else if (key == get_keycode_to_action(world->keybindings, "winconf")) + else if (key == get_available_keycode_to_action(world, "winconf")) { toggle_winconfig(world, world->wmeta->active); } - else if (key == get_keycode_to_action(world->keybindings, "to_height_t")) - { - toggle_win_height_type(world, world->wmeta->active); - } - else if (key == get_keycode_to_action(world->keybindings, "to_width_t")) - { - toggle_win_width_type(world, world->wmeta->active); - } - else if (key == get_keycode_to_action(world->keybindings, "save_winconf")) + else if (key == get_available_keycode_to_action(world, "save_winconf")) { save_win_configs(world); } diff --git a/src/control.h b/src/control.h index 79e5976..470b026 100644 --- a/src/control.h +++ b/src/control.h @@ -13,6 +13,12 @@ struct World; +/* Return keycode to action of "name" if available in current window config. */ +extern uint16_t get_available_keycode_to_action(struct World * world, + char * name); + + + /* Control the player character, either via recorded "action" or pressed "key". */ extern void record_control(int action, struct World * world); @@ -20,8 +26,16 @@ extern uint8_t player_control(int key, struct World * world); -/* Call by "key" game / window management actions that don't influence the - * player character. If the "quit" action is called, return 1 (instead of +/* Control via "key" active window's geometry / keybindings in respective config + * view. + */ +extern uint8_t wingeom_control(int key, struct World * world); +extern uint8_t winkeyb_control(int key, struct World * world); + + + +/* Call by "key" further game / window management actions that don't influence + * the player character. If the "quit" action is called, return 1 (instead of * exiting directly). */ extern uint8_t meta_control(int key, struct World * world); diff --git a/src/draw_wins.c b/src/draw_wins.c index d4275d3..f0397d9 100644 --- a/src/draw_wins.c +++ b/src/draw_wins.c @@ -28,6 +28,10 @@ static void draw_text_from_bottom(struct Win * win, char * text); static void draw_map_objects(struct World * world, struct MapObj * start, struct Map * map, struct Win * win); +/* Draw from line "start" on config view for keybindings defined at "kb". */ +static void draw_kb_view(struct World * world, struct Win * win, + char * f_name, struct KeyBiData * kb, uint8_t start); + static void draw_with_linebreaks(struct Win * win, char * text, @@ -162,7 +166,74 @@ static void draw_map_objects(struct World * world, struct MapObj * start, -extern void draw_log_win(struct Win * win) +static void draw_kb_view(struct World * world, struct Win * win, + char * f_name, struct KeyBiData * kb, uint8_t start) +{ + char * err_hint = trouble_msg(world, f_name, "draw_scroll_hint()"); + uint16_t kb_max = get_n_of_keybs(kb->kbs) - 1; + uint16_t y, x, offset; + offset = center_offset(kb->select, kb_max, win->frame.size.y - 1 - start); + uint8_t keydescwidth = 9 + 1; /* get_name_to_keycode()'s max length + \0 */ + char keydesc[keydescwidth]; + uint16_t nav_max = kb_max + start; + uint16_t y_border = win->frame.size.y + offset - 1 - start; + for (y = start; y <= nav_max && y < win->frame.size.y; y++) + { + + if (start == y && offset > 0) + { + uint8_t test = draw_scroll_hint(&win->frame, y, offset + 1, '^'); + exit_err(test, world, err_hint); + continue; + } + else if (win->frame.size.y == y + 1 && kb_max > y_border) + { + uint16_t pos = kb_max - (offset + win->frame.size.y) + 2 + start; + uint8_t test = draw_scroll_hint(&win->frame, y, pos, 'v'); + exit_err(test, world, err_hint); + continue; + } + + attr_t attri = 0; + if (y - start == kb->select - offset) + { + attri = A_REVERSE; + if (1 == kb->edit) + { + attri = attri | A_BLINK; + } + } + + struct KeyBinding * kb_p; + kb_p = get_keyb_of_n(kb->kbs, (y - start) + offset); + char * keyname = get_name_to_keycode(world, kb_p->key); + snprintf(keydesc, keydescwidth, "%-9s", keyname); + free(keyname); + char * cmd_dsc = get_command_longdsc(world, kb_p->name); + uint8_t dsclen = strlen(keydesc); + for (x = 0; x < win->frame.size.x; x++) + { + if (x < dsclen) + { + mvwaddch(win->frame.curses_win, y, x, keydesc[x] | attri); + continue; + } + else if (dsclen < x && x < strlen(cmd_dsc) + strlen(keydesc) + 1) + { + chtype ch = cmd_dsc[x - strlen(keydesc) - 1] | attri; + mvwaddch(win->frame.curses_win, y, x, ch); + continue; + } + mvwaddch(win->frame.curses_win, y, x, ' ' | attri); + } + + } + free(err_hint); +} + + + +extern void draw_win_log(struct Win * win) { struct World * world = (struct World *) win->data; draw_text_from_bottom(win, world->log); @@ -170,7 +241,7 @@ extern void draw_log_win(struct Win * win) -extern void draw_map_win(struct Win * win) +extern void draw_win_map(struct Win * win) { struct World * world = (struct World *) win->data; struct Map * map = world->map; @@ -206,7 +277,7 @@ extern void draw_map_win(struct Win * win) -extern void draw_info_win(struct Win * win) +extern void draw_win_info(struct Win * win) { struct World * world = (struct World *) win->data; char * dsc_turn = "Turn: "; @@ -224,81 +295,51 @@ extern void draw_info_win(struct Win * win) -extern void draw_keys_win(struct Win * win) +extern void draw_win_keybindings_global(struct Win * win) { - char * err_hint = "Trouble with draw_scroll_hint() in draw_keys_win()."; + char * f_name = "draw_win_keybindings_global()"; struct World * world = (struct World *) win->data; - uint16_t n_keybs = get_n_of_keybs(world); - uint16_t offset = center_offset(world->keyswindata->select, n_keybs - 1, - win->frame.size.y - 1); + draw_kb_view(world, win, f_name, &world->kb_global, 0); +} - uint8_t keydescwidth = 9 + 1; /* get_name_to_keycode()'s max length + \0 */ - char keydesc[keydescwidth]; - uint16_t y, x; - for (y = 0; y <= n_keybs - 1 && y < win->frame.size.y; y++) - { - if (0 == y && offset > 0) - { - exit_err(draw_scroll_hint(&win->frame, y, offset + 1, '^'), - world, err_hint); - continue; - } - else if (win->frame.size.y == y + 1 - && 0 < (n_keybs - 1) - - (win->frame.size.y + offset - 1)) - { - exit_err(draw_scroll_hint(&win->frame, y, - (n_keybs - 1) - - (offset + win->frame.size.y) + 2, - 'v'), - world, err_hint); - continue; - } +extern void draw_win_keybindings_winconf_geometry(struct Win * win) +{ + char * f_name = "draw_win_keybindings_winconf_geometry()"; + struct World * world = (struct World *) win->data; + draw_kb_view(world, win, f_name, &world->kb_wingeom, 0); +} - attr_t attri = 0; - if (y == world->keyswindata->select - offset) - { - attri = A_REVERSE; - if (1 == world->keyswindata->edit) - { - attri = attri | A_BLINK; - } - } - struct KeyBinding * kb_p = get_keyb_of_n(world, y + offset); - char * keyname = get_name_to_keycode(world, kb_p->key); - snprintf(keydesc, keydescwidth, "%-9s", keyname); - free(keyname); - char * cmd_dsc = get_command_longdsc(world, kb_p->name); - for (x = 0; x < win->frame.size.x; x++) - { - if (x < strlen(keydesc)) - { - mvwaddch(win->frame.curses_win, y, x, keydesc[x] | attri); - } - else if ( strlen(keydesc) < x - && x < strlen(cmd_dsc) + strlen(keydesc) + 1) - { - mvwaddch(win->frame.curses_win, y, x, - cmd_dsc[x - strlen(keydesc) - 1] | attri); - } - else - { - mvwaddch(win->frame.curses_win, y, x, ' ' | attri); - } - } - } + +extern void draw_win_keybindings_winconf_keybindings(struct Win * win) +{ + char * f_name = "draw_win_keybindings_winconf_keybindings()"; + struct World * world = (struct World *) win->data; + draw_kb_view(world, win, f_name, &world->kb_winkeys, 0); +} + + + +extern void draw_winconf_keybindings(struct Win * win) +{ + char * f_name = "draw_winconf_keybindings()"; + struct World * world = (struct World *) win->data; + struct WinConf * wc = get_winconf_by_win(world, win); + char * title = "Window's keybindings:"; + uint8_t title_space = strlen(title) / win->frame.size.x + 2; + mvwaddstr(win->frame.curses_win, 0, 0, "Window's keybindings:"); + draw_kb_view(world, win, f_name, &wc->kb, title_space); } -extern void draw_winconf(struct Win * win) +extern void draw_winconf_geometry(struct Win * win) { struct World * world = (struct World *) win->data; struct WinConf * wcp = get_winconf_by_win(world, win); - char * title = "Window configuration:\n"; + char * title = "Window's geometry:\n"; char * h_d = "\nWidth to save: "; char * h_pos = " (height in cells)"; char * h_neg = " (negative diff: cells to maximum height)"; diff --git a/src/draw_wins.h b/src/draw_wins.h index 6a939eb..d209d82 100644 --- a/src/draw_wins.h +++ b/src/draw_wins.h @@ -13,20 +13,17 @@ struct Win; -/* Write game log text into "win" from bottom to top. */ -extern void draw_log_win(struct Win * win); - -/* Draw game map and actors/objects on it into "win". Respect scroll offset. */ -extern void draw_map_win(struct Win * win); - -/* Draw into "win" the game / player status infos. */ -extern void draw_info_win(struct Win * win); - -/* Draw keybindings selection/manipulation menu. */ -extern void draw_keys_win(struct Win * win); - -/* Draw window configuration info. */ -extern void draw_winconf(struct Win * win); +/* Default routines to draw the various windows' contents. */ +extern void draw_win_log(struct Win * win); +extern void draw_win_map(struct Win * win); +extern void draw_win_info(struct Win * win); +extern void draw_win_keybindings_global(struct Win * win); +extern void draw_win_keybindings_winconf_geometry(struct Win * win); +extern void draw_win_keybindings_winconf_keybindings(struct Win * win); + +/* Routines to draw windows' configuration views. */ +extern void draw_winconf_keybindings(struct Win * win); +extern void draw_winconf_geometry(struct Win * win); diff --git a/src/keybindings.c b/src/keybindings.c index 5212d5a..9443531 100644 --- a/src/keybindings.c +++ b/src/keybindings.c @@ -113,10 +113,9 @@ extern char * get_name_to_keycode(struct World * world, uint16_t keycode) -extern uint16_t get_n_of_keybs(struct World * world) +extern uint16_t get_n_of_keybs(struct KeyBinding * kb_p) { uint16_t i = 0; - struct KeyBinding * kb_p = world->keybindings; while (1) { if (0 == kb_p) @@ -131,10 +130,9 @@ extern uint16_t get_n_of_keybs(struct World * world) -extern struct KeyBinding * get_keyb_of_n(struct World * world, uint16_t n) +extern struct KeyBinding * get_keyb_of_n(struct KeyBinding * kb_p, uint16_t n) { uint16_t i = 0; - struct KeyBinding * kb_p = world->keybindings; while (1) { if (n == i) @@ -149,11 +147,11 @@ extern struct KeyBinding * get_keyb_of_n(struct World * world, uint16_t n) -extern void init_keybindings(struct World * world) +extern void init_keybindings(struct World * world, char * path, + struct KeyBiData * kbd) { char * f_name = "init_keybindings()"; - char * path = "config/keybindings"; FILE * file = try_fopen(path, "r", world, f_name); uint16_t lines, linemax; char * err = "textfile_sizes() in init_keybindings() returns error."; @@ -161,9 +159,14 @@ extern void init_keybindings(struct World * world) char command[linemax + 1]; char * cmdptr; - struct KeyBinding ** loc_last_ptr = &world->keybindings; + struct KeyBinding ** loc_last_ptr = &kbd->kbs; + * loc_last_ptr = 0; while (fgets(command, linemax + 1, file)) { + if ('\n' == command[0] || 0 == command[0]) + { + break; + } * loc_last_ptr = try_malloc(sizeof(struct KeyBinding), world, f_name); struct KeyBinding * kb_p = * loc_last_ptr; kb_p->next = 0; @@ -177,25 +180,23 @@ extern void init_keybindings(struct World * world) try_fclose(file, world, f_name); - struct KeysWinData * keyswindata; - keyswindata = try_malloc(sizeof(struct KeysWinData), world, f_name); - keyswindata->select = 0; - keyswindata->edit = 0; - world->keyswindata = keyswindata; + kbd->edit = 0; + kbd->select = 0; } -extern void save_keybindings(struct World * world) +extern void save_keybindings(struct World * world, char * path, + struct KeyBiData * kbd) { char * f_name = "save_keybindings()"; - char * path = "config/keybindings"; - char * path_tmp = "config/keybindings_tmp"; + char path_tmp[strlen(path) + 4 + 1]; + sprintf(path_tmp, "%s_tmp", path); FILE * file = try_fopen(path_tmp, "w", world, f_name); uint16_t linemax = 0; - struct KeyBinding * kb_p = world->keybindings; + struct KeyBinding * kb_p = kbd->kbs; while (0 != kb_p) { if (strlen(kb_p->name) > linemax) @@ -207,7 +208,7 @@ extern void save_keybindings(struct World * world) linemax = linemax + 6; /* + 6 = + 3 digits + whitespace + \n + \0 */ char line[linemax]; - kb_p = world->keybindings; + kb_p = kbd->kbs; while (0 != kb_p) { snprintf(line, linemax, "%d %s\n", kb_p->key, kb_p->name); @@ -222,43 +223,45 @@ extern void save_keybindings(struct World * world) extern void free_keybindings(struct KeyBinding * kb_start) { + if (0 == kb_start) + { + return; + } struct KeyBinding * kb_p = kb_start->next; if (0 != kb_p) { free_keybindings(kb_p); } + free(kb_start->name); free(kb_start); } -extern void keyswin_mod_key(struct World * world, struct WinMeta * win_meta) +extern void mod_selected_keyb(struct World * world, struct KeyBiData * kbd) { - world->keyswindata->edit = 1; - exit_err(draw_all_wins(win_meta), world, "Trouble with draw_all_wins() in " - "keyswin_mod_key()."); + kbd->edit = 1; + exit_err(draw_all_wins(world->wmeta), world, + "Trouble with draw_all_wins() in mod_selected_keyb()."); int key = getch(); if (key < 1000) { - struct KeyBinding * kb_p = get_keyb_of_n(world, - world->keyswindata->select); + struct KeyBinding * kb_p = get_keyb_of_n(kbd->kbs, kbd->select); kb_p->key = key; } - world->keyswindata->edit = 0; + kbd->edit = 0; } -extern void move_keys_mod_selection(struct World * world, char dir) +extern void move_keyb_mod_selection(struct KeyBiData * kbd, char dir) { - if ( 'u' == dir - && world->keyswindata->select > 0) + if ('u' == dir && kbd->select > 0) { - world->keyswindata->select--; + kbd->select--; } - else if ( 'd' == dir - && world->keyswindata->select < get_n_of_keybs(world) - 1) + else if ('d' == dir && kbd->select < get_n_of_keybs(kbd->kbs) - 1) { - world->keyswindata->select++; + kbd->select++; } } diff --git a/src/keybindings.h b/src/keybindings.h index d400414..ce15e66 100644 --- a/src/keybindings.h +++ b/src/keybindings.h @@ -10,11 +10,10 @@ #include /* for uint16_t */ struct World; -struct WinMeta; -/* Individual keybinding. */ +/* Individual keybinding in keybinding chain. */ struct KeyBinding { struct KeyBinding * next; @@ -24,48 +23,56 @@ struct KeyBinding -/* Metadata used by the keybinding editing window. */ -struct KeysWinData +/* Wrapper to keybinding chain, contains some keybinding editing metadata. */ +struct KeyBiData { - char edit; /* 1 if currently editing a keybinding, else 0 */ - uint16_t select; /* list index of keybinding selected for editing */ + struct KeyBinding * kbs; + uint8_t edit; /* 1 if currently editing a keybinding, else 0 */ + uint16_t select; /* linear list index of keybinding selected for editing */ }; /* Return keycode matched by keybinding to command of "name". */ -extern uint16_t get_keycode_to_action(struct KeyBinding * keybindings, char * name); +extern uint16_t get_keycode_to_action(struct KeyBinding * keybindings, + char * name); /* Return human-readable name (of maximum 9 chars) for "keycode" as matched by - * ncurses.h; if none is found, return "UNKNOWN". */ + * ncurses.h; if none is found, return "UNKNOWN". + */ extern char * get_name_to_keycode(struct World * world, uint16_t keycode); -/* Return number of keybindings in keybindings chain. */ -extern uint16_t get_n_of_keybs(struct World * world); +/* Return number of keybindings in keybindings chain from "kb_p" on. */ +extern uint16_t get_n_of_keybs(struct KeyBinding * kb_p); -/* Return "n"-th keybinding in keybindings chain. */ -extern struct KeyBinding * get_keyb_of_n(struct World * world, uint16_t n); +/* Return "n"-th keybinding in keybindings chain from "kb_p" on. */ +extern struct KeyBinding * get_keyb_of_n(struct KeyBinding * kb_p, uint16_t n); -/* Initialize keybindings data (by reading from file "keybindings"), save it (by - * writing to the same file) and free it. +/* Initialize/save keybindings data from/to file at "path" to/from keybindings + * data pointer "kbd". */ -extern void init_keybindings(struct World * world); -extern void save_keybindings(struct World * world); +extern void init_keybindings(struct World * world, char * path, + struct KeyBiData * kbd); +extern void save_keybindings(struct World * world, char * path, + struct KeyBiData * kbd); + +/* Free keybinding chain starting at "kb_start". */ extern void free_keybindings(struct KeyBinding * kb_start); -/* Mark selection in keybindings window modifiable, get user input to modify - * key. Ensure there are max. three digits in the keycode ASCII representation. +/* Mark keybinding selected for modification as being edited, get user input to + * modify it, then unmark it again. Ensure there are max. three digits in the + * keycode ASCII representation. */ -extern void keyswin_mod_key(struct World * world, struct WinMeta * win_meta); +extern void mod_selected_keyb(struct World * world, struct KeyBiData * kbd); -/* Move selection in keybinding window upwards ("dir" = "u") or downwards ("dir" - * = "d") within the limits of the keybindings list length. +/* Move keybinding modification selection upwards ("dir"=="u") or downwards + * ("dir"=="d") within the limits of the keybindings chain length. */ -extern void move_keys_mod_selection(struct World * world, char dir); +extern void move_keyb_mod_selection(struct KeyBiData * kbd, char dir); diff --git a/src/main.c b/src/main.c index a9d22f2..457aae5 100644 --- a/src/main.c +++ b/src/main.c @@ -10,10 +10,6 @@ #include "windows.h" /* for structs WinMeta, Win, init_win(), init_win_meta(), * draw_all_wins() */ -#include "draw_wins.h" /* for draw_keys_win(), draw_map_win(), draw_info_win(), - * draw_log_win() - */ -#include "keybindings.h" /* for init_keybindings(), get_keycode_to_action() */ #include "readwrite.h" /* for [read/write]_uint[8/16/32][_bigendian](), * try_fopen(), try_fclose(), try_fclose_unlink_rename() */ @@ -30,8 +26,11 @@ */ #include "rrand.h" /* for rrand(), rrand_seed() */ #include "rexit.h" /* for exit_game(), exit_err() */ -#include "control.h" /* for meta_control() */ #include "command_db.h" /* for init_command_db() */ +#include "control.h" /* for *_control() */ +#include "keybindings.h" /* for init_keybindings(), + * get_available_keycode_to_action() + */ @@ -175,20 +174,22 @@ int main(int argc, char *argv[]) curs_set(0); keypad(screen, TRUE); raw(); - init_keybindings(&world); + init_keybindings(&world, "config/keybindings_global", &world.kb_global); + init_keybindings(&world, "config/keybindings_wingeom", &world.kb_wingeom); + init_keybindings(&world, "config/keybindings_winkeys", &world.kb_winkeys); set_cleanup_flag(CLEANUP_KEYBINDINGS); char * err_winmem = "Trouble with init_win_meta() in main ()."; exit_err(init_win_meta(screen, &world.wmeta), &world, err_winmem); set_cleanup_flag(CLEANUP_WIN_META); init_winconfs(&world); - set_cleanup_flag(CLEANUP_WINCONFS); init_wins(&world); - set_cleanup_flag(CLEANUP_WINS); + set_cleanup_flag(CLEANUP_WINCONFS); sorted_wintoggle(&world); err_winmem = "Trouble with draw_all_wins() in main()."; /* Replay mode. */ int key; + struct WinConf * wc; if (0 == world.interactive) { int action = 0; @@ -208,8 +209,14 @@ int main(int argc, char *argv[]) { draw_all_wins(world.wmeta); key = getch(); + wc = get_winconf_by_win(&world, world.wmeta->active); + if ( (1 == wc->view && wingeom_control(key, &world)) + || (2 == wc->view && winkeyb_control(key, &world))) + { + continue; + } if ( EOF != action - && key == get_keycode_to_action(world.keybindings, "wait")) + && key == get_available_keycode_to_action(&world, "wait")) { action = getc(file); if (EOF != action) @@ -233,10 +240,23 @@ int main(int argc, char *argv[]) save_game(&world); draw_all_wins(world.wmeta); key = getch(); - if (0 != player.hitpoints && 0 == player_control(key, &world)) + wc = get_winconf_by_win(&world, world.wmeta->active); + if (1 == wc->view && wingeom_control(key, &world)) { continue; } + else if (2 == wc->view && winkeyb_control(key, &world)) + { + continue; + } + + if ( (1 == wc->view && wingeom_control(key, &world)) + || (2 == wc->view && winkeyb_control(key, &world)) + || (0 != player.hitpoints && player_control(key, &world))) + { + continue; + } + if (meta_control(key, &world)) { exit_game(&world); diff --git a/src/main.h b/src/main.h index 792f294..b3ffc89 100644 --- a/src/main.h +++ b/src/main.h @@ -9,6 +9,7 @@ #include /* for uint32_t*/ +#include "keybindings.h" struct WinMeta; struct WinConf; struct Win; @@ -23,8 +24,9 @@ struct MonsterDef; struct World { char interactive; /* 1: playing; 0: record playback. */ - struct KeyBinding * keybindings; /* Pointer to the keybindings. */ - struct KeysWinData * keyswindata; /* Pointer to key edit window metadata. */ + struct KeyBiData kb_global; /* Global keybindings. */ + struct KeyBiData kb_wingeom; /* Window geometry config keybindings. */ + struct KeyBiData kb_winkeys; /* Window keybinding config keybindings.*/ uint32_t seed; /* Randomness seed. */ uint32_t turn; /* Current game turn. */ uint16_t score; /* Player's score. */ diff --git a/src/misc.h b/src/misc.h index 5101e47..782a6fa 100644 --- a/src/misc.h +++ b/src/misc.h @@ -44,11 +44,11 @@ extern void update_log(struct World * world, char * text); -/* Return the offset necessary to center "map" on position "pos" in a frame of - * "framesize. +/* Return the offset necessary to center a map of "mapsize" on position "pos" in + * a frame of "framesize. */ -extern uint16_t center_offset(uint16_t pos, uint16_t mapsize, - uint16_t framesize); +extern uint16_t center_offset(uint16_t pos, + uint16_t mapsize, uint16_t framesize); diff --git a/src/rexit.c b/src/rexit.c index 01c5727..e35e8a1 100644 --- a/src/rexit.c +++ b/src/rexit.c @@ -8,11 +8,11 @@ #include /* for errno */ #include "main.h" /* for World struct */ #include "map.h" /* for Map struct */ -#include "keybindings.h" /* for KeysWinData, KeyBinding structs */ +#include "keybindings.h" /* for free_keybindings() */ #include "command_db.h" /* for free_command_db() */ #include "windows.h" /* for Win struct, free_win(), free_winmeta() */ #include "map_objects.h" /* for free_item_defs(), free_monster_defs() */ -#include "wincontrol.h" /* for get_win_by_id(), free_winconfs(), free_wins() */ +#include "wincontrol.h" /* for free_winconfs() */ /* The clean-up routine and the flag resource by which it decides what to do. */ @@ -27,24 +27,15 @@ static void cleanup(struct World * world) { endwin(); } - if (cleanup_flags & CLEANUP_MAP) + if (cleanup_flags & CLEANUP_MAP_OBJECTS) { - free(world->map->cells); + free_items(world->item); + free_monsters(world->monster); } - if (cleanup_flags & CLEANUP_KEYBINDINGS) + if (cleanup_flags & CLEANUP_MAP_OBJECT_DEFS) { -/* - uint16_t i = 0; - struct KeyBinding * kb_p = world->keybindings; - while (1) - { - free(kb_p); - free(world->keybindings[key].name); - } - free(world->keybindings); -*/ - free_keybindings(world->keybindings); - free(world->keyswindata); + free_item_defs(world->item_def); + free_monster_defs(world->monster_def); } if (cleanup_flags & CLEANUP_LOG) { @@ -54,28 +45,24 @@ static void cleanup(struct World * world) { free_command_db(world); } - if (cleanup_flags & CLEANUP_MAP_OBJECTS) + if (cleanup_flags & CLEANUP_MAP) { - free_items(world->item); - free_monsters(world->monster); + free(world->map->cells); } - if (cleanup_flags & CLEANUP_MAP_OBJECT_DEFS) + if (cleanup_flags & CLEANUP_KEYBINDINGS) { - free_item_defs(world->item_def); - free_monster_defs(world->monster_def); + free_keybindings(world->kb_global.kbs); + free_keybindings(world->kb_wingeom.kbs); + free_keybindings(world->kb_winkeys.kbs); } - if (cleanup_flags & CLEANUP_WINS) + if (cleanup_flags & CLEANUP_WIN_META) { - free_wins(world); + free_winmeta(world->wmeta); } if (cleanup_flags & CLEANUP_WINCONFS) { free_winconfs(world); } - if (cleanup_flags & CLEANUP_WIN_META) - { - free_winmeta(world->wmeta); - } } diff --git a/src/rexit.h b/src/rexit.h index 459fd29..4738844 100644 --- a/src/rexit.h +++ b/src/rexit.h @@ -11,7 +11,6 @@ #include /* for uint8_t */ struct World; -struct Map; @@ -29,8 +28,7 @@ enum cleanup_flag CLEANUP_MAP_OBJECTS = 0x0020, CLEANUP_MAP_OBJECT_DEFS = 0x0040, CLEANUP_WIN_META = 0x0080, - CLEANUP_WINCONFS = 0x0100, - CLEANUP_WINS = 0x0200 + CLEANUP_WINCONFS = 0x0100 }; extern void set_cleanup_flag(enum cleanup_flag flag); diff --git a/src/wincontrol.c b/src/wincontrol.c index c88c56b..6095d36 100644 --- a/src/wincontrol.c +++ b/src/wincontrol.c @@ -15,13 +15,17 @@ * try_fgets(), try_fclose_unlink_rename(), try_fwrite() */ #include "rexit.h" /* for exit_err() */ -#include "main.h" /* for World, Wins structs */ -#include "draw_wins.h" /* for draw_keys_win(), draw_info_win(), draw_log_win(), - * draw_map_win +#include "main.h" /* for World struct */ +#include "draw_wins.h" /* for draw_win_map(), draw_win_info(), draw_win_og(), + * draw_win_keybindings_global(), + * draw_win_keybindings_winconf_geometry(), + * draw_win_keybindings_winconf_keybindings(), + * draw_winconf_geometry(), draw_winconf_keybindings() */ #include "misc.h" /* for try_malloc() */ #include "dirent.h" /* for opendir(), closedir(), readdir() */ #include "errno.h" /* for errno */ +#include "keybindings.h" /* for KeyBinding struct, free_keybindings() */ @@ -31,7 +35,7 @@ static char * string_prefixed_id(struct World * world, char * prefix, char id); /* Create Winconf, init ->view/height_type/width_type to 0, ->id to "id". */ -static void create_winconf(char id, struct WinConf * wcp); +static void create_winconf(struct World * world, char id, struct WinConf * wcp); /* Initialize Winconf of "id" from appropriate config file.*/ static void init_winconf_from_file(struct World * world, char id); @@ -42,12 +46,15 @@ static void init_win_from_winconf(struct World * world, char id); /* Save title, draw function, size of window identified by "id" to conffile. */ static void save_win_config(struct World * world, char id); +/* Free data pointed to inside WinConf struct. */ +static void free_winconf_data(struct World * world, char id); -/* Write size of a window to its WinConf, as positive or negative values + +/* Write geometry of a window to its WinConf, as positive or negative values * (dependent on state ofWinConf->height_type / WinConf->width_type). */ -static void set_winconf(struct World * world, char id); +static void set_winconf_geometry(struct World * world, char id); @@ -73,12 +80,14 @@ static char * string_prefixed_id(struct World * world, char * prefix, char id) -static void create_winconf(char id, struct WinConf * wcp) +static void create_winconf(struct World * world, char id, struct WinConf * wcp) { wcp->id = id; wcp->view = 0; wcp->height_type = 0; wcp->width_type = 0; + wcp->kb.edit = 0; + wcp->kb.select = 0; } @@ -119,6 +128,27 @@ static void init_winconf_from_file(struct World * world, char id) winconf->width_type = 1; } + char command[linemax + 1]; + char * cmdptr; + struct KeyBinding ** loc_last_ptr = &winconf->kb.kbs; + * loc_last_ptr = 0; + while (fgets(command, linemax + 1, file)) + { + if ('\n' == command[0] || 0 == command[0]) + { + break; + } + * loc_last_ptr = try_malloc(sizeof(struct KeyBinding), world, context); + struct KeyBinding * kb_p = * loc_last_ptr; + kb_p->next = 0; + kb_p->key = atoi(command); + cmdptr = strchr(command, ' ') + 1; + kb_p->name = try_malloc(strlen(cmdptr), world, context); + memcpy(kb_p->name, cmdptr, strlen(cmdptr) - 1); + kb_p->name[strlen(cmdptr) - 1] = '\0'; + loc_last_ptr = & kb_p->next; + } + try_fclose(file, world, context); free(context); } @@ -165,6 +195,27 @@ extern void save_win_config(struct World * world, char id) sprintf(line, "%d\n", wc->width); try_fwrite(line, sizeof(char), strlen(line), file, world, f_name); + uint16_t linemax = 0; + struct KeyBinding * kb_p = wc->kb.kbs; + while (0 != kb_p) + { + if (strlen(kb_p->name) > linemax) + { + linemax = strlen(kb_p->name); + } + kb_p = kb_p->next; + } + linemax = linemax + 6; /* + 6 = + 3 digits + whitespace + \n + \0 */ + + char keyb_line[linemax]; + kb_p = wc->kb.kbs; + while (0 != kb_p) + { + snprintf(keyb_line, linemax, "%d %s\n", kb_p->key, kb_p->name); + try_fwrite(keyb_line, sizeof(char), strlen(keyb_line), file, world, f_name); + kb_p = kb_p->next; + } + char * path = string_prefixed_id(world, "config/windows/Win_", id); try_fclose_unlink_rename(file, path_tmp, path, world, f_name); free(path); @@ -173,7 +224,17 @@ extern void save_win_config(struct World * world, char id) -static void set_winconf(struct World * world, char id) +static void free_winconf_data(struct World * world, char id) +{ + struct WinConf * wc = get_winconf_by_id(world, id); + free(wc->title); + free_keybindings(wc->kb.kbs); + free_win(wc->win); +} + + + +static void set_winconf_geometry(struct World * world, char id) { struct WinConf * wcp = get_winconf_by_id(world, id); if (0 == wcp->height_type) @@ -216,19 +277,27 @@ static void * get_drawfunc_by_char(char c) { if ('i' == c) { - return draw_info_win; - } - else if ('k' == c) - { - return draw_keys_win; + return draw_win_info; } else if ('l' == c) { - return draw_log_win; + return draw_win_log; } else if ('m' == c) { - return draw_map_win; + return draw_win_map; + } + else if ('0' == c) + { + return draw_win_keybindings_global; + } + else if ('1' == c) + { + return draw_win_keybindings_winconf_geometry; + } + else if ('2' == c) + { + return draw_win_keybindings_winconf_keybindings; } return NULL; } @@ -313,7 +382,7 @@ extern void init_winconfs(struct World * world) i = 0; while (0 != (id = get_next_winconf_id(world))) { - create_winconf(id, &winconfs[i]); + create_winconf(world, id, &winconfs[i]); i++; } world->winconfs = winconfs; @@ -326,20 +395,12 @@ extern void init_winconfs(struct World * world) -extern void free_winconf(struct World * world, char id) -{ - struct WinConf * wc = get_winconf_by_id(world, id); - free(wc->title); -} - - - extern void free_winconfs(struct World * world) { char id; while (0 != (id = get_next_winconf_id(world))) { - free_winconf(world, id); + free_winconf_data(world, id); } free(world->winconf_ids); free(world->winconfs); @@ -358,17 +419,6 @@ extern void init_wins(struct World * world) -extern void free_wins(struct World * world) -{ - char id; - while (0 != (id = get_next_winconf_id(world))) - { - free_win(get_win_by_id(world, id)); - } -} - - - extern void sorted_wintoggle(struct World * world) { char * f_name = "sorted_wintoggle()"; @@ -397,7 +447,6 @@ extern void reload_win_config(struct World * world) { suspend_win(world->wmeta, world->wmeta->active); } - free_wins(world); free_winconfs(world); init_winconfs(world); init_wins(world); @@ -455,11 +504,16 @@ extern uint8_t toggle_window(struct WinMeta * win_meta, struct Win * win) extern void toggle_winconfig(struct World * world, struct Win * win) { struct WinConf * wcp = get_winconf_by_win(world, win); - if (0 == wcp->view) + if (0 == wcp->view) { - win->draw = draw_winconf; + win->draw = draw_winconf_geometry; wcp->view = 1; } + else if (1 == wcp->view) + { + win->draw = draw_winconf_keybindings; + wcp->view = 2; + } else { win->draw = get_drawfunc_by_char(wcp->draw); @@ -480,7 +534,7 @@ extern void toggle_win_height_type(struct World * world, struct Win * win) { wcp->height_type = 0; } - set_winconf(world, wcp->id); + set_winconf_geometry(world, wcp->id); } @@ -497,7 +551,7 @@ extern void toggle_win_width_type(struct World * world, struct Win * win) { wcp->width_type = 0; } - set_winconf(world, wcp->id); + set_winconf_geometry(world, wcp->id); } @@ -545,7 +599,7 @@ extern uint8_t growshrink_active_window(struct World * world, char change) { wcp->width_type = 0; } - set_winconf(world, wcp->id); + set_winconf_geometry(world, wcp->id); return x; } return 0; diff --git a/src/wincontrol.h b/src/wincontrol.h index e783160..79f895a 100644 --- a/src/wincontrol.h +++ b/src/wincontrol.h @@ -10,14 +10,15 @@ #include /* for uint8_t, int16_t */ +#include "keybindings.h" /* for KeyBiData struct */ struct Win; struct WinMeta; struct World; -/* Stores designated configuration of a window pointed to in it, and data used - * to manipulate said window in the "window configuration" view of it. +/* Stores a window's configuration (like geometry, keybindings) and a pointer to + * the respective Win struct itself. */ struct WinConf { @@ -32,6 +33,7 @@ struct WinConf uint8_t view; /* 0: use ->draw as Win->_draw; 1: use draw_winconf()*/ uint8_t height_type; /* both: 0: interpret ->height/->width as size in */ uint8_t width_type; /* positive cells; 1: as negative diff to max width */ + struct KeyBiData kb; /* the window's specific keybindings */ }; @@ -43,11 +45,10 @@ extern struct Win * get_win_by_id(struct World * world, char id); -/* Create/initialize (from config files)/free Winconf / Win structs. */ +/* Create/initialize (from config files)/free Winconf structs. */ extern void init_winconfs(struct World * world); extern void free_winconfs(struct World * world); extern void init_wins(struct World * world); -extern void free_wins(struct World * world); diff --git a/src/windows.h b/src/windows.h index f5f4056..9f1b02b 100644 --- a/src/windows.h +++ b/src/windows.h @@ -177,7 +177,8 @@ extern uint8_t draw_all_wins(struct WinMeta * wmeta); * further into a certain direction) into "frame" at position "pos" (describing * a column or a row dependent on "dir" being *either* "<"/">" *or* something * else). It will consist of a line of "dir" symbols bracketing a descriptive - * text stating the number of rows/columns further available beyond the hint. + * text stating "dist" as the number of rows/columns further available beyond + * the hint. */ extern uint8_t draw_scroll_hint(struct Frame * frame, uint16_t pos, uint32_t dist, char dir);