source: libcaca/trunk/caca/frame.c @ 2821

Last change on this file since 2821 was 2821, checked in by Sam Hocevar, 11 years ago

Starting refactoring to get rid of libcucul. The initial reason for the
split is rendered moot by the plugin system: when enabled, binaries do
not link directly with libX11 or libGL. I hope this is a step towards
more consisteny and clarity.

  • Property svn:keywords set to Id
File size: 7.0 KB
Line 
1/*
2 *  libcaca       Colour ASCII-Art library
3 *  Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id: frame.c 2821 2008-09-27 13:12:46Z sam $
7 *
8 *  This library is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 *  This file contains a small framework for canvas frame management.
17 */
18
19#include "config.h"
20
21#if !defined(__KERNEL__)
22#   include <stdio.h>
23#   include <stdlib.h>
24#   include <string.h>
25#endif
26
27#include "caca.h"
28#include "caca_internals.h"
29
30/** \brief Get the number of frames in a canvas.
31 *
32 *  Return the current canvas' frame count.
33 *
34 *  This function never fails.
35 *
36 *  \param cv A libcaca canvas
37 *  \return The frame count
38 */
39int caca_get_frame_count(caca_canvas_t const *cv)
40{
41    return cv->framecount;
42}
43
44/** \brief Activate a given canvas frame.
45 *
46 *  Set the active canvas frame. All subsequent drawing operations will
47 *  be performed on that frame. The current painting context set by
48 *  caca_set_attr() is inherited.
49 *
50 *  If the frame index is outside the canvas' frame range, nothing happens.
51 *
52 *  If an error occurs, -1 is returned and \b errno is set accordingly:
53 *  - \c EINVAL Requested frame is out of range.
54 *
55 *  \param cv A libcaca canvas
56 *  \param id The canvas frame to activate
57 *  \return 0 in case of success, -1 if an error occurred.
58 */
59int caca_set_frame(caca_canvas_t *cv, int id)
60{
61    if(id < 0 || id >= cv->framecount)
62    {
63        seterrno(EINVAL);
64        return -1;
65    }
66
67    _caca_save_frame_info(cv);
68    cv->frame = id;
69    _caca_load_frame_info(cv);
70
71    return 0;
72}
73
74/** \brief Get the current frame's name.
75 *
76 *  Return the current frame's name. The returned string is valid until
77 *  the frame is deleted or caca_set_frame_name() is called to change
78 *  the frame name again.
79 *
80 *  This function never fails.
81 *
82 *  \param cv A libcaca canvas.
83 *  \return The current frame's name.
84 */
85char const *caca_get_frame_name(caca_canvas_t const *cv)
86{
87    return cv->frames[cv->frame].name;
88}
89
90/** \brief Set the current frame's name.
91 *
92 *  Set the current frame's name. Upon creation, a frame has a default name
93 *  of \c "frame#xxxxxxxx" where \c xxxxxxxx is a self-incrementing
94 *  hexadecimal number.
95 *
96 *  If an error occurs, -1 is returned and \b errno is set accordingly:
97 *  - \c ENOMEM Not enough memory to allocate new frame.
98 *
99 *  \param cv A libcaca canvas.
100 *  \param name The name to give to the current frame.
101 *  \return 0 in case of success, -1 if an error occurred.
102 */
103int caca_set_frame_name(caca_canvas_t *cv, char const *name)
104{
105    char *newname = strdup(name);
106
107    if(!newname)
108    {
109        seterrno(ENOMEM);
110        return -1;
111    }
112
113    free(cv->frames[cv->frame].name);
114    cv->frames[cv->frame].name = newname;
115
116    return 0;
117}
118
119/** \brief Add a frame to a canvas.
120 *
121 *  Create a new frame within the given canvas. Its contents and attributes
122 *  are copied from the currently active frame.
123 *
124 *  The frame index indicates where the frame should be inserted. Valid
125 *  values range from 0 to the current canvas frame count. If the frame
126 *  index is greater than or equals the current canvas frame count, the new
127 *  frame is appended at the end of the canvas. If the frame index is less
128 *  than zero, the new frame is inserted at index 0.
129 *
130 *  The active frame does not change, but its index may be renumbered due
131 *  to the insertion.
132 *
133 *  If an error occurs, -1 is returned and \b errno is set accordingly:
134 *  - \c ENOMEM Not enough memory to allocate new frame.
135 *
136 *  \param cv A libcaca canvas
137 *  \param id The index where to insert the new frame
138 *  \return 0 in case of success, -1 if an error occurred.
139 */
140int caca_create_frame(caca_canvas_t *cv, int id)
141{
142    int size = cv->width * cv->height;
143    int f;
144
145    if(id < 0)
146        id = 0;
147    else if(id > cv->framecount)
148        id = cv->framecount;
149
150    cv->framecount++;
151    cv->frames = realloc(cv->frames,
152                         sizeof(struct caca_frame) * cv->framecount);
153
154    for(f = cv->framecount - 1; f > id; f--)
155        cv->frames[f] = cv->frames[f - 1];
156
157    if(cv->frame >= id)
158        cv->frame++;
159
160    cv->frames[id].width = cv->width;
161    cv->frames[id].height = cv->height;
162    cv->frames[id].chars = malloc(size * sizeof(uint32_t));
163    memcpy(cv->frames[id].chars, cv->chars, size * sizeof(uint32_t));
164    cv->frames[id].attrs = malloc(size * sizeof(uint32_t));
165    memcpy(cv->frames[id].attrs, cv->attrs, size * sizeof(uint32_t));
166    cv->frames[id].curattr = cv->curattr;
167
168    cv->frames[id].x = cv->frames[cv->frame].x;
169    cv->frames[id].y = cv->frames[cv->frame].y;
170    cv->frames[id].handlex = cv->frames[cv->frame].handlex;
171    cv->frames[id].handley = cv->frames[cv->frame].handley;
172
173    cv->frames[id].name = strdup("frame#--------");
174    sprintf(cv->frames[id].name + 6, "%.08x", ++cv->autoinc);
175
176    return 0;
177}
178
179/** \brief Remove a frame from a canvas.
180 *
181 *  Delete a frame from a given canvas.
182 *
183 *  The frame index indicates the frame to delete. Valid values range from
184 *  0 to the current canvas frame count minus 1. If the frame index is
185 *  greater than or equals the current canvas frame count, the last frame
186 *  is deleted.
187 *
188 *  If the active frame is deleted, frame 0 becomes the new active frame.
189 *  Otherwise, the active frame does not change, but its index may be
190 *  renumbered due to the deletion.
191 *
192 *  If an error occurs, -1 is returned and \b errno is set accordingly:
193 *  - \c EINVAL Requested frame is out of range, or attempt to delete the
194 *    last frame of the canvas.
195 *
196 *  \param cv A libcaca canvas
197 *  \param id The index of the frame to delete
198 *  \return 0 in case of success, -1 if an error occurred.
199 */
200int caca_free_frame(caca_canvas_t *cv, int id)
201{
202    int f;
203
204    if(id < 0 || id >= cv->framecount)
205    {
206        seterrno(EINVAL);
207        return -1;
208    }
209
210    if(cv->framecount == 1)
211    {
212        seterrno(EINVAL);
213        return -1;
214    }
215
216    free(cv->frames[id].chars);
217    free(cv->frames[id].attrs);
218    free(cv->frames[id].name);
219
220    for(f = id + 1; f < cv->framecount; f++)
221        cv->frames[f - 1] = cv->frames[f];
222
223    cv->framecount--;
224    cv->frames = realloc(cv->frames,
225                         sizeof(struct caca_frame) * cv->framecount);
226
227    if(cv->frame > id)
228        cv->frame--;
229    else if(cv->frame == id)
230    {
231        cv->frame = 0;
232        _caca_load_frame_info(cv);
233    }
234
235    return 0;
236}
237
238/*
239 * XXX: the following functions are local.
240 */
241
242void _caca_save_frame_info(caca_canvas_t *cv)
243{
244    cv->frames[cv->frame].width = cv->width;
245    cv->frames[cv->frame].height = cv->height;
246
247    cv->frames[cv->frame].curattr = cv->curattr;
248}
249
250void _caca_load_frame_info(caca_canvas_t *cv)
251{
252    cv->width = cv->frames[cv->frame].width;
253    cv->height = cv->frames[cv->frame].height;
254
255    cv->chars = cv->frames[cv->frame].chars;
256    cv->attrs = cv->frames[cv->frame].attrs;
257
258    cv->curattr = cv->frames[cv->frame].curattr;
259}
260
Note: See TracBrowser for help on using the repository browser.