@@ -390,11 +390,10 @@ int cucul_set_canvas_boundaries(cucul_canvas_t *cv, int x, int y, | |||
cucul_set_canvas_frame(new, f); | |||
cucul_blit(new, -x, -y, cv, NULL); | |||
free(cv->allchars[f]); | |||
free(cv->allattrs[f]); | |||
free(cv->frames[f].chars); | |||
free(cv->frames[f].attrs); | |||
} | |||
free(cv->allchars); | |||
free(cv->allattrs); | |||
free(cv->frames); | |||
memcpy(cv, new, sizeof(cucul_canvas_t)); | |||
free(new); | |||
@@ -68,29 +68,24 @@ cucul_canvas_t * cucul_create_canvas(unsigned int width, unsigned int height) | |||
cv->frame = 0; | |||
cv->framecount = 1; | |||
cv->allchars = malloc(sizeof(uint32_t *)); | |||
if(!cv->allchars) | |||
cv->frames = malloc(sizeof(struct cucul_frame)); | |||
if(!cv->frames) | |||
{ | |||
free(cv); | |||
goto nomem; | |||
} | |||
cv->allattrs = malloc(sizeof(uint32_t *)); | |||
if(!cv->allattrs) | |||
{ | |||
free(cv->allchars); | |||
free(cv); | |||
goto nomem; | |||
} | |||
cv->allchars[0] = NULL; | |||
cv->allattrs[0] = NULL; | |||
cv->frames[0].width = cv->frames[0].height = 0; | |||
cv->frames[0].chars = NULL; | |||
cv->frames[0].attrs = NULL; | |||
cv->frames[0].curattr = cv->curattr; | |||
if(_cucul_set_canvas_size(cv, width, height) < 0) | |||
{ | |||
#if defined(HAVE_ERRNO_H) | |||
int saved_errno = errno; | |||
#endif | |||
free(cv->allattrs); | |||
free(cv->allchars); | |||
free(cv->frames); | |||
free(cv); | |||
#if defined(HAVE_ERRNO_H) | |||
errno = saved_errno; | |||
@@ -200,12 +195,11 @@ int cucul_free_canvas(cucul_canvas_t *cv) | |||
for(f = 0; f < cv->framecount; f++) | |||
{ | |||
free(cv->allchars[f]); | |||
free(cv->allattrs[f]); | |||
free(cv->frames[f].chars); | |||
free(cv->frames[f].attrs); | |||
} | |||
free(cv->allchars); | |||
free(cv->allattrs); | |||
free(cv->frames); | |||
free(cv); | |||
return 0; | |||
@@ -257,11 +251,11 @@ int _cucul_set_canvas_size(cucul_canvas_t *cv, unsigned int width, | |||
{ | |||
for(f = 0; f < cv->framecount; f++) | |||
{ | |||
cv->allchars[f] = realloc(cv->allchars[f], | |||
new_size * sizeof(uint32_t)); | |||
cv->allattrs[f] = realloc(cv->allattrs[f], | |||
new_size * sizeof(uint32_t)); | |||
if(new_size && (!cv->allchars[f] || !cv->allattrs[f])) | |||
cv->frames[f].chars = realloc(cv->frames[f].chars, | |||
new_size * sizeof(uint32_t)); | |||
cv->frames[f].attrs = realloc(cv->frames[f].attrs, | |||
new_size * sizeof(uint32_t)); | |||
if(new_size && (!cv->frames[f].chars || !cv->frames[f].attrs)) | |||
{ | |||
#if defined(HAVE_ERRNO_H) | |||
errno = ENOMEM; | |||
@@ -284,12 +278,12 @@ int _cucul_set_canvas_size(cucul_canvas_t *cv, unsigned int width, | |||
* we will overwrite information. */ | |||
for(f = 0; f < cv->framecount; f++) | |||
{ | |||
uint32_t *chars = cv->allchars[f]; | |||
uint32_t *attrs = cv->allattrs[f]; | |||
uint32_t *chars = cv->frames[f].chars; | |||
uint32_t *attrs = cv->frames[f].attrs; | |||
for(y = height < old_height ? height : old_height; y--; ) | |||
{ | |||
uint32_t attr = cv->curattr; | |||
uint32_t attr = cv->frames[f].curattr; | |||
for(x = old_width; x--; ) | |||
{ | |||
@@ -314,8 +308,8 @@ int _cucul_set_canvas_size(cucul_canvas_t *cv, unsigned int width, | |||
for(f = 0; f < cv->framecount; f++) | |||
{ | |||
uint32_t *chars = cv->allchars[f]; | |||
uint32_t *attrs = cv->allattrs[f]; | |||
uint32_t *chars = cv->frames[f].chars; | |||
uint32_t *attrs = cv->frames[f].attrs; | |||
for(y = 1; y < lines; y++) | |||
{ | |||
@@ -333,9 +327,9 @@ int _cucul_set_canvas_size(cucul_canvas_t *cv, unsigned int width, | |||
{ | |||
for(f = 0; f < cv->framecount; f++) | |||
{ | |||
uint32_t *chars = cv->allchars[f]; | |||
uint32_t *attrs = cv->allattrs[f]; | |||
uint32_t attr = cv->curattr; | |||
uint32_t *chars = cv->frames[f].chars; | |||
uint32_t *attrs = cv->frames[f].attrs; | |||
uint32_t attr = cv->frames[f].curattr; | |||
/* Zero the bottom of the screen */ | |||
for(x = (height - old_height) * width; x--; ) | |||
@@ -347,15 +341,15 @@ int _cucul_set_canvas_size(cucul_canvas_t *cv, unsigned int width, | |||
} | |||
/* Step 4: if new area is smaller, resize memory area now. */ | |||
if(new_size <= old_size) | |||
if(new_size < old_size) | |||
{ | |||
for(f = 0; f < cv->framecount; f++) | |||
{ | |||
cv->allchars[f] = realloc(cv->allchars[f], | |||
new_size * sizeof(uint32_t)); | |||
cv->allattrs[f] = realloc(cv->allattrs[f], | |||
new_size * sizeof(uint32_t)); | |||
if(new_size && (!cv->allchars[f] || !cv->allattrs[f])) | |||
cv->frames[f].chars = realloc(cv->frames[f].chars, | |||
new_size * sizeof(uint32_t)); | |||
cv->frames[f].attrs = realloc(cv->frames[f].attrs, | |||
new_size * sizeof(uint32_t)); | |||
if(new_size && (!cv->frames[f].chars || !cv->frames[f].attrs)) | |||
{ | |||
#if defined(HAVE_ERRNO_H) | |||
errno = ENOMEM; | |||
@@ -365,9 +359,16 @@ int _cucul_set_canvas_size(cucul_canvas_t *cv, unsigned int width, | |||
} | |||
} | |||
/* Reset the current frame shortcut */ | |||
cv->chars = cv->allchars[cv->frame]; | |||
cv->attrs = cv->allattrs[cv->frame]; | |||
/* Set new size */ | |||
for(f = 0; f < cv->framecount; f++) | |||
{ | |||
cv->frames[f].width = width; | |||
cv->frames[f].height = height; | |||
} | |||
/* Reset the current frame shortcuts */ | |||
cv->chars = cv->frames[cv->frame].chars; | |||
cv->attrs = cv->frames[cv->frame].attrs; | |||
return 0; | |||
} | |||
@@ -18,24 +18,32 @@ | |||
# include <inttypes.h> | |||
#endif | |||
struct cucul_canvas | |||
struct cucul_frame | |||
{ | |||
/* Canvas size */ | |||
/* Frame size */ | |||
unsigned int width, height; | |||
/* Shortcut to the active frame */ | |||
/* Cell information */ | |||
uint32_t *chars; | |||
uint32_t *attrs; | |||
/* Frame information */ | |||
unsigned int frame, framecount; | |||
uint32_t **allchars; | |||
uint32_t **allattrs; | |||
/* Painting context */ | |||
uint32_t curattr; | |||
}; | |||
struct cucul_canvas | |||
{ | |||
/* Frame information */ | |||
unsigned int frame, framecount; | |||
struct cucul_frame *frames; | |||
unsigned int refcount; | |||
/* Shortcut to the active frame information */ | |||
unsigned int width, height; | |||
uint32_t *chars; | |||
uint32_t *attrs; | |||
uint32_t curattr; | |||
}; | |||
struct cucul_buffer | |||
@@ -30,6 +30,9 @@ | |||
#include "cucul.h" | |||
#include "cucul_internals.h" | |||
static void save_frame_info(cucul_canvas_t *); | |||
static void load_frame_info(cucul_canvas_t *); | |||
/** \brief Get the number of frames in a canvas. | |||
* | |||
* Return the current canvas' frame count. | |||
@@ -69,10 +72,9 @@ int cucul_set_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||
return -1; | |||
} | |||
save_frame_info(cv); | |||
cv->frame = frame; | |||
cv->chars = cv->allchars[cv->frame]; | |||
cv->attrs = cv->allattrs[cv->frame]; | |||
load_frame_info(cv); | |||
return 0; | |||
} | |||
@@ -84,7 +86,7 @@ int cucul_set_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||
* | |||
* The frame index indicates where the frame should be inserted. Valid | |||
* values range from 0 to the current canvas frame count. If the frame | |||
* index is greater the or equals the current canvas frame count, the new | |||
* index is greater than or equals the current canvas frame count, the new | |||
* frame is appended at the end of the canvas. | |||
* | |||
* The active frame does not change, but its index may be renumbered due | |||
@@ -106,26 +108,23 @@ int cucul_create_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||
frame = cv->framecount; | |||
cv->framecount++; | |||
cv->allchars = realloc(cv->allchars, sizeof(uint32_t *) * cv->framecount); | |||
cv->allattrs = realloc(cv->allattrs, sizeof(uint32_t *) * cv->framecount); | |||
cv->frames = realloc(cv->frames, | |||
sizeof(struct cucul_frame) * cv->framecount); | |||
for(f = cv->framecount - 1; f > frame; f--) | |||
{ | |||
cv->allchars[f] = cv->allchars[f - 1]; | |||
cv->allattrs[f] = cv->allattrs[f - 1]; | |||
} | |||
cv->frames[f] = cv->frames[f - 1]; | |||
cv->allchars[frame] = malloc(size); | |||
memcpy(cv->allchars[frame], cv->chars, size); | |||
cv->allattrs[frame] = malloc(size); | |||
memcpy(cv->allattrs[frame], cv->attrs, size); | |||
cv->frames[frame].width = cv->width; | |||
cv->frames[frame].height = cv->height; | |||
cv->frames[frame].chars = malloc(size); | |||
memcpy(cv->frames[frame].chars, cv->chars, size); | |||
cv->frames[frame].attrs = malloc(size); | |||
memcpy(cv->frames[frame].attrs, cv->attrs, size); | |||
cv->frames[frame].curattr = cv->curattr; | |||
if(cv->frame >= frame) | |||
cv->frame++; | |||
cv->chars = cv->allchars[cv->frame]; | |||
cv->attrs = cv->allattrs[cv->frame]; | |||
return 0; | |||
} | |||
@@ -170,27 +169,47 @@ int cucul_free_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||
return -1; | |||
} | |||
free(cv->allchars[frame]); | |||
free(cv->allattrs[frame]); | |||
free(cv->frames[frame].chars); | |||
free(cv->frames[frame].attrs); | |||
for(f = frame + 1; f < cv->framecount; f++) | |||
{ | |||
cv->allchars[f - 1] = cv->allchars[f]; | |||
cv->allattrs[f - 1] = cv->allattrs[f]; | |||
} | |||
cv->frames[f - 1] = cv->frames[f]; | |||
cv->framecount--; | |||
cv->allchars = realloc(cv->allchars, sizeof(uint32_t *) * cv->framecount); | |||
cv->allattrs = realloc(cv->allattrs, sizeof(uint32_t *) * cv->framecount); | |||
cv->frames = realloc(cv->frames, | |||
sizeof(struct cucul_frame) * cv->framecount); | |||
if(cv->frame > frame) | |||
cv->frame--; | |||
else if(cv->frame == frame) | |||
{ | |||
cv->frame = 0; | |||
cv->chars = cv->allchars[cv->frame]; | |||
cv->attrs = cv->allattrs[cv->frame]; | |||
load_frame_info(cv); | |||
} | |||
return 0; | |||
} | |||
/* | |||
* XXX: the following functions are local. | |||
*/ | |||
static void save_frame_info(cucul_canvas_t *cv) | |||
{ | |||
cv->frames[cv->frame].width = cv->width; | |||
cv->frames[cv->frame].height = cv->height; | |||
cv->frames[cv->frame].curattr = cv->curattr; | |||
} | |||
static void load_frame_info(cucul_canvas_t *cv) | |||
{ | |||
cv->width = cv->frames[cv->frame].width; | |||
cv->height = cv->frames[cv->frame].height; | |||
cv->chars = cv->frames[cv->frame].chars; | |||
cv->attrs = cv->frames[cv->frame].attrs; | |||
cv->curattr = cv->frames[cv->frame].curattr; | |||
} | |||