colors and projections
This commit is contained in:
parent
256adb4ff3
commit
fc19ce7624
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"cmake.ignoreCMakeListsMissing": true
|
||||
}
|
||||
@ -46,3 +46,11 @@
|
||||
...
|
||||
fun:_dl_open
|
||||
}
|
||||
|
||||
{
|
||||
<MLX42>
|
||||
Memcheck:Addr8
|
||||
...
|
||||
fun:dl_open_worker
|
||||
}
|
||||
|
||||
|
||||
120
inc/fdf.h
120
inc/fdf.h
@ -31,16 +31,30 @@
|
||||
# define FILE_ERROR "Error: could not open file %s\n"
|
||||
# define USAGE_ERROR "Usage: %s <filename>\n"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
# ifndef M_PI
|
||||
# define M_PI 3.14159265358979323846
|
||||
# endif
|
||||
# define SQRT2 1.41421356237309514547
|
||||
# define SQRT6 2.44948974278317788134
|
||||
|
||||
# define WIDTH 500
|
||||
# define HEIGHT 500
|
||||
|
||||
typedef struct s_point_3d
|
||||
typedef enum e_colormode
|
||||
{
|
||||
COLOR_MODE_DEFAULT,
|
||||
COLOR_MODE_Z,
|
||||
COLOR_MODE_GRADIENT
|
||||
} t_colormode;
|
||||
|
||||
typedef enum e_projection
|
||||
{
|
||||
PROJECTION_ISOMETRIC,
|
||||
PROJECTION_PARALLEL,
|
||||
PROJECTION_TRIMETRIC
|
||||
} t_projection;
|
||||
|
||||
typedef struct s_point_3d
|
||||
{
|
||||
double x;
|
||||
double y;
|
||||
@ -52,11 +66,12 @@ typedef struct s_point_2d
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int orig_z;
|
||||
int color;
|
||||
} t_point_2d;
|
||||
|
||||
|
||||
typedef struct s_map
|
||||
typedef struct s_map
|
||||
{
|
||||
t_point_3d *orig;
|
||||
t_point_3d *rot;
|
||||
@ -68,54 +83,61 @@ typedef struct s_map
|
||||
|
||||
typedef struct s_fdf
|
||||
{
|
||||
t_map *map;
|
||||
mlx_t *mlx;
|
||||
mlx_image_t *img;
|
||||
mlx_image_t *menu;
|
||||
double angle_x;
|
||||
double angle_y;
|
||||
double angle_z;
|
||||
double animate_z;
|
||||
double zoom;
|
||||
int offset_x;
|
||||
int offset_y;
|
||||
int last_width;
|
||||
int last_height;
|
||||
double z_scale;
|
||||
t_map *map;
|
||||
mlx_t *mlx;
|
||||
mlx_image_t *img;
|
||||
mlx_image_t *menu;
|
||||
double angle_x;
|
||||
double angle_y;
|
||||
double angle_z;
|
||||
double animate_z;
|
||||
double zoom;
|
||||
int offset_x;
|
||||
int offset_y;
|
||||
int last_width;
|
||||
int last_height;
|
||||
double z_scale;
|
||||
t_colormode colormode;
|
||||
t_projection projection;
|
||||
} t_fdf;
|
||||
|
||||
int interpolate_color(t_point_2d start, t_point_2d end, t_point_2d current);
|
||||
int get_color(char *str);
|
||||
int get_map_sizes(char *filename, t_map *map);
|
||||
void free_line_and_split(char **line, char ***split);
|
||||
int read_map(char *filename, t_fdf *fdf);
|
||||
int parse_map(char *filename, t_fdf *fdf);
|
||||
void print_map(t_map *map);
|
||||
void copy_map(t_fdf *fdf);
|
||||
void fdf_apply_rotation(t_fdf *fdf);
|
||||
void handle_error(t_fdf *fdf, char *error);
|
||||
int interpolate_color(t_point_2d start,
|
||||
t_point_2d end, t_point_2d current);
|
||||
int get_color(char *str);
|
||||
int get_map_sizes(char *filename, t_map *map);
|
||||
void free_line_and_split(char **line, char ***split);
|
||||
int load_map_from_file(char *filename, t_fdf *fdf);
|
||||
int parse_map(char *filename, t_fdf *fdf);
|
||||
void copy_map(t_fdf *fdf);
|
||||
void fdf_apply_rotation(t_fdf *fdf);
|
||||
void handle_error(t_fdf *fdf, char *error);
|
||||
|
||||
void rotate_x(t_point_3d **points, double angle, int size);
|
||||
void rotate_y(t_point_3d **points, double angle, int size);
|
||||
void rotate_z(t_point_3d **points, double angle, int size);
|
||||
bool fdf_put_pixel(mlx_image_t *img, t_point_2d point);
|
||||
void fdf_draw_line(mlx_image_t *img, t_point_2d start,
|
||||
t_point_2d end);
|
||||
int fdf_hooks(t_fdf *fdf);
|
||||
void resize_hook(int width, int height, void *param);
|
||||
void rotate_x(t_point_3d **points, double angle, int size);
|
||||
void rotate_y(t_point_3d **points, double angle, int size);
|
||||
void rotate_z(t_point_3d **points, double angle, int size);
|
||||
bool fdf_put_pixel(t_fdf *fdf, t_point_2d point);
|
||||
void fdf_draw_line(t_fdf *fdf, t_point_2d start,
|
||||
t_point_2d end);
|
||||
int fdf_hooks(t_fdf *fdf);
|
||||
void resize_hook(int width, int height, void *param);
|
||||
|
||||
void draw_hook(void *param);
|
||||
void key_hook(mlx_key_data_t keydata, void *param);
|
||||
void fdf_set_background(mlx_image_t *img, int color);
|
||||
void project_isometric(t_fdf *fdf);
|
||||
double deg2rad(double deg);
|
||||
t_fdf *initialise_fdf(void);
|
||||
bool clean_fdf(t_fdf *fdf);
|
||||
void get_z_max(t_fdf *fdf);
|
||||
int init_mlx(t_fdf *fdf);
|
||||
void set_map_point(t_fdf *fdf, int x, int y, char **str);
|
||||
void draw_hook(void *param);
|
||||
void key_hook(mlx_key_data_t keydata, void *param);
|
||||
void fdf_set_background(mlx_image_t *img, int color);
|
||||
void project_isometric(t_fdf *fdf);
|
||||
double deg2rad(double deg);
|
||||
t_fdf *initialise_fdf(void);
|
||||
bool clean_fdf(t_fdf *fdf);
|
||||
void get_z_max(t_fdf *fdf);
|
||||
int init_mlx(t_fdf *fdf);
|
||||
void set_map_point(t_fdf *fdf, int x, int y, char **str);
|
||||
mlx_image_t *draw_menu(t_fdf *fdf);
|
||||
int get_z_color(double z, int z_max);
|
||||
int get_z_color(double z, int z_max);
|
||||
void close_hook(void *param);
|
||||
int get_gradient_color(double z, int z_max);
|
||||
void project_parallel(t_fdf *fdf);
|
||||
void project(t_fdf *fdf);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@ -135,4 +157,4 @@ int get_z_color(double z, int z_max);
|
||||
// [p] Change projection mode
|
||||
// [ESC] Close window
|
||||
|
||||
// ============================
|
||||
// ============================
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
0 0 10 10 0 0 10 10 0 0 0 10 10 10 10 10 0 0 0
|
||||
0 0 10 10 0 0 10 10 0 0 0 0 0 0 0 10 10 0 0
|
||||
|
||||
@ -14,16 +14,12 @@
|
||||
|
||||
bool clean_fdf(t_fdf *fdf)
|
||||
{
|
||||
mlx_delete_image(fdf->mlx, fdf->img);
|
||||
mlx_delete_image(fdf->mlx, fdf->menu);
|
||||
|
||||
if (fdf->map)
|
||||
{
|
||||
free(fdf->map->orig);
|
||||
free(fdf->map->rot);
|
||||
free(fdf->map->proj);
|
||||
free(fdf->map);
|
||||
|
||||
}
|
||||
free(fdf);
|
||||
return (true);
|
||||
|
||||
@ -58,15 +58,23 @@ int interpolate_color(t_point_2d start, t_point_2d end, t_point_2d current)
|
||||
return (red << 24 | green << 16 | blue << 8 | 0xFF);
|
||||
}
|
||||
|
||||
int get_z_color(double z, int z_max)
|
||||
int get_z_color(double z, int z_max)
|
||||
{
|
||||
int red;
|
||||
int red;
|
||||
int green;
|
||||
|
||||
int temp;
|
||||
int temp;
|
||||
|
||||
temp = 255 * z / z_max;
|
||||
red = temp;
|
||||
green = 255 - temp;
|
||||
return (red << 24 | green << 16 | 0x00FF);
|
||||
}
|
||||
}
|
||||
|
||||
int get_gradient_color(double z, int z_max)
|
||||
{
|
||||
const int colors[] = {0x0058fbff, 0x007efeff, 0x008fd7ff, 0x0098a3f,
|
||||
0x009c7aff, 0x1fa46bff, 0x5eb13dff, 0x83c052ff,
|
||||
0xa5cf69ff, 0xc3de81ff, 0xeeffffff, 0xffffffff,0xffffffff};
|
||||
|
||||
return (colors[(int)(z * 12 / z_max)]);
|
||||
}
|
||||
|
||||
@ -11,16 +11,25 @@
|
||||
/* ************************************************************************** */
|
||||
#include "fdf.h"
|
||||
|
||||
bool fdf_put_pixel(mlx_image_t *img, t_point_2d point)
|
||||
bool fdf_put_pixel(t_fdf *fdf, t_point_2d point)
|
||||
{
|
||||
if (point.x < 0 || point.x >= (int) img->width
|
||||
|| point.y < 0 || point.y >= (int) img->height)
|
||||
int color;
|
||||
|
||||
color = 0xFFFFFFFF;
|
||||
if (point.x < 0 || point.x >= (int) fdf->img->width
|
||||
|| point.y < 0 || point.y >= (int) fdf->img->height)
|
||||
return (false);
|
||||
mlx_put_pixel(img, point.x, point.y, point.color);
|
||||
if (fdf->colormode == COLOR_MODE_DEFAULT)
|
||||
color = point.color;
|
||||
else if (fdf->colormode == COLOR_MODE_Z)
|
||||
color = get_z_color(point.orig_z, fdf->map->z_max);
|
||||
else if (fdf->colormode == COLOR_MODE_GRADIENT)
|
||||
color = get_gradient_color(point.orig_z, fdf->map->z_max);
|
||||
mlx_put_pixel(fdf->img, point.x, point.y, color);
|
||||
return (true);
|
||||
}
|
||||
|
||||
void fdf_draw_line_low(mlx_image_t *img, t_point_2d start, t_point_2d end)
|
||||
void fdf_draw_line_low(t_fdf *fdf, t_point_2d start, t_point_2d end)
|
||||
{
|
||||
int delta;
|
||||
int yi;
|
||||
@ -37,7 +46,7 @@ void fdf_draw_line_low(mlx_image_t *img, t_point_2d start, t_point_2d end)
|
||||
while (current.x <= end.x)
|
||||
{
|
||||
current.color = interpolate_color(start, end, current);
|
||||
fdf_put_pixel(img, current);
|
||||
fdf_put_pixel(fdf, current);
|
||||
if (delta > 0)
|
||||
{
|
||||
current.y += yi;
|
||||
@ -48,7 +57,7 @@ void fdf_draw_line_low(mlx_image_t *img, t_point_2d start, t_point_2d end)
|
||||
}
|
||||
}
|
||||
|
||||
void fdf_draw_line_high(mlx_image_t *img, t_point_2d start, t_point_2d end)
|
||||
void fdf_draw_line_high(t_fdf *fdf, t_point_2d start, t_point_2d end)
|
||||
{
|
||||
int delta;
|
||||
int xi;
|
||||
@ -65,7 +74,7 @@ void fdf_draw_line_high(mlx_image_t *img, t_point_2d start, t_point_2d end)
|
||||
while (current.y <= end.y)
|
||||
{
|
||||
current.color = interpolate_color(start, end, current);
|
||||
fdf_put_pixel(img, current);
|
||||
fdf_put_pixel(fdf, current);
|
||||
if (delta > 0)
|
||||
{
|
||||
current.x += xi;
|
||||
@ -76,25 +85,25 @@ void fdf_draw_line_high(mlx_image_t *img, t_point_2d start, t_point_2d end)
|
||||
}
|
||||
}
|
||||
|
||||
void fdf_draw_line(mlx_image_t *img, t_point_2d start, t_point_2d end)
|
||||
void fdf_draw_line(t_fdf *fdf, t_point_2d start, t_point_2d end)
|
||||
{
|
||||
if ((start.x < 0 || start.x >= (int) img->width
|
||||
|| start.y < 0 || start.y >= (int) img->height)
|
||||
&& (end.x < 0 || end.x >= (int) img->width
|
||||
|| end.y < 0 || end.y >= (int) img->height))
|
||||
if ((start.x < 0 || start.x >= (int) fdf->img->width
|
||||
|| start.y < 0 || start.y >= (int) fdf->img->height)
|
||||
&& (end.x < 0 || end.x >= (int) fdf->img->width
|
||||
|| end.y < 0 || end.y >= (int) fdf->img->height))
|
||||
return ;
|
||||
if (abs(end.y - start.y) < abs(end.x - start.x))
|
||||
{
|
||||
if (start.x > end.x)
|
||||
fdf_draw_line_low(img, end, start);
|
||||
fdf_draw_line_low(fdf, end, start);
|
||||
else
|
||||
fdf_draw_line_low(img, start, end);
|
||||
fdf_draw_line_low(fdf, start, end);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (start.y > end.y)
|
||||
fdf_draw_line_high(img, end, start);
|
||||
fdf_draw_line_high(fdf, end, start);
|
||||
else
|
||||
fdf_draw_line_high(img, start, end);
|
||||
fdf_draw_line_high(fdf, start, end);
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ int fdf_hooks(t_fdf *fdf)
|
||||
{
|
||||
mlx_loop_hook(fdf->mlx, draw_hook, fdf);
|
||||
mlx_key_hook(fdf->mlx, key_hook, fdf);
|
||||
mlx_close_hook(fdf->mlx, close_hook, fdf);
|
||||
mlx_resize_hook(fdf->mlx, resize_hook, fdf);
|
||||
return (1);
|
||||
}
|
||||
@ -30,7 +31,7 @@ void resize_hook(int width, int height, void *param)
|
||||
fdf = (t_fdf *)param;
|
||||
mlx_delete_image(fdf->mlx, fdf->img);
|
||||
fdf->img = mlx_new_image(fdf->mlx, fdf->mlx->width, fdf->mlx->height);
|
||||
if (!fdf->img
|
||||
if (!fdf->img
|
||||
|| (mlx_image_to_window(fdf->mlx, fdf->img, 0, 0) < 0)
|
||||
|| (mlx_image_to_window(fdf->mlx, fdf->menu, 10, 10) < 0))
|
||||
exit(1);
|
||||
@ -57,15 +58,15 @@ void draw_hook(void *param)
|
||||
if (fdf->animate_z)
|
||||
fdf->angle_z += deg2rad(fdf->animate_z);
|
||||
fdf_apply_rotation(fdf);
|
||||
project_isometric(fdf);
|
||||
project(fdf);
|
||||
i = 0;
|
||||
while (i < fdf->map->width * fdf->map->height)
|
||||
{
|
||||
fdf_put_pixel(fdf->img, fdf->map->proj[i]);
|
||||
fdf_put_pixel(fdf, fdf->map->proj[i]);
|
||||
if (i % fdf->map->width != fdf->map->width - 1)
|
||||
fdf_draw_line(fdf->img, fdf->map->proj[i], fdf->map->proj[i + 1]);
|
||||
fdf_draw_line(fdf, fdf->map->proj[i], fdf->map->proj[i + 1]);
|
||||
if (i / fdf->map->width != fdf->map->height - 1)
|
||||
fdf_draw_line(fdf->img, fdf->map->proj[i], fdf->map->proj[i + fdf->map->width]);
|
||||
fdf_draw_line(fdf, fdf->map->proj[i], fdf->map->proj[i + fdf->map->width]);
|
||||
i++;
|
||||
}
|
||||
// draw_menu(fdf);
|
||||
@ -98,16 +99,21 @@ mlx_image_t *draw_menu(t_fdf *fdf)
|
||||
return (img);
|
||||
}
|
||||
|
||||
void close_hook(void *param)
|
||||
{
|
||||
mlx_close_window(((t_fdf *)param)->mlx);
|
||||
mlx_terminate(((t_fdf *)param)->mlx);
|
||||
clean_fdf((t_fdf *)param);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void key_hook(mlx_key_data_t keydata, void *param)
|
||||
{
|
||||
t_fdf *fdf;
|
||||
|
||||
fdf = (t_fdf *)param;
|
||||
if (keydata.key == MLX_KEY_ESCAPE)
|
||||
{
|
||||
mlx_close_window(((t_fdf *)param)->mlx);
|
||||
exit(0);
|
||||
}
|
||||
close_hook(fdf);
|
||||
if (keydata.key == MLX_KEY_A && keydata.action != MLX_RELEASE)
|
||||
fdf->angle_z -= deg2rad(5);
|
||||
if (keydata.key == MLX_KEY_D && keydata.action != MLX_RELEASE)
|
||||
@ -142,5 +148,9 @@ void key_hook(mlx_key_data_t keydata, void *param)
|
||||
fdf->animate_z += 0.5;
|
||||
if (keydata.key == MLX_KEY_SLASH && keydata.action == MLX_PRESS)
|
||||
fdf->menu->enabled = !fdf->menu->enabled;
|
||||
|
||||
}
|
||||
if (keydata.key == MLX_KEY_C && keydata.action == MLX_PRESS)
|
||||
fdf->colormode = (fdf->colormode + 1) % 3;
|
||||
if (keydata.key == MLX_KEY_P && keydata.action == MLX_PRESS)
|
||||
fdf->projection = (fdf->projection + 1) % 3;
|
||||
|
||||
}
|
||||
|
||||
@ -16,7 +16,6 @@ int init_mlx(t_fdf *fdf)
|
||||
{
|
||||
mlx_t *mlx;
|
||||
|
||||
printf("init_mlx\n");
|
||||
mlx = mlx_init(WIDTH, HEIGHT, "FdF", true);
|
||||
if (!mlx)
|
||||
handle_error(fdf, "Error: failed to initialise MLX");
|
||||
|
||||
@ -36,6 +36,8 @@ t_fdf *initialise_fdf(void)
|
||||
fdf->z_scale = 0.1;
|
||||
fdf->last_width = WIDTH;
|
||||
fdf->last_height = HEIGHT;
|
||||
fdf->colormode = COLOR_MODE_DEFAULT;
|
||||
fdf->projection = PROJECTION_ISOMETRIC;
|
||||
fdf->map->orig = NULL;
|
||||
fdf->map->rot = NULL;
|
||||
fdf->map->proj = NULL;
|
||||
|
||||
@ -24,9 +24,8 @@ int parse_map(char *filename, t_fdf *fdf)
|
||||
fdf->map->proj = malloc(map_size * sizeof(t_point_2d));
|
||||
if (!fdf->map->orig || !fdf->map->rot || !fdf->map->proj)
|
||||
handle_error(fdf, MALLOC_ERROR);
|
||||
if (!read_map(filename, fdf))
|
||||
if (!load_map_from_file(filename, fdf))
|
||||
handle_error(fdf, "Error: failed to read map");
|
||||
get_z_max(fdf);
|
||||
ft_printf("%d\n", fdf->map->z_max);
|
||||
return (SUCCESS);
|
||||
}
|
||||
|
||||
@ -12,6 +12,46 @@
|
||||
|
||||
#include "fdf.h"
|
||||
|
||||
void project_trimetric(t_fdf *fdf)
|
||||
{
|
||||
int i;
|
||||
double x;
|
||||
double y;
|
||||
|
||||
i = 0;
|
||||
if (fdf->zoom == 0)
|
||||
fdf->zoom = fmin(fdf->mlx->width / fdf->map->width,
|
||||
fdf->mlx->height / fdf->map->height) / 2;
|
||||
while (i < fdf->map->width * fdf->map->height)
|
||||
{
|
||||
x = fdf->map->rot[i].x - fdf->map->rot[i].y;
|
||||
y = fdf->map->rot[i].x + fdf->map->rot[i].y - fdf->map->rot[i].z;
|
||||
fdf->map->proj[i].x = x * fdf->zoom + fdf->offset_x;
|
||||
fdf->map->proj[i].y = y * fdf->zoom + fdf->offset_y;
|
||||
fdf->map->proj[i].orig_z = fdf->map->orig[i].z;
|
||||
fdf->map->proj[i].color = fdf->map->rot[i].color;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void project_parallel(t_fdf *fdf)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
if (fdf->zoom == 0)
|
||||
fdf->zoom = fmin(fdf->mlx->width / fdf->map->width,
|
||||
fdf->mlx->height / fdf->map->height) / 2;
|
||||
while (i < fdf->map->width * fdf->map->height)
|
||||
{
|
||||
fdf->map->proj[i].x = fdf->map->rot[i].x * fdf->zoom + fdf->offset_x;
|
||||
fdf->map->proj[i].y = fdf->map->rot[i].y * fdf->zoom + fdf->offset_y;
|
||||
fdf->map->proj[i].orig_z = fdf->map->orig[i].z;
|
||||
fdf->map->proj[i].color = fdf->map->orig[i].color;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void project_isometric(t_fdf *fdf)
|
||||
{
|
||||
int i;
|
||||
@ -29,8 +69,18 @@ void project_isometric(t_fdf *fdf)
|
||||
- 2 * fdf->map->rot[i].z) / SQRT6;
|
||||
fdf->map->proj[i].x = x * fdf->zoom + fdf->offset_x;
|
||||
fdf->map->proj[i].y = y * fdf->zoom + fdf->offset_y;
|
||||
fdf->map->proj[i].color = get_z_color(fdf->map->orig[i].z, fdf->map->z_max);
|
||||
// fdf->map->proj[i].color = fdf->map->rot[i].color;
|
||||
fdf->map->proj[i].orig_z = fdf->map->orig[i].z;
|
||||
fdf->map->proj[i].color = fdf->map->rot[i].color;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void project(t_fdf *fdf)
|
||||
{
|
||||
if (fdf->projection == PROJECTION_ISOMETRIC)
|
||||
project_isometric(fdf);
|
||||
else if (fdf->projection == PROJECTION_PARALLEL)
|
||||
project_parallel(fdf);
|
||||
else if (fdf->projection == PROJECTION_TRIMETRIC)
|
||||
project_trimetric(fdf);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: o_ :::::: ::: */
|
||||
/* read_map.c :+: / :+::+: :+: */
|
||||
/* load_map_from_file.c :+: / :+::+: :+: */
|
||||
/* +:+ > +:++:+ +:+ */
|
||||
/* By: whaffman <whaffman@student.codam.nl> +#+ +:+ +#++#++:++#++ */
|
||||
/* +#+ +#+#+ +#++#+ +#+ \o/ */
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
#include "fdf.h"
|
||||
|
||||
int read_map(char *filename, t_fdf *fdf)
|
||||
int load_map_from_file(char *filename, t_fdf *fdf)
|
||||
{
|
||||
int fd;
|
||||
char *line;
|
||||
Loading…
Reference in New Issue
Block a user