add struct ct_surface as a struct _win_st (ncurses) replacement
This commit is contained in:
parent
bcfcbaf529
commit
08e4376a35
3 changed files with 186 additions and 0 deletions
7
src/_ct_shared.h
Normal file
7
src/_ct_shared.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef _CURSETREE__SHARED_H
|
||||
#define _CURSETREE__SHARED_H
|
||||
|
||||
#define OK (0)
|
||||
#define ERR (1)
|
||||
|
||||
#endif /* _CURSETREE__SHARED_H */
|
||||
163
src/surface.c
Normal file
163
src/surface.c
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "_ct_shared.h"
|
||||
#include "surface.h"
|
||||
|
||||
#define ALLOC_ROW(w) ((char *)calloc(w, sizeof(char)))
|
||||
|
||||
/* Allocates a new 2D surface buffer with ROWS=h, COLS=w.
|
||||
* Returns NULL on failure and sets errno, otherwise
|
||||
* a pointer to the new buffer is returned.
|
||||
*/
|
||||
static inline __attribute__((malloc, warn_unused_result)) char **
|
||||
sfbuf(const pos w, const pos h) {
|
||||
char **buf;
|
||||
pos i;
|
||||
|
||||
buf = (char **)malloc(sizeof(char *) * h);
|
||||
if (buf == NULL)
|
||||
return buf;
|
||||
|
||||
for (i = 0; i < w; i++) {
|
||||
buf[i] = ALLOC_ROW(w);
|
||||
if (buf[i] == NULL)
|
||||
goto fail;
|
||||
}
|
||||
return buf;
|
||||
|
||||
fail:
|
||||
// Immediately decrement since we know the
|
||||
// current index is where ALLOW_ROW() failed.
|
||||
while (--i >= 0)
|
||||
free(buf[i]);
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Resize the width (columns) of a surface.
|
||||
* Returns 0 on success, or a non-zero errno on failure.
|
||||
* WARNING: Don't use sfseth directly, see sfresize()
|
||||
* WARNING: and how it optimises based on how height changes.
|
||||
*/
|
||||
static inline int sfsetw(const pos w1, surface *const s) {
|
||||
void *ptr;
|
||||
pos i, w0 = s->w;
|
||||
char **row;
|
||||
|
||||
errno = 0; // sanity check
|
||||
|
||||
if (w1 == w0)
|
||||
return OK;
|
||||
else if (w1 == 0) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0, row = s->buf; i < s->h; i++, row++) {
|
||||
ptr = (void *)reallocarray(*row, w1, sizeof(char));
|
||||
if (ptr == NULL) {
|
||||
return errno;
|
||||
}
|
||||
*row = (char *)ptr;
|
||||
}
|
||||
|
||||
s->w = w1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* Resize the height (rows) of a surface.
|
||||
* Returns 0 on success, or a non-zero errno on failure.
|
||||
* WARNING: Don't use sfseth directly, see sfresize()
|
||||
* WARNING: and how it optimises based on how height changes.
|
||||
*/
|
||||
static inline int sfseth(const pos h1, surface *const s) {
|
||||
void *ptr;
|
||||
pos i, h0 = s->h;
|
||||
char **row;
|
||||
|
||||
errno = 0; // sanity check
|
||||
|
||||
if (h1 == h0)
|
||||
return OK;
|
||||
else if (h1 == 0) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
// height decreased (free bottom rows)
|
||||
if (h1 < h0) {
|
||||
for (i = h1, row = s->buf; i < h0; i++, row++) {
|
||||
free(*row);
|
||||
}
|
||||
}
|
||||
|
||||
// use ptr to avoid losing unfreed s->buf
|
||||
ptr = (void *)reallocarray(s->buf, h1, sizeof(char));
|
||||
if (ptr == NULL)
|
||||
return errno;
|
||||
// ENOMEM X_X
|
||||
|
||||
s->buf = (char **)ptr;
|
||||
s->h = h1;
|
||||
|
||||
// height increased (alloc bottom rows)
|
||||
if (h1 > h0) {
|
||||
for (i = h0, row = s->buf; i < h1; i++, row++) {
|
||||
*row = ALLOC_ROW(s->w);
|
||||
if (*row == NULL)
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
|
||||
s->h = h1;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
int sfresize(const pos w1, const pos h1, surface *const s) {
|
||||
int retv;
|
||||
|
||||
/* Height is the 2D array's primary index dimension,
|
||||
* whether it grows/shrinks determines whether it is
|
||||
* optimal to resize width then height, or height then width.
|
||||
* ie Height increasing but doing sfseth() before sfsetw()
|
||||
* would result in new rows being allocated with the old width,
|
||||
* then resized again to the new width (not optimal).
|
||||
*/
|
||||
if (h1 > s->h) {
|
||||
if ((retv = sfsetw(w1, s)) || (retv = sfseth(h1, s)))
|
||||
return retv;
|
||||
} else if ((retv = sfseth(h1, s)) || (retv = sfsetw(w1, s)))
|
||||
return retv;
|
||||
return OK;
|
||||
}
|
||||
|
||||
__attribute__((malloc, warn_unused_result)) surface *sfalloc(const pos x, const pos y, const pos w, const pos h) {
|
||||
surface *s;
|
||||
|
||||
char **buf = sfbuf(w, h);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
s = (surface *)malloc(sizeof(struct ct_surface));
|
||||
*s = (surface){
|
||||
.x = x,
|
||||
.y = y,
|
||||
.w = w,
|
||||
.h = y,
|
||||
.vcx = 1,
|
||||
.vcy = 1,
|
||||
.buf = buf,
|
||||
};
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void sffree(surface *const s) {
|
||||
pos i;
|
||||
char **row;
|
||||
for (i=0, row=s->buf; i < s->h; i++, row++) {
|
||||
free(*row);
|
||||
}
|
||||
free(s->buf);
|
||||
}
|
||||
16
src/surface.h
Normal file
16
src/surface.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef _CURSETREE_SURFACE_H
|
||||
#define _CURSETREE_SURFACE_H
|
||||
|
||||
/* Initial row and column coordinates */
|
||||
#define ROW0 1
|
||||
#define COL0 1
|
||||
|
||||
typedef unsigned short pos;
|
||||
|
||||
typedef struct ct_surface {
|
||||
pos x, y, w, h;
|
||||
char **buf;
|
||||
pos vcx, vcy; /* virtual cursor position */
|
||||
} surface;
|
||||
|
||||
#endif /* _CURSETREE_SURFACE_H */
|
||||
Loading…
Add table
Add a link
Reference in a new issue