forked from cataclysmbnteam/Cataclysm-BN
-
Notifications
You must be signed in to change notification settings - Fork 0
/
output.h
1007 lines (911 loc) · 40.1 KB
/
output.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#pragma once
#ifndef CATA_SRC_OUTPUT_H
#define CATA_SRC_OUTPUT_H
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <forward_list>
#include <functional>
#include <iterator>
#include <stack>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include "catacharset.h"
#include "color.h"
#include "debug.h"
#include "enums.h"
#include "line.h"
#include "point.h"
#include "string_formatter.h"
#include "translations.h"
#include "units.h"
struct input_event;
struct iteminfo;
namespace catacurses
{
class window;
using chtype = int;
} // namespace catacurses
// LINE_NESW - X for on, O for off
#define LINE_XOXO 4194424 // '|' Vertical line. ncurses: ACS_VLINE; Unicode: U+2502
#define LINE_OXOX 4194417 // '-' Horizontal line. ncurses: ACS_HLINE; Unicode: U+2500
#define LINE_XXOO 4194413 // '|_' Lower left corner. ncurses: ACS_LLCORNER; Unicode: U+2514
#define LINE_OXXO 4194412 // '|^' Upper left corner. ncurses: ACS_ULCORNER; Unicode: U+250C
#define LINE_OOXX 4194411 // '^|' Upper right corner. ncurses: ACS_URCORNER; Unicode: U+2510
#define LINE_XOOX 4194410 // '_|' Lower right corner. ncurses: ACS_LRCORNER; Unicode: U+2518
#define LINE_XXXO 4194420 // '|-' Tee pointing right. ncurses: ACS_LTEE; Unicode: U+251C
#define LINE_XXOX 4194422 // '_|_' Tee pointing up. ncurses: ACS_BTEE; Unicode: U+2534
#define LINE_XOXX 4194421 // '-|' Tee pointing left. ncurses: ACS_RTEE; Unicode: U+2524
#define LINE_OXXX 4194423 // '^|^' Tee pointing down. ncurses: ACS_TTEE; Unicode: U+252C
#define LINE_XXXX 4194414 // '-|-' Large Plus or cross over. ncurses: ACS_PLUS; Unicode: U+253C
#define LINE_XOXO_C 0xa0
#define LINE_OXOX_C 0xa1
#define LINE_XXOO_C 0xa2
#define LINE_OXXO_C 0xa3
#define LINE_OOXX_C 0xa4
#define LINE_XOOX_C 0xa5
#define LINE_XXXO_C 0xa6
#define LINE_XXOX_C 0xa7
#define LINE_XOXX_C 0xa8
#define LINE_OXXX_C 0xa9
#define LINE_XXXX_C 0xaa
#define LINE_XOXO_S "│" // '|' Vertical line. ncurses: ACS_VLINE; Unicode: U+2502
#define LINE_OXOX_S "─" // '-' Horizontal line. ncurses: ACS_HLINE; Unicode: U+2500
#define LINE_XXOO_S "└" // '|_' Lower left corner. ncurses: ACS_LLCORNER; Unicode: U+2514
#define LINE_OXXO_S "┌" // '|^' Upper left corner. ncurses: ACS_ULCORNER; Unicode: U+250C
#define LINE_OOXX_S "┐" // '^|' Upper right corner. ncurses: ACS_URCORNER; Unicode: U+2510
#define LINE_XOOX_S "┘" // '_|' Lower right corner. ncurses: ACS_LRCORNER; Unicode: U+2518
#define LINE_XXXO_S "├" // '|-' Tee pointing right. ncurses: ACS_LTEE; Unicode: U+251C
#define LINE_XXOX_S "┴" // '_|_' Tee pointing up. ncurses: ACS_BTEE; Unicode: U+2534
#define LINE_XOXX_S "┤" // '-|' Tee pointing left. ncurses: ACS_RTEE; Unicode: U+2524
#define LINE_OXXX_S "┬" // '^|^' Tee pointing down. ncurses: ACS_TTEE; Unicode: U+252C
#define LINE_XXXX_S "┼" // '-|-' Large Plus or cross over. ncurses: ACS_PLUS; Unicode: U+253C
#define LINE_XOXO_UNICODE 0x2502
#define LINE_OXOX_UNICODE 0x2500
#define LINE_XXOO_UNICODE 0x2514
#define LINE_OXXO_UNICODE 0x250C
#define LINE_OOXX_UNICODE 0x2510
#define LINE_XOOX_UNICODE 0x2518
#define LINE_XXXO_UNICODE 0x251C
#define LINE_XXOX_UNICODE 0x2534
#define LINE_XOXX_UNICODE 0x2524
#define LINE_OXXX_UNICODE 0x252C
#define LINE_XXXX_UNICODE 0x253C
// Supports line drawing
std::string string_from_int( const catacurses::chtype ch );
// a consistent border color
#define BORDER_COLOR c_light_gray
// Display data
extern int TERMX; // width available for display
extern int TERMY; // height available for display
extern int POSX; // X position of '@' inside terrain window
extern int POSY; // Y position of '@' inside terrain window
extern int TERRAIN_WINDOW_WIDTH; // width of terrain window
extern int TERRAIN_WINDOW_HEIGHT; // height of terrain window
extern int TERRAIN_WINDOW_TERM_WIDTH; // width of terrain window in terminal characters
extern int TERRAIN_WINDOW_TERM_HEIGHT; // same for height
extern int FULL_SCREEN_WIDTH; // width of "full screen" popups
extern int FULL_SCREEN_HEIGHT; // height of "full screen" popups
extern int OVERMAP_WINDOW_WIDTH; // width of overmap window
extern int OVERMAP_WINDOW_HEIGHT; // height of overmap window
extern int OVERMAP_WINDOW_TERM_WIDTH; // width of the overmap window in terminal characters
extern int OVERMAP_WINDOW_TERM_HEIGHT; // same for height
extern int OVERMAP_LEGEND_WIDTH; // width of overmap window legend
nc_color msgtype_to_color( game_message_type type, bool bOldMsg = false );
/**
* @anchor color_tags
* @name color tags
*
* Most print function have only one color parameter (or none at all), therefor they would
* print the whole text in one color. To print some parts of a text in a different color,
* one would have to write separate calls to the print functions.
*
* Color tags allow embedding coloring instructions directly into the text, which allows
* a single call to the print function with the full text. The color tags are removed
* (not printed), but the text inside the tags is printed with a specific color.
*
* Example: Print "You need a tool to do this." in white and the word "tool" in red.
* \code
* wprintz( w, c_white, "You need a " );
* wprintz( w, c_red, "tool" );
* wprintz( w, c_white, " to do this." );
* \endcode
* Same code with color tags:
* \code
* print_colored_text( w, c_white, "You need a <color_red>tool</color> to do this." );
* \endcode
*
* Color tags must appear in pairs, first `<color_XXX>`, followed by text, followed by `</color>`.
* The text in between is colored according to the color `XXX`. `XXX` must be a valid color name,
* see @ref color_from_string. Color tags do *not* stack, the text inside the color tags should
* not contain any other color tags.
*
* Functions that handle color tags should contain a note about this in their documentation. If
* they have no such note, they probably don't handle color tags (which means they just print the
* string as is).
*
* Note: use @ref colorize to add color tags to a string.
* \code
* nc_color color = ...;
* text = colorize( "some text", color );
* \endcode
*
* One can use @ref utf8_width with the second parameter set to `true` to determine the printed
* length of a string containing color tags. The parameter instructs `utf8_width` to ignore the
* color tags. For example `utf8_width("<color_red>text</color>")` would return 23, but
* `utf8_width("<color_red>text</color>", true)` returns 4 (the length of "text").
*/
/*@{*/
/**
* Removes the prefix starting at the first occurrence of c1 until the first occurrence of c2
*/
std::string rm_prefix( std::string str, char c1 = '<', char c2 = '>' );
/**
* Adds the color represented by the next color tag found in the string to the top of the stack.
* If color_error == report_color_error::yes a debugmsg will be shown when the tag is not valid.
*/
color_tag_parse_result::tag_type update_color_stack(
std::stack<nc_color> &color_stack, const std::string &seg,
report_color_error color_error = report_color_error::yes );
/**
* Removes the color tags from the input string. This might be required when the string is to
* be used for functions that don't handle color tags.
*/
std::string remove_color_tags( const std::string &s );
/*@}*/
/**
* Split the input text into separate lines and wrap long lines. Each resulting line is at most
* `width` console cells long.
* The functions handles @ref color_tags. Color tags are added to the resulting lines so each
* line can be independently printed.
* @return A vector of lines, it may contain empty strings. Each entry is at most `width`
* console cells width.
*/
std::vector<std::string> foldstring( const std::string &str, int width, char split = ' ' );
/**
* Print text with embedded @ref color_tags, x, y are in curses system.
* The text is not word wrapped, but may automatically be wrapped on new line characters or
* when it reaches the border of the window (both is done by the curses system).
* If the text contains no color tags, it's equivalent to a simple mvprintz.
*
* @param w Window we are drawing in
* @param p Curses-style coordinates to print text at.
* @param text The text to print.
* @param cur_color The current color (could have been set by a previously encountered color tag),
* change to a color according to the color tags that are in the text.
* @param base_color Base color that is used outside of any color tag.
**/
void print_colored_text( const catacurses::window &w, point p, nc_color &cur_color,
const nc_color &base_color, const std::string &text,
report_color_error color_error = report_color_error::yes );
/**
* Print word wrapped text (with @ref color_tags) into the window.
*
* @param w Window we are printing in
* @param begin_line Line in the word wrapped text that is printed first (lines before that are not printed at all).
* @param text Text to print
* @param base_color Color used outside of any color tags.
* @param scroll_msg Optional, can be empty. If not empty and the text does not fit the window, the string is printed
* on the last line (in light green), it should show how to scroll the text.
* @return The maximal scrollable offset ([number of lines to be printed] - [lines available in the window]).
* This allows the caller to restrict the begin_line number on future calls / when modified by the user.
*/
int print_scrollable( const catacurses::window &w, int begin_line, const std::string &text,
const nc_color &base_color, const std::string &scroll_msg );
/**
* Fold and print text in the given window. The function handles @ref color_tags and
* uses them while printing.
*
* @param w Window we are printing in
* @param begin The (row, column) index on which to start.
* @param width The width used to fold the text (see @ref foldstring). `width + begin_y` should be
* less than the window width, otherwise the lines will be wrapped by the curses system, which
* defeats the purpose of using `foldstring`.
* @param base_color The initially used color. This can be overridden using color tags.
* @param text Actual message to print
* @param split Character after string is folded
* @return The number of lines of the formatted text (after folding). This may be larger than
* the height of the window.
*/
int fold_and_print( const catacurses::window &w, point begin, int width,
const nc_color &base_color, const std::string &text, char split = ' ' );
/**
* Same as other @ref fold_and_print, but does string formatting via @ref string_format.
*/
template<typename ...Args>
inline int fold_and_print( const catacurses::window &w, point begin,
const int width, const nc_color &base_color,
const char *const mes, Args &&... args )
{
return fold_and_print( w, begin, width, base_color, string_format( mes,
std::forward<Args>( args )... ) );
}
/**
* Like @ref fold_and_print, but starts the output with the N-th line of the folded string.
* This can be used for scrolling large texts. Parameters have the same meaning as for
* @ref fold_and_print, the function therefor handles @ref color_tags correctly.
*
* @param w Window we are printing in
* @param begin The (row,column) index on which to start.
* @param width The width used to fold the text (see @ref foldstring). `width + begin_y` should be
* @param begin_line The index of the first line (of the folded string) that is to be printed.
* The function basically removes all lines before this one and prints the remaining lines
* with `fold_and_print`.
* @param base_color The initially used color. This can be overridden using color tags.
* @param text Actual message to print
* @return Same as `fold_and_print`: the number of lines of the text (after folding). This is
* always the same value, regardless of `begin_line`, it can be used to determine the maximal
* value for `begin_line`.
*/
int fold_and_print_from( const catacurses::window &w, point begin, int width,
int begin_line, const nc_color &base_color, const std::string &text );
/**
* Same as other @ref fold_and_print_from, but does formatting via @ref string_format.
*/
template<typename ...Args>
inline int fold_and_print_from( const catacurses::window &w, point begin,
const int width, const int begin_line, const nc_color &base_color,
const char *const mes, Args &&... args )
{
return fold_and_print_from( w, begin, width, begin_line, base_color,
string_format( mes, std::forward<Args>( args )... ) );
}
/**
* Prints a single line of text. The text is automatically trimmed to fit into the given
* width. The function handles @ref color_tags correctly.
*
* @param w Window we are printing in
* @param begin The coordinates of line start (curses coordinates)
* @param width Maximal width of the printed line, if the text is longer, it is cut off.
* @param base_color The initially used color. This can be overridden using color tags.
* @param text Actual message to print
*/
void trim_and_print( const catacurses::window &w, point begin, int width,
const nc_color &base_color, const std::string &text,
report_color_error color_error = report_color_error::yes );
std::string trim_by_length( const std::string &text, int width );
template<typename ...Args>
inline void trim_and_print( const catacurses::window &w, point begin,
const int width, const nc_color &base_color,
const char *const mes, Args &&... args )
{
return trim_and_print( w, begin, width, base_color,
string_format( mes, std::forward<Args>( args )... ) );
}
template<typename ...Args>
inline void trim_and_print( const catacurses::window &w, point begin,
const int width, const nc_color &base_color,
const report_color_error color_error,
const char *const mes, Args &&... args )
{
return trim_and_print( w, begin, width, base_color,
string_format( mes, std::forward<Args>( args )... ),
color_error );
}
void center_print( const catacurses::window &w, int y, const nc_color &FG,
const std::string &text );
int right_print( const catacurses::window &w, int line, int right_indent,
const nc_color &FG, const std::string &text );
void insert_table( const catacurses::window &w, int pad, int line, int columns,
const nc_color &FG, const std::string ÷r, bool r_align,
const std::vector<std::string> &data );
void scrollable_text( const std::function<catacurses::window()> &init_window,
const std::string &title, const std::string &text );
std::string name_and_value( const std::string &name, int value, int field_width );
std::string name_and_value( const std::string &name, const std::string &value, int field_width );
void wputch( const catacurses::window &w, nc_color FG, int ch );
// Using int ch is deprecated, use an UTF-8 encoded string instead
void mvwputch( const catacurses::window &w, point p, nc_color FG, int ch );
void mvwputch( const catacurses::window &w, point p, nc_color FG, const std::string &ch );
// Using int ch is deprecated, use an UTF-8 encoded string instead
void mvwputch_inv( const catacurses::window &w, point p, nc_color FG, int ch );
void mvwputch_inv( const catacurses::window &w, point p, nc_color FG,
const std::string &ch );
// Using int ch is deprecated, use an UTF-8 encoded string instead
void mvwputch_hi( const catacurses::window &w, point p, nc_color FG, int ch );
void mvwputch_hi( const catacurses::window &w, point p, nc_color FG, const std::string &ch );
void mvwprintz( const catacurses::window &w, point p, const nc_color &FG,
const std::string &text );
template<typename ...Args>
inline void mvwprintz( const catacurses::window &w, point p, const nc_color &FG,
const char *const mes, Args &&... args )
{
mvwprintz( w, p, FG, string_format( mes, std::forward<Args>( args )... ) );
}
void wprintz( const catacurses::window &w, const nc_color &FG, const std::string &text );
template<typename ...Args>
inline void wprintz( const catacurses::window &w, const nc_color &FG, const char *const mes,
Args &&... args )
{
wprintz( w, FG, string_format( mes, std::forward<Args>( args )... ) );
}
void draw_custom_border(
const catacurses::window &w, catacurses::chtype ls = 1, catacurses::chtype rs = 1,
catacurses::chtype ts = 1, catacurses::chtype bs = 1, catacurses::chtype tl = 1,
catacurses::chtype tr = 1, catacurses::chtype bl = 1, catacurses::chtype br = 1,
nc_color FG = BORDER_COLOR, point pos = point_zero, int height = 0, int width = 0 );
void draw_border( const catacurses::window &w, nc_color border_color = BORDER_COLOR,
const std::string &title = "", nc_color title_color = c_light_red );
void draw_border_below_tabs( const catacurses::window &w, nc_color border_color = BORDER_COLOR );
class border_helper
{
public:
class border_info
{
public:
void set( point pos, point size );
// Prevent accidentally copying the return value from border_helper::add_border
border_info( const border_info & ) = delete;
border_info( border_info && ) = default;
border_info &operator=( const border_info & ) = delete;
border_info &operator=( border_info && ) = default;
friend class border_helper;
private:
border_info( border_helper &helper );
point pos;
point size;
std::reference_wrapper<border_helper> helper;
};
border_info &add_border();
void draw_border( const catacurses::window &win );
friend class border_info;
private:
struct border_connection {
bool top = false;
bool right = false;
bool bottom = false;
bool left = false;
int as_curses_line() const;
};
std::optional<std::map<point, border_connection>> border_connection_map;
std::forward_list<border_info> border_info_list;
};
std::string word_rewrap( const std::string &ins, int width, uint32_t split = ' ' );
std::vector<size_t> get_tag_positions( const std::string &s );
std::vector<std::string> split_by_color( const std::string &s );
bool query_yn( const std::string &text );
template<typename ...Args>
inline bool query_yn( const char *const msg, Args &&... args )
{
return query_yn( string_format( msg, std::forward<Args>( args )... ) );
}
bool query_int( int &result, int default_val, const std::string &text );
template<typename ...Args>
inline bool query_int( int &result, int default_val, const char *const msg, Args &&... args )
{
return query_int( result, default_val, string_format( msg, std::forward<Args>( args )... ) );
}
bool query_int( int &result, const std::string &text );
template<typename ...Args>
inline bool query_int( int &result, const char *const msg, Args &&... args )
{
return query_int( result, string_format( msg, std::forward<Args>( args )... ) );
}
std::vector<std::string> get_hotkeys( const std::string &s );
/**
* @name Popup windows
*
* Each function displays a popup (above all other windows) with the given (formatted)
* text. The popup function with the flags parameters does all the work, the other functions
* call it with specific flags. The function can be called with a bitwise combination of flags.
*
* The functions return the key (taken from @ref getch) that was entered by the user.
*
* The message is a printf-like string. It may contain @ref color_tags, which are used while printing.
*
* - PF_GET_KEY (ignored when combined with PF_NO_WAIT) cancels the popup on *any* user input.
* Without the flag the popup is only canceled when the user enters new-line, Space and Escape.
* This flag is passed by @ref popup_getkey.
* - PF_ON_TOP makes the window appear on the top of the screen (at the upper most row). Without
* this flag, the popup is centered on the screen.
* The flag is passed by @ref popup_top.
* - PF_FULLSCREEN makes the popup window as big as the whole screen.
* This flag is passed by @ref full_screen_popup.
* - PF_NONE is a placeholder for none of the above flags.
*
*/
/*@{*/
enum PopupFlags {
PF_NONE = 0,
PF_GET_KEY = 1 << 0,
PF_ON_TOP = 1 << 2,
PF_FULLSCREEN = 1 << 3,
};
template<typename ...Args>
inline int popup_getkey( const char *const mes, Args &&... args )
{
return popup( string_format( mes, std::forward<Args>( args )... ), PF_GET_KEY );
}
template<typename ...Args>
inline void popup_top( const char *const mes, Args &&... args )
{
popup( string_format( mes, std::forward<Args>( args )... ), PF_ON_TOP );
}
template<typename ...Args>
inline void popup( const char *mes, Args &&... args )
{
popup( string_format( mes, std::forward<Args>( args )... ), PF_NONE );
}
int popup( const std::string &text, PopupFlags flags = PF_NONE );
template<typename ...Args>
inline void full_screen_popup( const char *mes, Args &&... args )
{
popup( string_format( mes, std::forward<Args>( args )... ), PF_FULLSCREEN );
}
/*@}*/
std::string format_item_info( const std::vector<iteminfo> &item_display,
const std::vector<iteminfo> &item_compare );
// the extra data that item_info needs to draw
struct item_info_data {
private:
std::string item_name;
std::string type_name;
std::vector<iteminfo> item_display;
std::vector<iteminfo> item_compare;
int selected = 0;
public:
item_info_data();
~item_info_data();
item_info_data( const std::string &item_name, const std::string &type_name,
const std::vector<iteminfo> &item_display, const std::vector<iteminfo> &item_compare );
item_info_data( const std::string &item_name, const std::string &type_name,
const std::vector<iteminfo> &item_display, const std::vector<iteminfo> &item_compare,
int &ptr_selected );
const std::string &get_item_name() const {
return item_name;
}
const std::string &get_type_name() const {
return type_name;
}
const std::vector<iteminfo> &get_item_display() const {
return item_display;
}
const std::vector<iteminfo> &get_item_compare() const {
return item_compare;
}
int *ptr_selected = &selected;
bool without_getch = false;
bool without_border = false;
bool handle_scrolling = false;
bool any_input = true;
bool scrollbar_left = true;
bool use_full_win = false;
unsigned int padding = 1;
};
input_event draw_item_info( const catacurses::window &win, item_info_data &data );
input_event draw_item_info( int iLeft, int iWidth, int iTop, int iHeight, item_info_data &data );
input_event draw_item_info( const std::function<catacurses::window()> &init_window,
item_info_data &data );
enum class item_filter_type : int {
FIRST = 1, // used for indexing into tables
FILTER = 1,
LOW_PRIORITY = 2,
HIGH_PRIORITY = 3
};
/**
* Write some tips (such as precede items with - to exclude them) onto the window.
*
* @param win Window we are drawing in
* @param starty Where to start relative to the top of the window.
* @param height Every row from starty to starty + height - 1 will be cleared before printing the rules.
* @param type Filter to use when drawing
*/
void draw_item_filter_rules( const catacurses::window &win, int starty, int height,
item_filter_type type );
char rand_char();
int special_symbol( int sym );
size_t shortcut_print( const catacurses::window &w, point p, nc_color text_color,
nc_color shortcut_color, const std::string &fmt );
size_t shortcut_print( const catacurses::window &w, nc_color text_color, nc_color shortcut_color,
const std::string &fmt );
std::string shortcut_text( nc_color shortcut_color, const std::string &fmt );
/**
* @return Pair of a string containing the bar, and its color
* @param cur Current value being formatted
* @param max Maximum possible value, e.g. a full bar
* @param extra_resolution Double the resolution of displayed values with \ symbols.
* @param colors A vector containing N colors with which to color the bar at different values
*/
// The last color is used for an empty bar
// extra_resolution
std::pair<std::string, nc_color> get_bar( float cur, float max, int width = 5,
bool extra_resolution = true,
const std::vector<nc_color> &colors = { c_green, c_light_green, c_yellow, c_light_red, c_red } );
std::pair<std::string, nc_color> get_hp_bar( int cur_hp, int max_hp, bool is_mon = false );
std::pair<std::string, nc_color> get_stamina_bar( int cur_stam, int max_stam );
std::pair<std::string, nc_color> get_light_level( float light );
/**
* @return String containing the bar. Example: "Label [******** ]".
* @param val Value to display. Can be unclipped.
* @param width Width of the entire string.
* @param label Label before the bar. Can be empty.
* @param begin Iterator over pairs <double p, char c> (see below).
* @param end Iterator over pairs <double p, char c> (see below).
* Where:
* p - percentage of the entire bar which can be filled with c.
* c - character to fill the segment of the bar with
*/
// MSVC has problem dealing with template functions.
// Implementing this function in cpp file results link error.
template<typename RatingIterator>
inline std::string get_labeled_bar( const double val, const int width, const std::string &label,
RatingIterator begin, RatingIterator end )
{
std::string result;
result.reserve( width );
if( !label.empty() ) {
result += label;
result += ' ';
}
const int bar_width = width - utf8_width( result ) - 2; // - 2 for the brackets
result += '[';
if( bar_width > 0 ) {
int used_width = 0;
for( RatingIterator it( begin ); it != end; ++it ) {
const double factor = std::min( 1.0, std::max( 0.0, it->first * val ) );
const int seg_width = static_cast<int>( factor * bar_width ) - used_width;
if( seg_width <= 0 ) {
continue;
}
used_width += seg_width;
result.insert( result.end(), seg_width, it->second );
}
result.insert( result.end(), bar_width - used_width, ' ' );
}
result += ']';
return result;
}
enum class enumeration_conjunction {
none,
and_,
or_,
newline,
arrow
};
/**
* @return String containing enumerated elements in format: "a, b, c, ..., and z". Uses the Oxford comma.
* @param values A vector of strings
* @param conj Choose how to separate the last elements.
*/
template<typename _Container>
std::string enumerate_as_string( const _Container &values,
enumeration_conjunction conj = enumeration_conjunction::and_ )
{
const std::string final_separator = [&]() {
switch( conj ) {
case enumeration_conjunction::none:
return _( ", " );
case enumeration_conjunction::and_:
return ( values.size() > 2 ? _( ", and " ) : _( " and " ) );
case enumeration_conjunction::or_:
return ( values.size() > 2 ? _( ", or " ) : _( " or " ) );
case enumeration_conjunction::newline:
return "\n";
case enumeration_conjunction::arrow:
return _( " > " );
}
debugmsg( "Unexpected conjunction" );
return _( ", " );
}
();
const std::string separator = [&conj]() {
switch( conj ) {
case enumeration_conjunction::arrow:
return _( " > " );
default:
return _( ", " );
}
}
();
std::string res;
for( auto iter = values.begin(); iter != values.end(); ++iter ) {
if( iter != values.begin() ) {
if( conj == enumeration_conjunction::newline ) {
res += "\n";
} else if( std::next( iter ) == values.end() ) {
res += final_separator;
} else {
res += separator;
}
}
res += *iter;
}
return res;
}
/**
* @return String containing enumerated elements in format: "a, b, c, ..., and z". Uses the Oxford comma.
* @param first Iterator pointing to the first element.
* @param last Iterator pointing to the last element.
* @param string_for Function that accepts an element and returns a representing string.
* May return an empty string to omit the element.
* @param conj Choose how to separate the last elements.
*/
template<typename _FIter, typename F>
std::string enumerate_as_string( _FIter first, _FIter last, F string_for,
enumeration_conjunction conj = enumeration_conjunction::and_ )
{
std::vector<std::string> values;
values.reserve( static_cast<size_t>( std::distance( first, last ) ) );
for( _FIter iter = first; iter != last; ++iter ) {
const std::string str( string_for( *iter ) );
if( !str.empty() ) {
values.push_back( str );
}
}
return enumerate_as_string( values, conj );
}
/**
* @return String containing the bar. Example: "Label [******** ]".
* @param val Value to display. Can be unclipped.
* @param width Width of the entire string.
* @param label Label before the bar. Can be empty.
* @param c Character to fill the bar with.
*/
std::string get_labeled_bar( double val, int width, const std::string &label, char c );
void draw_tab( const catacurses::window &w, int iOffsetX, const std::string &sText,
bool bSelected );
void draw_subtab( const catacurses::window &w, int iOffsetX, const std::string &sText,
bool bSelected,
bool bDecorate = true, bool bDisabled = false );
// Draws multiple tabs, with the titles specified in tab_texts.
// Also draws the line beneath the tabs and corners at the ends.
// The selected tab (specified by current_tab) is drawn differently.
// In total, something like the following:
// ┌──────┐ ┌──────┐
// │ TAB1 │ │ TAB2 │
// ┌─┴──────┴─┘ └───────────┐
void draw_tabs( const catacurses::window &, const std::vector<std::string> &tab_texts,
size_t current_tab );
// As above, but specify current tab by its label rather than position
void draw_tabs( const catacurses::window &, const std::vector<std::string> &tab_texts,
const std::string ¤t_tab );
// This overload of draw_tabs is intended for use when you track the current
// tab via some other value (like an enum) linked to each tab. Expected use
// looks something like this:
//
// tab_mode current_tab = ...;
// const std::vector<std::pair<tab_mode, std::string>> tabs = {
// { tab_mode::first_tab, _( "FIRST_TAB" ) },
// { tab_mode::second_tab, _( "SECOND_TAB" ) },
// };
// draw_tabs( w, tabs, current_tab );
template<typename TabList, typename CurrentTab, typename = std::enable_if_t<
std::is_same<CurrentTab,
std::remove_const_t<typename TabList::value_type::first_type>>::value>>
void draw_tabs( const catacurses::window &w, const TabList &tab_list,
const CurrentTab ¤t_tab )
{
std::vector<std::string> tab_text;
std::transform( tab_list.begin(), tab_list.end(), std::back_inserter( tab_text ),
[]( const typename TabList::value_type & pair ) {
return pair.second;
} );
auto current_tab_it = std::find_if( tab_list.begin(), tab_list.end(),
[¤t_tab]( const typename TabList::value_type & pair ) {
return pair.first == current_tab;
} );
assert( current_tab_it != tab_list.end() );
draw_tabs( w, tab_text, std::distance( tab_list.begin(), current_tab_it ) );
}
// Similar to the above, but where the order of tabs is specified separately
// TabList is expected to be a map type.
template<typename TabList, typename TabKeys, typename CurrentTab, typename = std::enable_if_t<
std::is_same<CurrentTab,
std::remove_const_t<typename TabList::value_type::first_type>>::value>>
void draw_tabs( const catacurses::window &w, const TabList &tab_list, const TabKeys &keys,
const CurrentTab ¤t_tab )
{
std::vector<typename TabList::value_type> ordered_tab_list;
for( const auto &key : keys ) {
auto it = tab_list.find( key );
assert( it != tab_list.end() );
ordered_tab_list.push_back( *it );
}
draw_tabs( w, ordered_tab_list, current_tab );
}
// Legacy function, use class scrollbar instead!
void draw_scrollbar( const catacurses::window &window, int iCurrentLine,
int iContentHeight, int iNumLines, point offset = point_zero,
nc_color bar_color = c_white, bool bDoNotScrollToEnd = false );
void calcStartPos( int &iStartPos, int iCurrentLine, int iContentHeight,
int iNumEntries );
class scrollbar
{
public:
scrollbar();
// relative position of the scrollbar to the window
scrollbar &offset_x( int offx );
scrollbar &offset_y( int offy );
// total number of lines
scrollbar &content_size( int csize );
// index of the beginning line
scrollbar &viewport_pos( int vpos );
// number of lines shown
scrollbar &viewport_size( int vsize );
// window border color
scrollbar &border_color( nc_color border_c );
// scrollbar arrow color
scrollbar &arrow_color( nc_color arrow_c );
// scrollbar slot color
scrollbar &slot_color( nc_color slot_c );
// scrollbar bar color
scrollbar &bar_color( nc_color bar_c );
// can viewport_pos go beyond (content_size - viewport_size)?
scrollbar &scroll_to_last( bool scr2last );
// draw the scrollbar to the window
void apply( const catacurses::window &window );
private:
int offset_x_v, offset_y_v;
int content_size_v, viewport_pos_v, viewport_size_v;
nc_color border_color_v, arrow_color_v, slot_color_v, bar_color_v;
bool scroll_to_last_v;
};
// A simple scrolling view onto some text. Given a window, it will use the
// leftmost column for the scrollbar and fill the rest with text. When the
// scrollbar is not needed it prints a vertical border in place of it, so the
// expectation is that the given window will overlap the left edge of a
// bordered window if one exists.
// (Options to e.g. not print the border would be easy to add if needed).
// Update the text with set_text (it will be wrapped for you).
// scroll_up and scroll_down are expected to be called from handlers for the
// keys used for that purpose.
// Call draw when drawing related UI stuff. draw calls werase/wnoutrefresh for its
// window internally.
class scrolling_text_view
{
public:
scrolling_text_view( catacurses::window &w ) : w_( w ) {}
void set_text( const std::string & );
void scroll_up();
void scroll_down();
void page_up();
void page_down();
void draw( const nc_color &base_color );
private:
int text_width();
int num_lines();
int max_offset();
catacurses::window &w_;
std::vector<std::string> text_;
int offset_ = 0;
};
class scrollingcombattext
{
public:
enum : int { iMaxSteps = 8 };
scrollingcombattext() = default;
class cSCT
{
private:
point pos;
direction oDir;
direction oUp;
direction oUpRight;
direction oRight;
direction oDownRight;
direction oDown;
direction oDownLeft;
direction oLeft;
direction oUpLeft;
point dir;
int iStep;
int iStepOffset;
std::string sText;
game_message_type gmt;
std::string sText2;
game_message_type gmt2;
std::string sType;
bool iso_mode;
public:
cSCT( point pos, direction p_oDir,
const std::string &p_sText, game_message_type p_gmt,
const std::string &p_sText2 = "", game_message_type p_gmt2 = m_neutral,
const std::string &p_sType = "" );
int getStep() const {
return iStep;
}
int getStepOffset() const {
return iStepOffset;
}
int advanceStep() {
return ++iStep;
}
int advanceStepOffset() {
return ++iStepOffset;
}
int getPosX() const;
int getPosY() const;
direction getDirecton() const {
return oDir;
}
int getInitPosX() const {
return pos.x;
}
int getInitPosY() const {
return pos.y;
}
std::string getType() const {
return sType;
}
std::string getText( const std::string &type = "full" ) const;
game_message_type getMsgType( const std::string &type = "first" ) const;
};
std::vector<cSCT> vSCT;
void add( point pos, direction p_oDir,
const std::string &p_sText, game_message_type p_gmt,
const std::string &p_sText2 = "", game_message_type p_gmt2 = m_neutral,
const std::string &p_sType = "" );
void advanceAllSteps();
void removeCreatureHP();
};
extern scrollingcombattext SCT;
std::string format_volume( const units::volume &volume );
std::string format_volume( const units::volume &volume, int width, bool *out_truncated,
double *out_value );
inline std::string format_money( int cents )
{
return string_format( _( "$%.2f" ), cents / 100.0 );
}
/** Get the width in font glyphs of the drawing screen.
*
* May differ from OPTIONS["TERMINAL_X"], for instance in
* SDL FULLSCREEN mode, the user setting is overridden.
*/
int get_terminal_width();
/** Get the height in font glyphs of the drawing screen.
*
* May differ from OPTIONS["TERMINAL_Y"], for instance in
* SDL FULLSCREEN mode, the user setting is overridden.
*/
int get_terminal_height();
/**
* Check whether we're in tile drawing mode. The most important
* effect of this is that we don't need to draw to the ASCII
* window.
*
* Ideally, of course, we'd have a unified tile drawing and ASCII
* drawing API and use polymorphy, but for the time being there will
* be a lot of switching around in the map drawing code.
*/
bool is_draw_tiles_mode();
/**
* Make changes made to the display visible to the user immediately.
*
* In curses mode, this is a no-op. In SDL mode, this refreshes
* the real display from the backing buffer immediately, rather than
* delaying the update until the next time we are waiting for user input.
*/
void refresh_display();
/**
* Assigns a custom color to each symbol.
*
* @param str String to colorize symbols in
* @param color_of Function that accepts symbols (std::string::value_type) and returns colors.
* @return Colorized string.
*/
template<typename F>
std::string colorize_symbols( const std::string &str, F color_of )
{
std::string res;
nc_color prev_color = c_unset;
const auto closing_tag = [ &res, prev_color ]() {
if( prev_color != c_unset ) {
res += "</color>";
}
};
for( const auto &elem : str ) {
const nc_color new_color = color_of( elem );
if( prev_color != new_color ) {
closing_tag();
res += "<color_" + get_all_colors().get_name( new_color ) + ">";
prev_color = new_color;
}
res += elem;
}