~ubuntu-branches/ubuntu/raring/libcaca/raring

« back to all changes in this revision

Viewing changes to caca/string.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hocevar
  • Date: 2010-02-08 01:40:59 UTC
  • mfrom: (1.1.8 upstream) (4.1.6 sid)
  • Revision ID: james.westby@ubuntu.com-20100208014059-9q4av8pze8p7uw3i
Tags: 0.99.beta17-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 *  libcaca       Colour ASCII-Art library
3
 
 *  Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
 
3
 *  Copyright (c) 2002-2009 Sam Hocevar <sam@hocevar.net>
4
4
 *                All Rights Reserved
5
5
 *
6
 
 *  $Id$
7
 
 *
8
6
 *  This library is free software. It comes without any warranty, to
9
7
 *  the extent permitted by applicable law. You can redistribute it
10
8
 *  and/or modify it under the terms of the Do What The Fuck You Want
68
66
 *  \param cv A handle to the libcaca canvas.
69
67
 *  \return The cursor's X coordinate.
70
68
 */
71
 
int caca_get_cursor_x(caca_canvas_t const *cv)
 
69
int caca_wherex(caca_canvas_t const *cv)
72
70
{
73
71
    return cv->frames[cv->frame].x;
74
72
}
82
80
 *  \param cv A handle to the libcaca canvas.
83
81
 *  \return The cursor's Y coordinate.
84
82
 */
85
 
int caca_get_cursor_y(caca_canvas_t const *cv)
 
83
int caca_wherey(caca_canvas_t const *cv)
86
84
{
87
85
    return cv->frames[cv->frame].y;
88
86
}
101
99
 *  characters is undefined. To print a sequence of bytes forming an UTF-8
102
100
 *  character instead of an UTF-32 character, use the caca_put_str() function.
103
101
 *
 
102
 *  This function returns the width of the printed character. If it is a
 
103
 *  fullwidth character, 2 is returned. Otherwise, 1 is returned.
 
104
 *
104
105
 *  This function never fails.
105
106
 *
106
107
 *  \param cv A handle to the libcaca canvas.
107
108
 *  \param x X coordinate.
108
109
 *  \param y Y coordinate.
109
110
 *  \param ch The character to print.
110
 
 *  \return This function always returns 0.
 
111
 *  \return The width of the printed character: 2 for a fullwidth character,
 
112
 *          1 otherwise.
111
113
 */
