1 /* vim:tw=78:ts=8:sw=4:set ft=c: */
3 Copyright (C) 2002-2006 Ben Kibbey <bjk@arbornet.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 void free_historydata(HISTORY
**history
, int idx
, int total
)
41 HISTORY
*h
= *history
;
44 for (i
= idx
; i
< total
; i
++) {
51 h
= Realloc(h
, (idx
) * sizeof(HISTORY
));
63 if ((fp
= fopen(config
.nagfile
, "r")) == NULL
) {
64 cmessage(ERROR
, ANYKEY
, "%s: %s", config
.nagfile
, strerror(errno
));
69 if (fscanf(fp
, " %[^\n] ", line
) == 1) {
70 nags
= Realloc(nags
, (i
+ 2) * sizeof(struct nag_s
));
71 nags
[i
].line
= strdup(line
);
81 static void view_nag(void *arg
)
85 char line
[LINE_MAX
] = {0};
88 snprintf(buf
, sizeof(buf
), "Viewing NAG for \"%s\"",
89 game
[gindex
].history
[idx
].move
);
96 for (i
= 0; i
< MAX_PGN_NAG
; i
++) {
97 if (!game
[gindex
].history
[idx
].nag
[i
])
100 strncat(line
, nags
[game
[gindex
].history
[idx
].nag
[i
] - 1].line
,
102 strncat(line
, "\n", sizeof(line
));
105 line
[strlen(line
) - 1] = 0;
106 message(buf
, ANYKEY
, "%s", line
);
110 void view_annotation(int idx
)
112 char buf
[MAX_PGN_MOVE_LEN
+ strlen(ANNOTATION_VIEW_TITLE
) + 4];
113 int nag
= 0, comment
= 0;
115 if (idx
< 0 || idx
> game
[gindex
].htotal
)
118 if (game
[gindex
].history
[idx
].comment
&&
119 game
[gindex
].history
[idx
].comment
[0])
122 if (game
[gindex
].history
[idx
].nag
[0])
125 if (!nag
&& !comment
)
128 snprintf(buf
, sizeof(buf
), "%s \"%s\"", ANNOTATION_VIEW_TITLE
,
129 game
[gindex
].history
[idx
].move
);
132 show_message(buf
, (nag
) ? "Any other key to continue" : ANYKEY
,
133 (nag
) ? "Press 'n' to view NAG" : NULL
,
134 (nag
) ? view_nag
: NULL
, (nag
) ? (void *)idx
: NULL
,
135 (nag
) ? 'n' : 0, "%s", game
[gindex
].history
[idx
].comment
);
137 show_message(buf
, "Any other key to continue", "Press 'n' to view NAG",
138 view_nag
, (void *)idx
, 'n', "%s",
139 "No annotations for this move");
144 int get_history_by_index(int n
, HISTORY
*h
)
146 if (n
< 0 || n
> game
[gindex
].htotal
- 1)
149 *h
= game
[gindex
].history
[n
];
155 game
[gindex
].hindex
= game
[gindex
].htotal
= 0;
159 char *history_edit_nag(void *arg
)
163 ITEM
**mitems
= NULL
;
177 mitems
= Realloc(mitems
, (i
+ 2) * sizeof(ITEM
));
178 mitems
[i
++] = new_item(NONE
, NULL
);
180 for (n
= 0; nags
[n
].line
; n
++, i
++) {
181 mitems
= Realloc(mitems
, (i
+ 2) * sizeof(ITEM
));
182 mitems
[i
] = new_item(nags
[n
].line
, NULL
);
186 menu
= new_menu(mitems
);
187 scale_menu(menu
, &rows
, &cols
);
189 win
= newwin(rows
+ 4, cols
+ 2, CALCPOSY(rows
) - 2, CALCPOSX(cols
));
190 set_menu_win(menu
, win
);
191 subw
= derwin(win
, rows
, cols
, 2, 1);
192 set_menu_sub(menu
, subw
);
193 set_menu_fore(menu
, A_REVERSE
);
194 set_menu_grey(menu
, A_NORMAL
);
195 set_menu_mark(menu
, NULL
);
196 set_menu_spacing(menu
, 0, 0, 0);
197 menu_opts_off(menu
, O_NONCYCLIC
|O_SHOWDESC
|O_ONEVALUE
);
199 panel
= new_panel(win
);
203 set_menu_pattern(menu
, mbuf
);
204 wbkgd(win
, CP_MESSAGE_WINDOW
);
205 draw_window_title(win
, NAG_EDIT_TITLE
, cols
+ 2, CP_HISTORY_TITLE
,
208 for (i
= 0; i
< MAX_PGN_NAG
; i
++) {
209 if (game
[gindex
].history
[idx
].nag
[i
] &&
210 game
[gindex
].history
[idx
].nag
[i
] <= item_count(menu
)) {
211 set_item_value(mitems
[game
[gindex
].history
[idx
].nag
[i
]], TRUE
);
212 set_current_item(menu
, mitems
[game
[gindex
].history
[idx
].nag
[i
]]);
222 wattron(win
, A_REVERSE
);
224 for (c
= 1; c
< (cols
+ 2) - 1; c
++)
225 mvwprintw(win
, rows
+ 2, c
, " ");
227 c
= item_index(current_item(menu
)) + 1;
229 snprintf(buf
, sizeof(buf
), "Item %i of %i (%i of %i selected) %s", c
,
230 item_count(menu
), itemcount
, MAX_PGN_NAG
, NAG_EDIT_PROMPT
);
231 draw_prompt(win
, rows
+ 2, cols
+ 2, buf
, CP_MESSAGE_PROMPT
);
233 wattroff(win
, A_REVERSE
);
236 for (i
= 0; mitems
[i
]; i
++)
237 set_item_value(mitems
[i
], FALSE
);
239 set_item_value(mitems
[0], TRUE
);
242 set_item_value(mitems
[0], FALSE
);
244 /* This nl() statement needs to be here because NL is recognized
245 * for some reason after the first selection.
257 help(NAG_EDIT_HELP
, ANYKEY
, naghelp
);
265 for (i
= item_index(current_item(menu
)) + 1; mitems
[i
]; i
++) {
266 if (item_value(mitems
[i
]) == TRUE
) {
273 for (i
= 0; mitems
[i
]; i
++) {
274 if (item_value(mitems
[i
]) == TRUE
) {
281 set_current_item(menu
, mitems
[found
]);
289 for (i
= item_index(current_item(menu
)) - 1; i
> 0; i
--) {
290 if (item_value(mitems
[i
]) == TRUE
) {
297 for (i
= item_count(menu
) - 1; i
> 0; i
--) {
298 if (item_value(mitems
[i
]) == TRUE
) {
305 set_current_item(menu
, mitems
[found
]);
308 menu_driver(menu
, REQ_FIRST_ITEM
);
311 menu_driver(menu
, REQ_LAST_ITEM
);
314 menu_driver(menu
, REQ_UP_ITEM
);
317 menu_driver(menu
, REQ_DOWN_ITEM
);
321 if (menu_driver(menu
, REQ_SCR_UPAGE
) == E_REQUEST_DENIED
)
322 menu_driver(menu
, REQ_FIRST_ITEM
);
326 if (menu_driver(menu
, REQ_SCR_DPAGE
) == E_REQUEST_DENIED
)
327 menu_driver(menu
, REQ_LAST_ITEM
);
330 if (item_index(current_item(menu
)) == 0 &&
331 item_value(current_item(menu
)) == FALSE
) {
336 if (item_value(current_item(menu
)) == TRUE
) {
337 set_item_value(current_item(menu
), FALSE
);
341 if (itemcount
+ 1 > MAX_PGN_NAG
)
344 set_item_value(current_item(menu
), TRUE
);
348 SET_FLAG(game
[gindex
].flags
, GF_MODIFIED
);
357 tmp
= menu_pattern(menu
);
359 if (tmp
&& tmp
[strlen(tmp
) - 1] != c
) {
360 menu_driver(menu
, REQ_CLEAR_PATTERN
);
361 menu_driver(menu
, c
);
364 if (menu_driver(menu
, REQ_NEXT_MATCH
) == E_NO_MATCH
)
365 menu_driver(menu
, c
);
373 for (i
= 0; i
< MAX_PGN_NAG
; i
++)
374 game
[gindex
].history
[idx
].nag
[i
] = 0;
376 for (i
= 0, n
= 0; mitems
[i
] && n
< MAX_PGN_NAG
; i
++) {
377 if (item_value(mitems
[i
]) == TRUE
)
378 game
[gindex
].history
[idx
].nag
[n
++] = i
;
387 for (i
= 0; mitems
[i
]; i
++)
388 free_item(mitems
[i
]);
397 void add_to_history(HISTORY
**h
, int *n
, int *t
, const char *str
)
399 HISTORY
*history
= *h
;
402 history
= Realloc(history
, (idx
+ 2) * sizeof(HISTORY
));
403 memset(&history
[idx
], 0, sizeof(HISTORY
));
404 strncpy(history
[idx
].move
, str
, sizeof(history
[idx
].move
));
405 memset(&history
[++idx
], 0, sizeof(HISTORY
));
412 void parse_history_move(BOARD b
, int idx
)
417 game
[gindex
].bcaptures
= game
[gindex
].wcaptures
= 0;
418 status
.turn
= game
[gindex
].openingside
;
420 if (TEST_FLAG(game
[gindex
].flags
, GF_PERROR
))
421 SET_FLAG(flags
, GF_PERROR
);
423 if (TEST_FLAG(game
[gindex
].flags
, GF_MODIFIED
))
424 SET_FLAG(flags
, GF_MODIFIED
);
426 if (TEST_FLAG(game
[gindex
].flags
, GF_DELETE
))
427 SET_FLAG(flags
, GF_DELETE
);
429 if (TEST_FLAG(game
[gindex
].flags
, GF_GAMEOVER
))
430 SET_FLAG(flags
, GF_GAMEOVER
);
432 game
[gindex
].flags
= flags
;
433 game
[gindex
].ply
= 0;
437 /* FIXME Move numbers and turns. */
438 if (game
[gindex
].fentag
)
439 parse_fen_line(b
, game
[gindex
].tag
[game
[gindex
].fentag
].value
);
441 for (i
= 0; i
< idx
; i
++) {
444 if (get_history_by_index(i
, &h
))
447 if (parse_move_text(b
, h
.move
)) {
448 cmessage(NULL
, ANYKEY
, "%s \"%s\"", E_INVALID_MOVE
, h
.move
);
455 if (!status
.notify
&& !status
.mode
== MODE_HISTORY
)
456 update_status_notify("%s", GAME_HELP_PROMPT
);
462 static void cursor_from_history(int idx
, int *r
, int *c
)
467 p
= game
[gindex
].history
[idx
].move
;
480 *r
= (status
.turn
== WHITE
) ? 8 : 1;
493 void history_previous(BOARD b
, int n
, int *r
, int *c
)
495 if (game
[gindex
].hindex
- n
< 0) {
496 if ((n
== 2 && movestep
== 2) || (n
== 1 && movestep
== 1))
497 game
[gindex
].hindex
= game
[gindex
].htotal
;
499 game
[gindex
].hindex
= 0;
502 game
[gindex
].hindex
-= n
;
504 cursor_from_history(game
[gindex
].hindex
, r
, c
);
505 parse_history_move(b
, game
[gindex
].hindex
);
509 void history_next(BOARD b
, int n
, int *r
, int *c
)
511 if (game
[gindex
].hindex
+ n
> game
[gindex
].htotal
) {
512 if ((n
== 2 && movestep
== 2) || (n
== 1 && movestep
== 1))
513 game
[gindex
].hindex
= 0;
515 game
[gindex
].hindex
= game
[gindex
].htotal
;
518 game
[gindex
].hindex
+= n
;
520 cursor_from_history(game
[gindex
].hindex
, r
, c
);
521 parse_history_move(b
, game
[gindex
].hindex
);
525 void init_history(BOARD b
)
527 status
.mode
= MODE_HISTORY
;
528 parse_history_move(b
, game
[gindex
].hindex
);
529 update_status_window();