| @@ -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; | |||||
| } | |||||