112
114
int caca_put_char(caca_canvas_t *cv, int x, int y, uint32_t ch)
113
115
{
114
116
    uint32_t *curchar, *curattr, attr;
115
 
    int fullwidth;
116
 
 
117
 
    if(x >= (int)cv->width || y < 0 || y >= (int)cv->height)
118
 
        return 0;
 
117
    int fullwidth, xmin, xmax, ret;
119
118
 
120
119
    if(ch == CACA_MAGIC_FULLWIDTH)
121
 
        return 0;
 
120
        return 1;
122
121
 
123
122
    fullwidth = caca_utf32_is_fullwidth(ch);
 
123
    ret = fullwidth ? 2 : 1;
 
124
 
 
125
    if(x >= (int)cv->width || y < 0 || y >= (int)cv->height)
 
126
        return ret;
124
127
 
125
128
    if(x == -1 && fullwidth)
126
129
    {
129
132
        fullwidth = 0;
130
133
    }
131
134
    else if(x < 0)
132
 
        return 0;
 
135
        return ret;
133
136
 
134
137
    curchar = cv->chars + x + y * cv->width;
135
138
    curattr = cv->attrs + x + y * cv->width;
136
139
    attr = cv->curattr;
137
140
 
 
141
    xmin = xmax = x;
 
142
 
138
143
    /* When overwriting the right part of a fullwidth character,
139
144
     * replace its left part with a space. */
140
145
    if(x && curchar[0] == CACA_MAGIC_FULLWIDTH)
 
146
    {
141
147
        curchar[-1] = ' ';
 
148
        xmin--;
 
149
    }
142
150
 
143
151
    if(fullwidth)
144
152
    {
146
154
            ch = ' ';
147
155
        else
148
156
        {
 
157
            xmax++;
 
158
 
149
159
            /* When overwriting the left part of a fullwidth character,
150
160
             * replace its right part with a space. */
151
161
            if(x + 2 < (int)cv->width && curchar[2] == CACA_MAGIC_FULLWIDTH)
 
162
            {
152
163
                curchar[2] = ' ';
 
164
                xmax++;
 
165
            }
153
166
 
154
167
            curchar[1] = CACA_MAGIC_FULLWIDTH;
155
168
            curattr[1] = attr;
160
173
        /* When overwriting the left part of a fullwidth character,
161
174
         * replace its right part with a space. */
162
175
        if(x + 1 != (int)cv->width && curchar[1] == CACA_MAGIC_FULLWIDTH)
 
176
        {
163
177
            curchar[1] = ' ';
 
178
            xmax++;
 
179
        }
164
180
    }
165
181
 
 
182
    /* Only add a dirty rectangle if we are pasting a different character
 
183
     * or attribute at that place. This does not account for inconsistencies
 
184
     * in the canvas, ie. if CACA_MAGIC_FULLWIDTH lies at illegal places,
 
185
     * but it's the caller's responsibility not to corrupt the contents. */
 
186
    if(!cv->dirty_disabled
 
187
        && (curchar[0] != ch || curattr[0] != attr))
 
188
        caca_add_dirty_rect(cv, xmin, y, xmax - xmin + 1, 1);
 
189
 
166
190
    curchar[0] = ch;
167
191
    curattr[0] = attr;
168
192
 
169
 
    return 0;
 
193
    return ret;
170
194
}
171
195
 
172
196
/** \brief Get the Unicode character at the given coordinates.
189
213
 *  \param cv A handle to the libcaca canvas.
190
214
 *  \param x X coordinate.
191
215
 *  \param y Y coordinate.
192
 
 *  \return This function always returns 0.
 
216
 *  \return The Unicode character at the given coordinates.
193
217
 */
194
218
uint32_t caca_get_char(caca_canvas_t const *cv, int x, int y)
195
219
{
209
233
 *  See caca_put_char() for more information on how fullwidth characters
210
234
 *  are handled when overwriting each other or at the canvas' boundaries.
211
235
 *
 
236
 *  This function returns the number of cells printed by the string. It is
 
237
 *  not the number of characters printed, because fullwidth characters
 
238
 *  account for two cells.
 
239
 *
212
240
 *  This function never fails.
213
241
 *
214
242
 *  \param cv A handle to the libcaca canvas.
215
243
 *  \param x X coordinate.
216
244
 *  \param y Y coordinate.
217
245
 *  \param s The string to print.
218
 
 *  \return This function always returns 0.
 
246
 *  \return The number of cells printed.
219
247
 */
220
248
int caca_put_str(caca_canvas_t *cv, int x, int y, char const *s)
221
249
{
222
250
    size_t rd;
 
251
    int len = 0;
223
252
 
224
253
    if(y < 0 || y >= (int)cv->height || x >= (int)cv->width)
225
 
        return 0;
226
 
 
227
 
    while(*s && x < -1)
228
254
    {
229
 
        x += caca_utf32_is_fullwidth(caca_utf8_to_utf32(s, &rd)) ? 2 : 1;
230
 
        s += rd;
 
255
        while(*s)
 
256
        {
 
257
            len += caca_utf32_is_fullwidth(caca_utf8_to_utf32(s, &rd)) ? 2 : 1;
 
258
            s += rd;
 
259
        }
 
260
        return len;
231
261
    }
232
262
 
233
 
    while(*s && x < (int)cv->width)
 
263
    while(*s)
234
264
    {
235
265
        uint32_t ch = caca_utf8_to_utf32(s, &rd);
236
 
        caca_put_char(cv, x, y, ch);
237
 
        x += caca_utf32_is_fullwidth(ch) ? 2 : 1;
 
266
 
 
267
        if(x + len >= -1 && x + len < (int)cv->width)
 
268
            caca_put_char(cv, x + len, y, ch);
 
269
 
 
270
        len += caca_utf32_is_fullwidth(ch) ? 2 : 1;
238
271
        s += rd;
239
272
    }
240
273
 
241
 
    return 0;
 
274
    return len;
242
275
}
243
276
 
244
277
/** \brief Print a formated string.
249
282
 *  accordingly if it is too long. The syntax of the format string is the
250
283
 *  same as for the C printf() function.
251
284
 *
 
285
 *  This function returns the number of cells printed by the string. It is
 
286
 *  not the number of characters printed, because fullwidth characters
 
287
 *  account for two cells.
 
288
 *
252
289
 *  This function never fails.
253
290
 *
254
291
 *  \param cv A handle to the libcaca canvas.
256
293
 *  \param y Y coordinate.
257
294
 *  \param format The format string to print.
258
295
 *  \param ... Arguments to the format string.
259
 
 *  \return This function always returns 0.
 
296
 *  \return The number of cells printed.
260
297
 */
261
298
int caca_printf(caca_canvas_t *cv, int x, int y, char const *format, ...)
262
299
{
 
300
    va_list args;
 
301
    int ret;
 
302
    va_start(args, format);
 
303
    ret = caca_vprintf(cv, x, y, format, args);
 
304
    va_end(args);
 
305
    return ret;
 
306
}
 
307
 
 
308
/** \brief Print a formated string (va_list version).
 
309
 *
 
310
 *  Format a string at the given coordinates, using the default foreground
 
311
 *  and background values. The coordinates may be outside the canvas
 
312
 *  boundaries (eg. a negative Y coordinate) and the string will be cropped
 
313
 *  accordingly if it is too long. The syntax of the format string is the
 
314
 *  same as for the C vprintf() function.
 
315
 *
 
316
 *  This function returns the number of cells printed by the string. It is
 
317
 *  not the number of characters printed, because fullwidth characters
 
318
 *  account for two cells.
 
319
 *
 
320
 *  This function never fails.
 
321
 *
 
322
 *  \param cv A handle to the libcaca canvas.
 
323
 *  \param x X coordinate.
 
324
 *  \param y Y coordinate.
 
325
 *  \param format The format string to print.
 
326
 *  \param args A va_list containting the arguments to the format string.
 
327
 *  \return The number of cells printed.
 
328
 */
 
329
int caca_vprintf(caca_canvas_t *cv, int x, int y, char const *format,
 
330
                 va_list args)
 
331
{
263
332
    char tmp[BUFSIZ];
264
333
    char *buf = tmp;
265
 
    va_list args;
266
 
 
267
 
    if(y < 0 || y >= (int)cv->height || x >= (int)cv->width)
268
 
        return 0;
 
334
    int ret;
269
335
 
270
336
    if(cv->width - x + 1 > BUFSIZ)
271
337
        buf = malloc(cv->width - x + 1);
272
338
 
273
 
    va_start(args, format);
274
339
#if defined(HAVE_VSNPRINTF)
275
340
    vsnprintf(buf, cv->width - x + 1, format, args);
276
341
#else
277
342
    vsprintf(buf, format, args);
278
343
#endif
279
344
    buf[cv->width - x] = '\0';
280
 
    va_end(args);
281
345
 
282
 
    caca_put_str(cv, x, y, buf);
 
346
    ret = caca_put_str(cv, x, y, buf);
283
347
 
284
348
    if(buf != tmp)
285
349
        free(buf);
286
350
 
287
 
    return 0;
 
351
    return ret;
288
352
}
289
353
 
290
354
/** \brief Clear the canvas.
307
371
        cv->attrs[n] = attr;
308
372
    }
309
373
 
 
374
    if(!cv->dirty_disabled)
 
375
        caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);
 
376
 
310
377
    return 0;
311
378
}
312
379
 
375
442
 *  \return 0 in case of success, -1 if an error occurred.
376
443
 */
377
444
int caca_blit(caca_canvas_t *dst, int x, int y,
378
 
               caca_canvas_t const *src, caca_canvas_t const *mask)
 
445
              caca_canvas_t const *src, caca_canvas_t const *mask)
379
446
{
380
 
    int i, j, starti, startj, endi, endj;
 
447
    int i, j, starti, startj, endi, endj, stride, bleed_left, bleed_right;
381
448
 
382
449
    if(mask && (src->width != mask->width || src->height != mask->height))
383
450
    {
392
459
    startj = y < 0 ? -y : 0;
393
460
    endi = (x + src->width >= dst->width) ? dst->width - x : src->width;
394
461
    endj = (y + src->height >= dst->height) ? dst->height - y : src->height;
 
462
    stride = endi - starti;
395
463
 
396
464
    if(starti > src->width || startj > src->height
397
465
        || starti >= endi || startj >= endj)
398
466
        return 0;
399
467
 
 
468
    bleed_left = bleed_right = 0;
 
469
 
400
470
    for(j = startj; j < endj; j++)
401
471
    {
402
472
        int dstix = (j + y) * dst->width + starti + x;
403
473
        int srcix = j * src->width + starti;
404
 
        int stride = endi - starti;
405
474
 
406
475
        /* FIXME: we are ignoring the mask here */
407
476
        if((starti + x) && dst->chars[dstix] == CACA_MAGIC_FULLWIDTH)
 
477
        {
408
478
            dst->chars[dstix - 1] = ' ';
 
479
            bleed_left = 1;
 
480
        }
409
481
 
410
482
        if(endi + x < dst->width
411
483
                && dst->chars[dstix + stride] == CACA_MAGIC_FULLWIDTH)
 
484
        {
412
485
            dst->chars[dstix + stride] = ' ';
 
486
            bleed_right = 1;
 
487
        }
413
488
 
414
489
        if(mask)
415
490
        {
418
493
                if(mask->chars[srcix + i] == (uint32_t)' ')
419
494
                    continue;
420
495
 
421
 
                dst->chars[dstix + i] = src->chars[srcix + i];
422
 
                dst->attrs[dstix + i] = src->attrs[srcix + i];
 
496
                if(dst->chars[dstix + i] != src->chars[srcix + i] ||
 
497
                   dst->attrs[dstix + i] != src->attrs[srcix + i])
 
498
                {
 
499
                    dst->chars[dstix + i] = src->chars[srcix + i];
 
500
                    dst->attrs[dstix + i] = src->attrs[srcix + i];
 
501
                    if(!dst->dirty_disabled)
 
502
                        caca_add_dirty_rect(dst, x + starti + i, y + j, 1, 1);
 
503
                }
423
504
            }
424
505
        }
425
506
        else
426
507
        {
427
 
            memcpy(dst->chars + dstix, src->chars + srcix, stride * 4);
428
 
            memcpy(dst->attrs + dstix, src->attrs + srcix, stride * 4);
 
508
            if(memcmp(dst->chars + dstix, src->chars + srcix, stride * 4) ||
 
509
               memcmp(dst->attrs + dstix, src->attrs + srcix, stride * 4))
 
510
            {
 
511
                /* FIXME be more precise ? */
 
512
                memcpy(dst->chars + dstix, src->chars + srcix, stride * 4);
 
513
                memcpy(dst->attrs + dstix, src->attrs + srcix, stride * 4);
 
514
                if(!dst->dirty_disabled)
 
515
                    caca_add_dirty_rect(dst, x + starti, y + j, stride, 1);
 
516
            }
429
517
        }
430
518
 
431
519
        /* Fix split fullwidth chars */
436
524
            dst->chars[dstix + stride - 1] = ' ';
437
525
    }
438
526
 
 
527
 
439
528
    return 0;
440
529
}
441
530
 
499
588
    caca_set_frame(cv, saved_f);
500
589
    _caca_load_frame_info(cv);
501
590
 
 
591
    /* FIXME: this may be optimised somewhat */
 
592
    if(!cv->dirty_disabled)
 
593
        caca_add_dirty_rect(cv, 0, 0, cv->width, cv->height);
 
594
 
502
595
    return 0;
503
596
}
504
597
 
507
600
 */
508
601
 
509
602
int cucul_gotoxy(cucul_canvas_t *, int, int) CACA_ALIAS(caca_gotoxy);
510
 
int cucul_get_cursor_x(cucul_canvas_t const *) CACA_ALIAS(caca_get_cursor_x);
511
 
int cucul_get_cursor_y(cucul_canvas_t const *) CACA_ALIAS(caca_get_cursor_y);
 
603
int cucul_get_cursor_x(cucul_canvas_t const *) CACA_ALIAS(caca_wherex);
 
604
int cucul_get_cursor_y(cucul_canvas_t const *) CACA_ALIAS(caca_wherey);
 
605
int caca_get_cursor_x(caca_canvas_t const *) CACA_ALIAS(caca_wherex);
 
606
int caca_get_cursor_y(caca_canvas_t const *) CACA_ALIAS(caca_wherey);
512
607
int cucul_put_char(cucul_canvas_t *, int, int, uint32_t)
513
608
         CACA_ALIAS(caca_put_char);
514
609
uint32_t cucul_get_char(cucul_canvas_t const *, int, int)