Changeset 1244
- Timestamp:
- Oct 26, 2006, 10:59:01 PM (17 years ago)
- Location:
- cacamoo/trunk
- Files:
-
- 2 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
cacamoo/trunk/TODO
r1209 r1244 1 Handle COWPATH env var 2 Support color (through ANSI) 3 Support unicode -
cacamoo/trunk/configure.ac
r1209 r1244 26 26 fi 27 27 28 AC_CHECK_HEADERS(getopt.h) 29 30 AC_CHECK_FUNCS(getopt_long, 31 [AC_DEFINE(HAVE_GETOPT_LONG, 1, Define to 1 if you have the `getopt_long' function.)], 32 [AC_CHECK_LIB(gnugetopt, getopt_long, 33 [AC_DEFINE(HAVE_GETOPT_LONG, 1, Define to 1 if you have the `getopt_long' function.) 34 GETOPT_LIBS="${GETOPT_LIBS} -lgnugetopt"])]) 35 AC_SUBST(GETOPT_LIBS) 36 28 37 CACA="no" 29 38 PKG_CHECK_MODULES(cucul, cucul, -
cacamoo/trunk/data/Makefile.am
r1209 r1244 1 EXTRA_DIST = 1 EXTRA_DIST = caca.cow -
cacamoo/trunk/src/Makefile.am
r1209 r1244 2 2 bin_PROGRAMS = cacamoo 3 3 4 cacamoo_SOURCES = main.c 4 cacamoo_SOURCES = main.c cacamoo.h 5 5 cacamoo_CFLAGS = `pkg-config --cflags cucul` 6 6 cacamoo_LDFLAGS = `pkg-config --libs cucul` -
cacamoo/trunk/src/main.c
r1209 r1244 1 1 /* 2 * $Id$ 2 * cacamoo 3 * Copyright (c) 2006 Jean-Yves Lamoureux <jylam@lnxscene.org> 4 * All Rights Reserved 3 5 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 6 * $Id$ 8 7 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the Do What The Fuck You Want To 10 * Public License, Version 2, as published by Sam Hocevar. See 11 * http://sam.zoy.org/wtfpl/COPYING for more details. 17 12 */ 18 13 14 19 15 #include "config.h" 20 16 17 #if defined(HAVE_INTTYPES_H) 18 # include <inttypes.h> 19 #endif 20 #if defined(HAVE_GETOPT_H) 21 # include <getopt.h> 22 #endif 23 #if defined(HAVE_SYS_IOCTL_H) && defined(TIOCGWINSZ) 24 # include <sys/ioctl.h> 25 #endif 26 27 #include "cacamoo.h" 21 28 #include <cucul.h> 29 30 char const *cacamoo_export = "utf8"; 31 char const *cacamoo_file = "default"; 32 char const *cacamoo_dir = "/usr/share/cowsay/cows"; 33 34 /* Default glyphs */ 35 char *cacamoo_eyes = "oo"; 36 char *cacamoo_tongue = " "; 37 char *cacamoo_thoughts = "\\"; 38 char *cacamoo_think = "o"; 39 char *cacamoo_borg = "=="; 40 char *cacamoo_tired = "--"; 41 char *cacamoo_dead = "xx"; 42 char *cacamoo_greedy = "$$"; 43 char *cacamoo_parano = "@@"; 44 char *cacamoo_stoned = "**"; 45 char *cacamoo_youth = ".."; 46 char *cacamoo_wired = "OO"; 47 char cacamoo_use_eyes[3] = {' ',' ',0}; 48 char cacamoo_use_tongue[3] = {' ',' ',0}; 49 50 /* String we have to display */ 51 char *string = NULL; 52 /* Wrapped and balloonified */ 53 char *wrapped = NULL; 54 55 56 /* Width */ 57 unsigned int term_width = 40-1; /* Default for cowsay */ 58 59 /* Think ? */ 60 unsigned char think = 0; 61 22 62 23 63 int main (int argc, char **argv) 24 64 { 65 int i, length; 66 char *buffer = NULL; 67 unsigned int buffer_size = 0; 68 unsigned int new_width = 0; 69 char *initial = NULL; 70 unsigned int no_wrap = 0; 71 cucul_buffer_t* input_buffer; 72 cucul_buffer_t* output_buffer; 73 cucul_canvas_t* canvas; 74 int buf_size; 75 char *buf_data; 76 77 if ((strstr(argv[0], "cacathink")) != NULL) { 78 think = 1; 79 } 80 81 #if defined(HAVE_GETOPT_H) 82 for(;;) 83 { 84 # ifdef HAVE_GETOPT_LONG 85 # define MOREINFO "Try `%s --help' for more information.\n" 86 int option_index = 0; 87 static struct option long_options[] = 88 { 89 /* Long option, needs arg, flag, short option */ 90 { "file", 1, NULL, 'f' }, 91 { "directory", 1, NULL, 'D' }, 92 { "width", 1, NULL, 'W' }, 93 { "no-wrap", 1, NULL, 'n' }, 94 { "eyes", 1, NULL, 'e' }, 95 { "tongue", 1, NULL, 'T' }, 96 { "borg", 1, NULL, 'b' }, 97 { "tired", 1, NULL, 't' }, 98 { "dead", 1, NULL, 'd' }, 99 { "greedy", 1, NULL, 'g' }, 100 { "parano", 1, NULL, 'p' }, 101 { "stoned", 1, NULL, 's' }, 102 { "youth", 1, NULL, 'y' }, 103 { "wired", 1, NULL, 'w' }, 104 { "think", 1, NULL, 'O' }, 105 { "version", 0, NULL, 'v' }, 106 { "help", 0, NULL, 'h' }, 107 { NULL, 0, NULL, 0 } 108 }; 109 110 111 112 int c = getopt_long(argc, argv, "D:f:W:e:T:hvObtdgpsywn", 113 long_options, &option_index); 114 # else 115 # define MOREINFO "Try `%s -h' for more information.\n" 116 int c = getopt(argc, argv, "D:f:W:hvObtdgpsywn"); 117 # endif 118 if(c == -1) 119 break; 120 121 switch(c) 122 { 123 case 'h': /* --help */ 124 usage(); 125 return 0; 126 case 'v': /* --version */ 127 version(); 128 return 0; 129 case 'f': /* --file*/ 130 cacamoo_file = optarg; 131 break; 132 case 'D': /* --directory */ 133 cacamoo_dir = optarg; 134 break; 135 case 'e': /* --eyes*/ 136 cacamoo_eyes = optarg; 137 break; 138 case 'b': /* --borg*/ 139 cacamoo_eyes = cacamoo_borg; 140 break; 141 case 't': /* --tired*/ 142 cacamoo_eyes = cacamoo_tired; 143 break; 144 case 'd': /* --dead*/ 145 cacamoo_eyes = cacamoo_dead; 146 break; 147 case 'g': /* --greedy*/ 148 cacamoo_eyes = cacamoo_greedy; 149 break; 150 case 'p': /* --parano*/ 151 cacamoo_eyes = cacamoo_parano; 152 break; 153 case 's': /* --stoned*/ 154 cacamoo_eyes = cacamoo_stoned; 155 break; 156 case 'y': /* --youth*/ 157 cacamoo_eyes = cacamoo_youth; 158 break; 159 case 'w': /* --wired*/ 160 cacamoo_eyes = cacamoo_wired; 161 break; 162 case 'T': /* --tongue */ 163 cacamoo_tongue = optarg; 164 break; 165 case 'O': /* --thoughts */ 166 think = 1; 167 break; 168 case 'W': /* --width */ 169 term_width = strtol(optarg, NULL, 10); 170 if(term_width && (term_width != 1)) term_width--; 171 break; 172 case 'n': /* --width */ 173 no_wrap = 1; 174 break; 175 case '?': 176 printf(MOREINFO, argv[0]); 177 return 1; 178 default: 179 printf("%s: invalid option -- %c\n", argv[0], c); 180 printf(MOREINFO, argv[0]); 181 return 1; 182 } 183 } 184 #else 185 # define MOREINFO "Usage: %s message...\n" 186 int optind = 1; 187 #endif 188 189 if(think) 190 cacamoo_thoughts = cacamoo_think; 191 192 /* Load rest of commandline */ 193 for(i = optind, length = 0; i < argc; i++) 194 { 195 unsigned int k, guessed_len, real_len = 0; 196 197 guessed_len = strlen(argv[i]); 198 199 if(i > optind) 200 string[length++] = ' '; 201 202 string = realloc(string, (length + guessed_len + 1)); 203 204 for(k = 0, real_len = 0; k < guessed_len; real_len++) 205 { 206 string[length + real_len] = *(argv[i]+k); 207 k ++; 208 } 209 length += real_len; 210 } 211 212 if(string == NULL) { 213 usage(); 214 return -1; 215 } 216 217 string[length] = 0; 218 219 220 /* Eyes and tongue are 2 characters wide */ 221 memcpy(cacamoo_use_eyes, cacamoo_eyes, strlen(cacamoo_eyes)>2?2:strlen(cacamoo_eyes)); 222 memcpy(cacamoo_use_tongue, cacamoo_tongue, strlen(cacamoo_tongue)>2?2:strlen(cacamoo_tongue)); 223 224 initial = malloc(strlen(string)+1); 225 memcpy(initial, string, strlen(string)+1); 226 free(string); 227 228 wrapped = wrap_string(initial, term_width, &new_width, no_wrap); 229 string = wrapped; 230 231 buffer = make_caca_from_file(&buffer_size); 232 if(buffer == NULL) 233 { 234 if(string) 235 free(string); 236 return -1; 237 } 238 239 240 /* Import our buffer as an ansi (color) one */ 241 input_buffer = cucul_load_memory(buffer, buffer_size); 242 canvas = cucul_import_canvas (input_buffer, "ansi"); 243 /* Export given canvas to format we want */ 244 output_buffer = cucul_export_canvas(canvas, "irc"); 245 246 buf_size = cucul_get_buffer_size(output_buffer); 247 buf_data = cucul_get_buffer_data(output_buffer); 248 249 for(i = 0; i < buf_size; i++) 250 printf("%c", buf_data[i]); 251 252 if(string) 253 free(string); 254 if(buffer) 255 free(buffer); 256 25 257 return 0; 26 258 } 27 259 260 261 char * make_caca_from_file(unsigned int *size) 262 { 263 FILE *fp = NULL; 264 char filepath[1024]; 265 unsigned int s = 0; 266 char *temp = NULL; 267 char *temp2 = NULL; 268 269 /* Try direct name */ 270 snprintf(filepath, 1023, "%s", cacamoo_file); 271 fp = fopen(filepath, "r"); 272 if(fp == NULL) 273 { 274 /* Try direct file + .cow */ 275 snprintf(filepath, 1023, "%s.cow", cacamoo_file); 276 fp = fopen(filepath, "r"); 277 if(fp == NULL) 278 { 279 /* Try with complete directory */ 280 snprintf(filepath, 1023, "%s/%s.cow", cacamoo_dir, cacamoo_file); 281 fp = fopen(filepath, "r"); 282 if(fp == NULL) 283 { 284 printf("Can't open %s\n", filepath); 285 perror("fopen"); 286 return NULL; 287 } 288 } 289 } 290 291 292 fseek(fp, 0, SEEK_END); 293 s = ftell(fp); 294 fseek(fp, 0, SEEK_SET); 295 296 297 temp = malloc(s+1*sizeof(char)); 298 if(temp == NULL) { 299 printf("Not enough memory.\n"); 300 return NULL; 301 } 302 303 if(fread(temp, 1, s, fp)!=s) 304 { 305 printf("Can't read %s\n", filepath); 306 perror("fread"); 307 return NULL; 308 } 309 310 311 temp = remove_comments(temp); 312 temp = remove_slashes(temp); 313 314 315 /* AHAHAH, THAT'S A COOL PERL INTERPRETER ! */ 316 temp2 = replace(temp, " = <<\"EOC\";", ""); 317 if(temp2 != temp) 318 { 319 free(temp); 320 temp = temp2; 321 } 322 temp2 = replace(temp, " = <<EOC;" , ""); 323 if(temp2 != temp) 324 { 325 free(temp); 326 temp = temp2; 327 } 328 temp2 = replace(temp, " = <<EOC" , ""); 329 if(temp2 != temp) 330 { 331 free(temp); 332 temp = temp2; 333 } 334 temp2 = replace(temp, " = << EOC" , ""); 335 if(temp2 != temp) 336 { 337 free(temp); 338 temp = temp2; 339 } 340 temp2 = replace(temp, "EOC" , ""); 341 if(temp2 != temp) 342 { 343 free(temp); 344 temp = temp2; 345 } 346 temp2 = replace(temp, "$eyes" , cacamoo_use_eyes); 347 if(temp2 != temp) 348 { 349 free(temp); 350 temp = temp2; 351 } 352 temp2 = replace(temp, "${eyes}" , cacamoo_use_eyes); 353 if(temp2 != temp) 354 { 355 free(temp); 356 temp = temp2; 357 } 358 359 temp2 = replace(temp, "$tongue" , cacamoo_use_tongue); 360 if(temp2 != temp) 361 { 362 free(temp); 363 temp = temp2; 364 } 365 temp2 = replace(temp, "${tongue}" , cacamoo_use_tongue); 366 if(temp2 != temp) 367 { 368 free(temp); 369 temp = temp2; 370 } 371 372 temp2 = replace(temp, "$thoughts" , cacamoo_thoughts); 373 if(temp2 != temp) 374 { 375 free(temp); 376 temp = temp2; 377 } 378 temp2 = replace(temp, "${thoughts}" , cacamoo_thoughts); 379 if(temp2 != temp) 380 { 381 free(temp); 382 temp = temp2; 383 } 384 385 temp2 = replace(temp, "$the_cow" , (const char*)string); 386 if(temp2 != temp) 387 { 388 free(temp); 389 temp = temp2; 390 } 391 temp2 = replace(temp, "${the_cow}" , (const char*)string); 392 if(temp2 != temp) 393 { 394 free(temp); 395 temp = temp2; 396 } 397 398 *size = strlen(temp)+1; 399 400 401 fclose(fp); 402 return temp; 403 } 404 char *remove_slashes(char *str) 405 { 406 int i=0, size, r=0; 407 408 if(str == NULL) return NULL; 409 410 size = strlen(str); 411 412 for(i=0; i<size-r; i++) 413 { 414 if(str[i]== '\\') 415 { 416 memmove(&str[i], &str[i+1], strlen(str) - i); 417 str = realloc(str, (size-r)+1); 418 r++; 419 } 420 } 421 return str; 422 } 423 424 425 char *remove_comments(char *str) 426 { 427 int size = 0, added=0; 428 int i=0, j; 429 430 if(str == NULL) return NULL; 431 432 size = strlen(str) + 1; 433 434 while(i < size) 435 { 436 if(str[i] == '#') { 437 for(j = i; j < size; j++) 438 439 if((str[j] == '\n') || (str[j] == '\r') || (str[j] == 0)) 440 goto hop; // just because I like goto's, break sucks 441 hop: 442 j++; 443 added += (i-j); 444 memmove(&str[i], &str[j], size-j); 445 i = j - added; 446 size -= added; 447 str = realloc(str, size); 448 str[size-1] = 0; 449 i = 0; 450 } 451 else 452 i++; 453 } 454 return str; 455 } 456 457 458 char *replace(char *str, char *oldpiece, const char *newpiece) 459 { 460 int str_index, newstr_index, oldpiece_index, end, 461 new_len, old_len, cpy_len; 462 char *c = NULL; 463 char *newstr = NULL; 464 465 if(oldpiece==NULL || newpiece==NULL) 466 return NULL; 467 468 if ((c = (char *) strstr(str, oldpiece)) == NULL) { 469 return str; 470 } 471 472 newstr = malloc(1024); 473 474 if(newstr == NULL) 475 { 476 return str; 477 } 478 479 new_len = strlen(newpiece); 480 old_len = strlen(oldpiece); 481 end = strlen(str) - old_len; 482 oldpiece_index = c - str; 483 484 newstr_index = 0; 485 str_index = 0; 486 while(str_index <= end && c != NULL) 487 { 488 /* Copy characters from the left of matched pattern occurence */ 489 cpy_len = oldpiece_index-str_index; 490 strncpy(newstr+newstr_index, str+str_index, cpy_len); 491 newstr_index += cpy_len; 492 str_index += cpy_len; 493 494 /* Copy replacement characters instead of matched pattern */ 495 strcpy(newstr+newstr_index, newpiece); 496 newstr_index += new_len; 497 str_index += old_len; 498 499 /* Check for another pattern match */ 500 if((c = (char *) strstr(str+str_index, oldpiece)) != NULL) 501 oldpiece_index = c - str; 502 503 504 } 505 /* Copy remaining characters from the right of last matched pattern */ 506 strcpy(newstr+newstr_index, str+str_index); 507 508 return newstr; 509 } 510 511 512 static void version(void) 513 { 514 printf("cacamoo Copyright 2006 Jean-Yves Lamoureux %s\n", VERSION); 515 printf("Internet: <jylam@lnscene.org> Version: 0, date: 30 Sep 2006\n"); 516 printf("\n"); 517 } 518 519 #if defined(HAVE_GETOPT_H) 520 static void usage(void) 521 { 522 printf("Usage: cacamoo [ -vh ] [ -d cowsdirectory ]\n"); 523 printf(" [ -f cowfile ] [ -w outputwidth ]\n"); 524 printf(" [-bdgpstwy] [ message ]\n"); 525 # ifdef HAVE_GETOPT_LONG 526 printf(" -f, --file <cowfile> select the cow\n"); 527 printf(" -d, --directory <dir> specify cows directory\n"); 528 printf(" -W, --width <width> set output width\n"); 529 printf(" -n --no-wrap do not wrap string\n"); 530 printf(" -O, --think think\n"); 531 printf(" -h display this help and exit\n"); 532 printf(" -v, --version output version information and exit\n"); 533 # else 534 printf(" -f <cowfile> select the cow\n"); 535 printf(" -d <dir> specify cows directory\n"); 536 printf(" -W <width> set output width\n"); 537 printf(" -n --no-wrap do not wrap string\n"); 538 printf(" -O, --think think\n"); 539 printf(" -h display this help and exit\n"); 540 printf(" -v output version information and exit\n"); 541 # endif 542 } 543 #endif 544 545 546 /* AHAHAHAHA please make no comment about this, I was in hurry \o/ */ 547 548 char *wrap_string(char *buffer, unsigned int width, unsigned int *max_width, int no_wrap) 549 { 550 unsigned int i = 0, j =0, o = 0, last_space = 0, line = 0, offset = 0; 551 unsigned int size = strlen(buffer) + 1, t = 0, rew = 0; 552 char *ret = NULL; 553 ret = malloc(2); 554 *max_width = 0; 555 556 /* Wrap string itself */ 557 if(size > width && !no_wrap) 558 { 559 while(i<size-1) 560 { 561 if(buffer[i] == ' ') 562 { 563 last_space = i; 564 rew = o; 565 } 566 if(offset == width) 567 { 568 ret = realloc(ret, o+2); 569 if(rew) 570 o = rew; 571 ret[o++] = '\n'; 572 573 if(last_space) { 574 575 if(width - (i - last_space) >= *max_width) 576 *max_width = width - (i - last_space); 577 578 i = last_space + 1; 579 last_space = 0; 580 rew = 0; 581 582 } else { 583 if(width>= *max_width) 584 *max_width = width; 585 } 586 587 588 offset = 0; 589 line ++; 590 } 591 ret = realloc(ret, o+2); 592 ret[o++] = buffer[i]; 593 594 i++; 595 offset++; 596 } 597 if(offset>= *max_width) 598 *max_width = offset; 599 if(!(*max_width)) 600 *max_width = size-1; 601 602 ret[o] = 0; 603 line++; 604 } 605 else 606 { 607 *max_width = strlen(buffer); 608 if(ret) 609 free(ret); 610 ret = buffer; 611 line = 1; 612 } 613 614 /* String is wrapped, put spaces after each line */ 615 if(line != 1) 616 { 617 char *scaled = malloc(((*max_width+1) * line) + 1); 618 int curx = 0; 619 620 memset(scaled, ' ', (*max_width * line)); 621 o = 0; 622 for(i = 0; i < strlen(ret); i ++) 623 { 624 if(ret[i] != '\n') 625 { 626 scaled[o] = ret[i]; 627 curx++; 628 } 629 else 630 { 631 for(j=o;j<o+(*max_width - curx);j++) 632 { 633 scaled[j] = ' '; 634 635 } 636 o += ((*max_width) - curx) -1; 637 curx = 0; 638 } 639 o++; 640 } 641 for(i = o; i <o+(*max_width - curx); i ++) 642 { 643 scaled[i] = ' '; 644 } 645 646 scaled[o+i] = 0; 647 if(ret) 648 free(ret); 649 ret = scaled; 650 651 652 /* Put balloon */ 653 o = 0; 654 scaled = malloc((*max_width+5) * (line+2)); 655 656 scaled[t++] = ' '; 657 for(i = 0; i < *max_width+2; i++) 658 scaled[t++] = '_'; 659 scaled[t++] = ' '; 660 scaled[t++] = '\n'; 661 662 663 for(j = 0; j < line ; j++) 664 { 665 if(think) 666 { 667 scaled[t++] = '('; 668 } 669 else 670 { 671 if(j == 0) 672 scaled[t++] = '/'; 673 else if (j == line -1) 674 scaled[t++] = '\\'; 675 else 676 scaled[t++] = '|'; 677 } 678 scaled[t++] = ' '; 679 680 for(i = 0; i < *max_width; i++) 681 { 682 scaled[t++] = ret[o++]; 683 } 684 scaled[t++] = ' '; 685 if(think) 686 { 687 scaled[t++] = ')'; 688 } 689 else 690 { 691 if(j == 0) 692 scaled[t++] = '\\'; 693 else if (j == line -1) 694 scaled[t++] = '/'; 695 else 696 scaled[t++] = '|'; 697 } 698 scaled[t++] = '\n'; 699 } 700 701 scaled[t++] = ' '; 702 for(i = 0; i < *max_width+2; i++) 703 scaled[t++] = '-'; 704 scaled[t++] = ' '; 705 scaled[t] = 0; 706 707 free(ret); 708 ret = NULL; 709 ret = scaled; 710 } 711 else 712 { 713 /* Put ballon */ 714 char *scaled = malloc((size+4) * 3); 715 t = 0; 716 *max_width = size -1 ; 717 o = 0; 718 scaled[t++] = ' '; 719 for(i = 0; i < *max_width+2; i++) 720 scaled[t++] = '_'; 721 scaled[t++] = ' '; 722 scaled[t++] = '\n'; 723 if(think) 724 scaled[t++] = '('; 725 else 726 scaled[t++] = '<'; 727 scaled[t++] = ' '; 728 for(i = 0; i < *max_width; i++) 729 { 730 scaled[t++] = ret[o++]; 731 } 732 scaled[t++] = ' '; 733 if(think) 734 scaled[t++] = ')'; 735 else 736 scaled[t++] = '>'; 737 738 scaled[t++] = '\n'; 739 scaled[t++] = ' '; 740 for(i = 0; i < *max_width+2; i++) 741 scaled[t++] = '-'; 742 743 free(ret); 744 ret = NULL; 745 ret = scaled; 746 } 747 748 749 return ret; 750 } 751
Note: See TracChangeset
for help on using the changeset viewer.