|
- /*
- * cacamoo
- * Copyright (c) 2006 Jean-Yves Lamoureux <jylam@lnxscene.org>
- * All Rights Reserved
- *
- * $Id$
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the Do What The Fuck You Want To
- * Public License, Version 2, as published by Sam Hocevar. See
- * http://sam.zoy.org/wtfpl/COPYING for more details.
- */
-
-
- #include "config.h"
-
- #if defined(HAVE_INTTYPES_H)
- # include <inttypes.h>
- #endif
- #if defined(HAVE_GETOPT_H)
- # include <getopt.h>
- #endif
- #if defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ)
- # include <sys/ioctl.h>
- #endif
-
- #include "cacamoo.h"
- #include <cucul.h>
-
- char const *cacamoo_export = "utf8";
- char const *cacamoo_file = "default";
- char const *cacamoo_dir = "/usr/share/cowsay/cows";
-
- /* Default glyphs */
- char *cacamoo_eyes = "oo";
- char *cacamoo_tongue = " ";
- char *cacamoo_thoughts = "\\";
- char *cacamoo_think = "o";
- char *cacamoo_borg = "==";
- char *cacamoo_tired = "--";
- char *cacamoo_dead = "xx";
- char *cacamoo_greedy = "$$";
- char *cacamoo_parano = "@@";
- char *cacamoo_stoned = "**";
- char *cacamoo_youth = "..";
- char *cacamoo_wired = "OO";
- char cacamoo_use_eyes[3] = {' ',' ',0};
- char cacamoo_use_tongue[3] = {' ',' ',0};
-
- /* String we have to display */
- char *string = NULL;
- /* Wrapped and balloonified */
- char *wrapped = NULL;
-
-
- /* Width */
- unsigned int term_width = 40-1; /* Default for cowsay */
-
- /* Think ? */
- unsigned char think = 0;
-
- /* Unicode */
- unsigned char unicode = 0;
-
-
- int main (int argc, char **argv)
- {
- int i, length;
- char *buffer = NULL;
- unsigned int buffer_size = 0;
- unsigned int new_width = 0;
- char *initial = NULL;
- unsigned int no_wrap = 0;
- cucul_buffer_t* input_buffer;
- cucul_buffer_t* output_buffer;
- cucul_canvas_t* canvas;
- int buf_size;
- char *buf_data;
-
- if ((strstr(argv[0], "cacathink")) != NULL) {
- think = 1;
- }
-
- #if defined(HAVE_GETOPT_H)
- for(;;)
- {
- # ifdef HAVE_GETOPT_LONG
- # define MOREINFO "Try `%s --help' for more information.\n"
- int option_index = 0;
- static struct option long_options[] =
- {
- /* Long option, needs arg, flag, short option */
- { "file", 1, NULL, 'f' },
- { "directory", 1, NULL, 'D' },
- { "width", 1, NULL, 'W' },
- { "no-wrap", 1, NULL, 'n' },
- { "eyes", 1, NULL, 'e' },
- { "tongue", 1, NULL, 'T' },
- { "borg", 1, NULL, 'b' },
- { "tired", 1, NULL, 't' },
- { "dead", 1, NULL, 'd' },
- { "greedy", 1, NULL, 'g' },
- { "parano", 1, NULL, 'p' },
- { "stoned", 1, NULL, 's' },
- { "youth", 1, NULL, 'y' },
- { "wired", 1, NULL, 'w' },
- { "think", 1, NULL, 'O' },
- { "unicode", 1, NULL, 'u' },
- { "version", 0, NULL, 'v' },
- { "list-files", 0, NULL, 'l' },
- { "help", 0, NULL, 'h' },
- { NULL, 0, NULL, 0 }
- };
-
-
-
- int c = getopt_long(argc, argv, "D:f:W:e:T:hvObtdgpsylwnu",
- long_options, &option_index);
- # else
- # define MOREINFO "Try `%s -h' for more information.\n"
- int c = getopt(argc, argv, "D:f:W:hvObtdgpsylwnu");
- # endif
- if(c == -1)
- break;
-
- switch(c)
- {
- case 'h': /* --help */
- usage();
- return 0;
- case 'v': /* --version */
- version();
- return 0;
- case 'f': /* --file*/
- cacamoo_file = optarg;
- break;
- case 'D': /* --directory */
- cacamoo_dir = optarg;
- break;
- case 'e': /* --eyes*/
- cacamoo_eyes = optarg;
- break;
- case 'b': /* --borg*/
- cacamoo_eyes = cacamoo_borg;
- break;
- case 't': /* --tired*/
- cacamoo_eyes = cacamoo_tired;
- break;
- case 'd': /* --dead*/
- cacamoo_eyes = cacamoo_dead;
- break;
- case 'g': /* --greedy*/
- cacamoo_eyes = cacamoo_greedy;
- break;
- case 'p': /* --parano*/
- cacamoo_eyes = cacamoo_parano;
- break;
- case 's': /* --stoned*/
- cacamoo_eyes = cacamoo_stoned;
- break;
- case 'y': /* --youth*/
- cacamoo_eyes = cacamoo_youth;
- break;
- case 'w': /* --wired*/
- cacamoo_eyes = cacamoo_wired;
- break;
- case 'T': /* --tongue */
- cacamoo_tongue = optarg;
- break;
- case 'O': /* --thoughts */
- think = 1;
- break;
- case 'W': /* --width */
- term_width = strtol(optarg, NULL, 10);
- if(term_width && (term_width != 1)) term_width--;
- break;
- case 'l': /* --list-files */
- list_files(".");
- list_files(cacamoo_dir);
- return 0;
- break;
- case 'u': /* --unicode */
- unicode = 1;
- break;
- case 'n': /* --no-wrap */
- no_wrap = 1;
- break;
- case '?':
- printf(MOREINFO, argv[0]);
- return 1;
- default:
- printf("%s: invalid option -- %c\n", argv[0], c);
- printf(MOREINFO, argv[0]);
- return 1;
- }
- }
- #else
- # define MOREINFO "Usage: %s message...\n"
- int optind = 1;
- #endif
-
- if(think)
- cacamoo_thoughts = cacamoo_think;
-
- /* Load rest of commandline */
- for(i = optind, length = 0; i < argc; i++)
- {
- unsigned int k, guessed_len, real_len = 0;
-
- guessed_len = strlen(argv[i]);
-
- if(i > optind)
- string[length++] = ' ';
-
- string = realloc(string, (length + guessed_len + 1));
-
- for(k = 0, real_len = 0; k < guessed_len; real_len++)
- {
- string[length + real_len] = *(argv[i]+k);
- k ++;
- }
- length += real_len;
- }
-
- if(string == NULL) {
- usage();
- return -1;
- }
-
- string[length] = 0;
-
-
- /* Eyes and tongue are 2 characters wide */
- memcpy(cacamoo_use_eyes, cacamoo_eyes, strlen(cacamoo_eyes)>2?2:strlen(cacamoo_eyes));
- memcpy(cacamoo_use_tongue, cacamoo_tongue, strlen(cacamoo_tongue)>2?2:strlen(cacamoo_tongue));
-
- initial = malloc(strlen(string)+1);
- memcpy(initial, string, strlen(string)+1);
- free(string);
-
- wrapped = wrap_string(initial, term_width, &new_width, no_wrap);
- string = wrapped;
-
- buffer = make_caca_from_file(&buffer_size);
- if(buffer == NULL)
- {
- if(string)
- free(string);
- return -1;
- }
-
-
- /* Import our buffer as an ansi (color) one */
- input_buffer = cucul_load_memory(buffer, buffer_size-1);
- if(input_buffer == NULL)
- {
- printf("Can't load file in libcucul !\n");
- return -1;
- }
- canvas = cucul_import_canvas (input_buffer, unicode?"utf8":"ansi");
- if(canvas == NULL)
- {
- printf("Can't load file in libcucul !\n");
- return -1;
- }
- /* Export given canvas to format we want */
- output_buffer = cucul_export_canvas(canvas, "ansi");
- if(output_buffer == NULL)
- {
- printf("Can't export file to text !\n");
- return -1;
- }
-
- buf_size = cucul_get_buffer_size(output_buffer);
- buf_data = cucul_get_buffer_data(output_buffer);
-
- for(i = 0; i < buf_size; i++)
- printf("%c", buf_data[i]);
-
- if(string)
- free(string);
- if(buffer)
- free(buffer);
-
- cucul_free_buffer(input_buffer);
- cucul_free_buffer(output_buffer);
- cucul_free_canvas(canvas);
-
-
- return 0;
- }
-
-
- void list_files(const char *directory)
- {
- struct dirent * dp;
- int count = 0;
- DIR *dir = opendir(directory);
-
-
- for (dp = readdir(dir); dp != NULL; dp = readdir(dir))
- {
- if(!strncmp(&dp->d_name[strlen(dp->d_name)-4], ".cow", 4))
- {
- char name[256];
- memcpy(name, dp->d_name, strlen(dp->d_name)-4);
- name[strlen(dp->d_name)-4] = 0;
- printf("%s ", name);
- count++;
- if(!(count%6))
- printf("\n");
- }
- }
- closedir(dir);
- if(count)
- printf("\n");
- return;
- }
-
- char * make_caca_from_file(unsigned int *size)
- {
- FILE *fp = NULL;
- char filepath[1024];
- unsigned int s = 0;
- char *temp = NULL;
-
- /* Try direct name */
- snprintf(filepath, 1023, "%s", cacamoo_file);
- fp = fopen(filepath, "r");
- if(fp == NULL)
- {
- /* Try direct file + .cow */
- snprintf(filepath, 1023, "%s.cow", cacamoo_file);
- fp = fopen(filepath, "r");
- if(fp == NULL)
- {
- /* Try with complete directory */
- snprintf(filepath, 1023, "%s/%s.cow", cacamoo_dir, cacamoo_file);
- fp = fopen(filepath, "r");
- if(fp == NULL)
- {
- printf("Can't open %s\n", filepath);
- perror("fopen");
- return NULL;
- }
- }
- }
-
-
- fseek(fp, 0, SEEK_END);
- s = ftell(fp);
- fseek(fp, 0, SEEK_SET);
-
-
- temp = malloc(s+1*sizeof(char));
- if(temp == NULL) {
- printf("Not enough memory.\n");
- return NULL;
- }
-
- if(fread(temp, 1, s, fp)!=s)
- {
- printf("Can't read %s\n", filepath);
- perror("fread");
- return NULL;
- }
- temp[s] = '\0';
-
- temp = remove_comments(temp);
- temp = remove_slashes(temp);
-
-
- /* AHAHAH, THAT'S A COOL PERL INTERPRETER ! */
- temp = replace(temp, " = <<\"EOC\";", "");
- temp = replace(temp, " = <<EOC;" , "");
- temp = replace(temp, " = <<EOC" , "");
- temp = replace(temp, " = << EOC" , "");
- temp = replace(temp, "EOC" , "");
- temp = replace(temp, "$eyes" , cacamoo_use_eyes);
- temp = replace(temp, "${eyes}" , cacamoo_use_eyes);
- temp = replace(temp, "$tongue" , cacamoo_use_tongue);
- temp = replace(temp, "${tongue}" , cacamoo_use_tongue);
- temp = replace(temp, "$thoughts" , cacamoo_thoughts);
- temp = replace(temp, "${thoughts}" , cacamoo_thoughts);
- temp = replace(temp, "$the_cow" , (const char*)string);
- temp = replace(temp, "${the_cow}" , (const char*)string);
- *size = strlen(temp)+1;
-
- fclose(fp);
- return temp;
- }
- char *remove_slashes(char *str)
- {
- int i=0, size, r=0;
-
- if(str == NULL) return NULL;
-
- size = strlen(str);
-
- for(i=0; i<size-r; i++)
- {
- if(str[i]== '\\')
- {
- memmove(&str[i], &str[i+1], strlen(str) - i);
- str = realloc(str, (size-r)+1);
- r++;
- }
- }
- return str;
- }
-
-
- char *remove_comments(char *str)
- {
- int size = 0, added=0;
- int i=0, j;
-
- if(str == NULL) return NULL;
-
- size = strlen(str) + 1;
-
- while(i < size)
- {
- if(str[i] == '#') {
- for(j = i; j < size; j++)
-
- if((str[j] == '\n') || (str[j] == '\r') || (str[j] == 0))
- goto hop; // just because I like goto's, break sucks
- hop:
- j++;
- added += (i-j);
- memmove(&str[i], &str[j], size-j);
- i = j - added;
- size -= added;
- str = realloc(str, size);
- str[size-1] = 0;
- i = 0;
- }
- else
- i++;
- }
- return str;
- }
-
- char *replace(char *s1, char *oldpiece, const char *newpiece)
- {
- unsigned int oldlen = strlen(oldpiece), newlen = strlen(newpiece);
- unsigned int i1 = 0, i2 = 0;
- char *s2 = oldlen < newlen ? NULL : s1;
-
- for(;;)
- {
- char *found = strstr(s1 + i1, oldpiece);
- unsigned int tocopy;
-
- if(!found)
- {
- tocopy = strlen(s1 + i1);
- if(oldlen < newlen)
- s2 = realloc(s2, i2 + tocopy + 1);
- memcpy(s2 + i2, s1 + i1, tocopy + 1);
- if(oldlen < newlen)
- free(s1);
- return s2;
- }
-
- tocopy = found - (s1 + i1);
- if(oldlen < newlen)
- s2 = realloc(s2, i2 + tocopy + newlen);
- memmove(s2 + i2, s1 + i1, tocopy);
- memcpy(s2 + i2 + tocopy, newpiece, newlen);
- i1 += tocopy + oldlen;
- i2 += tocopy + newlen;
- }
- }
-
-
- static void version(void)
- {
- printf("cacamoo Copyright 2006 Jean-Yves Lamoureux %s\n", VERSION);
- printf("Internet: <jylam@lnscene.org> Version: 0, date: 30 Sep 2006\n");
- printf("\n");
- }
-
- #if defined(HAVE_GETOPT_H)
- static void usage(void)
- {
- printf("Usage: cacamoo [ -vh ] [ -d cowsdirectory ]\n");
- printf(" [ -f cowfile ] [ -w outputwidth ]\n");
- printf(" [-bdgpstwy] [ message ]\n");
- # ifdef HAVE_GETOPT_LONG
- printf(" -f, --file <cowfile> select the cow\n");
- printf(" -d, --directory <dir> specify cows directory\n");
- printf(" -W, --width <width> set output width\n");
- printf(" -n --no-wrap do not wrap string\n");
- printf(" -O, --think think\n");
- printf(" -h display this help and exit\n");
- printf(" -v, --version output version information and exit\n");
- # else
- printf(" -f <cowfile> select the cow\n");
- printf(" -d <dir> specify cows directory\n");
- printf(" -W <width> set output width\n");
- printf(" -n --no-wrap do not wrap string\n");
- printf(" -O, --think think\n");
- printf(" -h display this help and exit\n");
- printf(" -v output version information and exit\n");
- # endif
- }
- #endif
-
-
- /* AHAHAHAHA please make no comment about this, I was in hurry \o/ */
-
- char *wrap_string(char *buffer, unsigned int width, unsigned int *max_width, int no_wrap)
- {
- unsigned int i = 0, j =0, o = 0, last_space = 0, line = 0, offset = 0;
- unsigned int size = strlen(buffer) + 1, t = 0, rew = 0;
- char *ret = NULL;
- ret = malloc(2);
- *max_width = 0;
-
- /* Wrap string itself */
- if(size > width && !no_wrap)
- {
- while(i<size-1)
- {
- if(buffer[i] == ' ')
- {
- last_space = i;
- rew = o;
- }
- if(offset == width)
- {
- ret = realloc(ret, o+2);
- if(rew)
- o = rew;
- ret[o++] = '\n';
-
- if(last_space) {
-
- if(width - (i - last_space) >= *max_width)
- *max_width = width - (i - last_space);
-
- i = last_space + 1;
- last_space = 0;
- rew = 0;
-
- } else {
- if(width>= *max_width)
- *max_width = width;
- }
-
-
- offset = 0;
- line ++;
- }
- ret = realloc(ret, o+2);
- ret[o++] = buffer[i];
-
- i++;
- offset++;
- }
- if(offset>= *max_width)
- *max_width = offset;
- if(!(*max_width))
- *max_width = size-1;
-
- ret[o] = 0;
- line++;
- }
- else
- {
- *max_width = strlen(buffer);
- if(ret)
- free(ret);
- ret = buffer;
- line = 1;
- }
-
- /* String is wrapped, put spaces after each line */
- if(line != 1)
- {
- char *scaled = malloc(((*max_width+1) * line) + 1);
- int curx = 0;
-
- memset(scaled, ' ', (*max_width * line));
- o = 0;
- for(i = 0; i < strlen(ret); i ++)
- {
- if(ret[i] != '\n')
- {
- scaled[o] = ret[i];
- curx++;
- }
- else
- {
- for(j=o;j<o+(*max_width - curx);j++)
- {
- scaled[j] = ' ';
-
- }
- o += ((*max_width) - curx) -1;
- curx = 0;
- }
- o++;
- }
- for(i = o; i <o+(*max_width - curx); i ++)
- {
- scaled[i] = ' ';
- }
-
- scaled[o+i] = 0;
- if(ret)
- free(ret);
- ret = scaled;
-
-
- /* Put balloon */
- o = 0;
- scaled = malloc((*max_width+5) * (line+2));
-
- scaled[t++] = ' ';
- for(i = 0; i < *max_width+2; i++)
- scaled[t++] = '_';
- scaled[t++] = ' ';
- scaled[t++] = '\n';
-
-
- for(j = 0; j < line ; j++)
- {
- if(think)
- {
- scaled[t++] = '(';
- }
- else
- {
- if(j == 0)
- scaled[t++] = '/';
- else if (j == line -1)
- scaled[t++] = '\\';
- else
- scaled[t++] = '|';
- }
- scaled[t++] = ' ';
-
- for(i = 0; i < *max_width; i++)
- {
- scaled[t++] = ret[o++];
- }
- scaled[t++] = ' ';
- if(think)
- {
- scaled[t++] = ')';
- }
- else
- {
- if(j == 0)
- scaled[t++] = '\\';
- else if (j == line -1)
- scaled[t++] = '/';
- else
- scaled[t++] = '|';
- }
- scaled[t++] = '\n';
- }
-
- scaled[t++] = ' ';
- for(i = 0; i < *max_width+2; i++)
- scaled[t++] = '-';
- scaled[t++] = ' ';
- scaled[t] = 0;
-
- free(ret);
- ret = NULL;
- ret = scaled;
- }
- else
- {
- /* Put ballon */
- char *scaled = malloc((size+4) * 3);
- t = 0;
- *max_width = size -1 ;
- o = 0;
- scaled[t++] = ' ';
- for(i = 0; i < *max_width+2; i++)
- scaled[t++] = '_';
- scaled[t++] = ' ';
- scaled[t++] = '\n';
- if(think)
- scaled[t++] = '(';
- else
- scaled[t++] = '<';
- scaled[t++] = ' ';
- for(i = 0; i < *max_width; i++)
- {
- scaled[t++] = ret[o++];
- }
- scaled[t++] = ' ';
- if(think)
- scaled[t++] = ')';
- else
- scaled[t++] = '>';
-
- scaled[t++] = '\n';
- scaled[t++] = ' ';
- for(i = 0; i < *max_width+2; i++)
- scaled[t++] = '-';
- scaled[t] = '\0';
-
- free(ret);
- ret = NULL;
- ret = scaled;
- }
-
-
- return ret;
- }
|