home · contact · privacy
3eaf491a1a41c5d043f90bc077e1bd5dfee12862
[plomrogue] / draw_wins.c
1 #include <ncurses.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include "windows.h"
5 #include "roguelike.h"
6
7 void draw_with_linebreaks (struct Win * win, char * text, int start_y) {
8 // Write text into window content space. Start on row start_y. Fill unused rows with whitespace.
9   int x, y;
10   char toggle;
11   char fin = 0;
12   int z = -1;
13   for (y = start_y; y < win->height; y++) {
14     if (0 == fin)
15       toggle = 0;
16     for (x = 0; x < win->width; x++) {
17        if (0 == toggle) {
18          z++;
19          if ('\n' == text[z]) {
20            toggle = 1;
21            continue; }
22          else
23            mvwaddch(win->curses, y, x, text[z]);
24          if ('\n' == text[z+1]) {
25            z++;
26            toggle = 1; }
27          else if (0 == text[z+1]) {
28             toggle = 1;
29             fin = 1; } } } } }
30
31 void draw_text_from_bottom (struct Win * win, char * text) {
32 // Draw text from end/bottom to the top.
33   char toggle = 0;
34   int x, y, offset;
35   int z = -1;
36   for (y = 0; 0 == toggle; y++)                           // Determine number of lines text would have in
37     for (x = 0; x < win->width; x++) {                    // a window of available width, but infinite height.
38       z++;
39       if ('\n' == text[z])            // Treat \n and \0 as control characters for incrementing y and stopping
40         break;                        // the loop. Make sure they don't count as cell space themselves.
41       if ('\n' == text[z+1]) {
42         z++;
43         break; }
44       else if (0 == text[z+1]) {
45         toggle = 1;
46         break; } }
47   z = -1;
48   int start_y = 0;
49   if (y < win->height)             // Depending on what is bigger, determine start point in window or in text.
50     start_y = win->height - y;
51   else if (y > win->height) {
52     offset = y - win->height;
53     for (y = 0; y < offset; y++)
54       for (x = 0; x < win->width; x++) {
55         z++;
56         if ('\n' == text[z])
57           break;
58         if ('\n' == text[z+1]) {
59           z++;
60           break; } }
61     text = text + (sizeof(char) * (z + 1)); }
62   draw_with_linebreaks(win, text, start_y); }
63
64 void draw_log_win (struct Win * win) {
65 // Draw log text from world struct in win->data from bottom to top.
66   struct World * world = (struct World *) win->data;
67   draw_text_from_bottom(win, world->log); }
68
69 void draw_map_win (struct Win * win) {
70 // Draw map determined by win->data Map struct into window. Respect offset.
71   struct World * world = (struct World *) win->data;
72   struct Map * map = world->map;
73   struct Player * player = world->player;
74   struct Monster * monster = world->monster;
75   char * cells = map->cells;
76   int width_map_av = map->width - map->offset_x;
77   int height_map_av = map->height - map->offset_y;
78   int x, y, z;
79   for (y = 0; y < win->height; y++) {
80     z = map->offset_x + (map->offset_y + y) * (map->width);
81     for (x = 0; x < win->width; x++) {
82       if (y < height_map_av && x < width_map_av) {
83         if (z == (map->width * player->y) + player->x)
84           mvwaddch(win->curses, y, x, '@');
85         else if (z == (map->width * monster->y) + monster->x)
86           mvwaddch(win->curses, y, x, 'M');
87         else
88           mvwaddch(win->curses, y, x, cells[z]);
89         z++; } } } }
90
91 void draw_info_win (struct Win * win) {
92 // Draw info window by appending win->data integer value to "Turn: " display.
93   struct World * world = (struct World *) win->data;
94   int count = world->turn;
95   char text[100];
96   snprintf(text, 100, "Turn: %d", count);
97   draw_with_linebreaks(win, text, 0); }
98
99 void draw_keys_win (struct Win * win) {
100 // Draw keybinding window.
101   struct World * world = (struct World *) win->data;
102   struct KeysWinData * keyswindata = (struct KeysWinData *) world->keyswindata;
103   struct KeyBinding * keybindings = world->keybindings;
104   int offset = 0;
105   if (keyswindata->max >= win->height) {
106     if (keyswindata->select > win->height / 2) {
107       if (keyswindata->select < (keyswindata->max - (win->height / 2)))
108         offset = keyswindata->select - (win->height / 2);
109       else
110         offset = keyswindata->max - win->height + 1; } }
111   int keydescwidth = 9 + 1; // max length assured by get_keyname() + \0
112   char * keydesc = malloc(keydescwidth);
113   attr_t attri;
114   int y, x;
115   char * keyname;
116   for (y = 0; y <= keyswindata->max && y < win->height; y++) {
117     attri = 0;
118     if (y == keyswindata->select - offset) {
119       attri = A_REVERSE;
120       if (1 == keyswindata->edit)
121         attri = attri | A_BLINK; }
122     keyname = get_keyname(keybindings[y + offset].key);
123     snprintf(keydesc, keydescwidth, "%-9s", keyname);
124     free(keyname);
125     for (x = 0; x < win->width; x++)
126       if (x < strlen(keydesc))
127         mvwaddch(win->curses, y, x, keydesc[x] | attri);
128       else if (strlen(keydesc) < x && x < strlen(keybindings[y + offset].name) + strlen(keydesc) + 1)
129         mvwaddch(win->curses, y, x, keybindings[y + offset].name[x - strlen(keydesc) - 1] | attri);
130       else
131         mvwaddch(win->curses, y, x, ' ' | attri); }
132   free(keydesc); }