@@ -390,11 +390,10 @@ int cucul_set_canvas_boundaries(cucul_canvas_t *cv, int x, int y, | |||||
cucul_set_canvas_frame(new, f); | cucul_set_canvas_frame(new, f); | ||||
cucul_blit(new, -x, -y, cv, NULL); | 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)); | memcpy(cv, new, sizeof(cucul_canvas_t)); | ||||
free(new); | free(new); | ||||
@@ -68,29 +68,24 @@ cucul_canvas_t * cucul_create_canvas(unsigned int width, unsigned int height) | |||||
cv->frame = 0; | cv->frame = 0; | ||||
cv->framecount = 1; | cv->framecount = 1; | ||||
cv->allchars = malloc(sizeof(uint32_t *)); | |||||
if(!cv->allchars) | |||||
cv->frames = malloc(sizeof(struct cucul_frame)); | |||||
if(!cv->frames) | |||||
{ | { | ||||
free(cv); | free(cv); | ||||
goto nomem; | 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(_cucul_set_canvas_size(cv, width, height) < 0) | ||||
{ | { | ||||
#if defined(HAVE_ERRNO_H) | #if defined(HAVE_ERRNO_H) | ||||
int saved_errno = errno; | int saved_errno = errno; | ||||
#endif | #endif | ||||
free(cv->allattrs); | |||||
free(cv->allchars); | |||||
free(cv->frames); | |||||
free(cv); | free(cv); | ||||
#if defined(HAVE_ERRNO_H) | #if defined(HAVE_ERRNO_H) | ||||
errno = saved_errno; | errno = saved_errno; | ||||
@@ -200,12 +195,11 @@ int cucul_free_canvas(cucul_canvas_t *cv) | |||||
for(f = 0; f < cv->framecount; f++) | 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); | free(cv); | ||||
return 0; | 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++) | 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) | #if defined(HAVE_ERRNO_H) | ||||
errno = ENOMEM; | errno = ENOMEM; | ||||
@@ -284,12 +278,12 @@ int _cucul_set_canvas_size(cucul_canvas_t *cv, unsigned int width, | |||||
* we will overwrite information. */ | * we will overwrite information. */ | ||||
for(f = 0; f < cv->framecount; f++) | 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--; ) | 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--; ) | 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++) | 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++) | 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++) | 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 */ | /* Zero the bottom of the screen */ | ||||
for(x = (height - old_height) * width; x--; ) | 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. */ | /* 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++) | 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) | #if defined(HAVE_ERRNO_H) | ||||
errno = ENOMEM; | 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; | return 0; | ||||
} | } | ||||
@@ -18,24 +18,32 @@ | |||||
# include <inttypes.h> | # include <inttypes.h> | ||||
#endif | #endif | ||||
struct cucul_canvas | |||||
struct cucul_frame | |||||
{ | { | ||||
/* Canvas size */ | |||||
/* Frame size */ | |||||
unsigned int width, height; | unsigned int width, height; | ||||
/* Shortcut to the active frame */ | |||||
/* Cell information */ | |||||
uint32_t *chars; | uint32_t *chars; | ||||
uint32_t *attrs; | uint32_t *attrs; | ||||
/* Frame information */ | |||||
unsigned int frame, framecount; | |||||
uint32_t **allchars; | |||||
uint32_t **allattrs; | |||||
/* Painting context */ | /* Painting context */ | ||||
uint32_t curattr; | uint32_t curattr; | ||||
}; | |||||
struct cucul_canvas | |||||
{ | |||||
/* Frame information */ | |||||
unsigned int frame, framecount; | |||||
struct cucul_frame *frames; | |||||
unsigned int refcount; | 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 | struct cucul_buffer | ||||
@@ -30,6 +30,9 @@ | |||||
#include "cucul.h" | #include "cucul.h" | ||||
#include "cucul_internals.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. | /** \brief Get the number of frames in a canvas. | ||||
* | * | ||||
* Return the current canvas' frame count. | * Return the current canvas' frame count. | ||||
@@ -69,10 +72,9 @@ int cucul_set_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||||
return -1; | return -1; | ||||
} | } | ||||
save_frame_info(cv); | |||||
cv->frame = frame; | cv->frame = frame; | ||||
cv->chars = cv->allchars[cv->frame]; | |||||
cv->attrs = cv->allattrs[cv->frame]; | |||||
load_frame_info(cv); | |||||
return 0; | 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 | * The frame index indicates where the frame should be inserted. Valid | ||||
* values range from 0 to the current canvas frame count. If the frame | * 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. | * frame is appended at the end of the canvas. | ||||
* | * | ||||
* The active frame does not change, but its index may be renumbered due | * 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; | frame = cv->framecount; | ||||
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--) | 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) | if(cv->frame >= frame) | ||||
cv->frame++; | cv->frame++; | ||||
cv->chars = cv->allchars[cv->frame]; | |||||
cv->attrs = cv->allattrs[cv->frame]; | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -170,27 +169,47 @@ int cucul_free_canvas_frame(cucul_canvas_t *cv, unsigned int frame) | |||||
return -1; | 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++) | 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->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) | if(cv->frame > frame) | ||||
cv->frame--; | cv->frame--; | ||||
else if(cv->frame == frame) | else if(cv->frame == frame) | ||||
{ | |||||
cv->frame = 0; | cv->frame = 0; | ||||
cv->chars = cv->allchars[cv->frame]; | |||||
cv->attrs = cv->allattrs[cv->frame]; | |||||
load_frame_info(cv); | |||||
} | |||||
return 0; | 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; | |||||
} | |||||