amatrix

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
git clone git://git.kocotian.pl/amatrix.git
Log | Files | Refs | README | LICENSE

cmatrix.c (25335B)


      1 /*
      2     cmatrix.c
      3 
      4     Copyright (C) 1999-2017 Chris Allegretta
      5     Copyright (C) 2017-Present Abishek V Ashok
      6 
      7     This file is part of cmatrix.
      8 
      9     cmatrix is free software: you can redistribute it and/or modify
     10     it under the terms of the GNU General Public License as published by
     11     the Free Software Foundation, either version 3 of the License, or
     12     (at your option) any later version.
     13 
     14     cmatrix is distributed in the hope that it will be useful,
     15     but WITHOUT ANY WARRANTY; without even the implied warranty of
     16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17     GNU General Public License for more details.
     18 
     19     You should have received a copy of the GNU General Public License
     20     along with cmatrix. If not, see <http://www.gnu.org/licenses/>.
     21 
     22 */
     23 
     24 #include <errno.h>
     25 #include <stdio.h>
     26 #include <stdlib.h>
     27 #include <stdarg.h>
     28 #include <string.h>
     29 #include <time.h>
     30 #include <sys/types.h>
     31 #include <sys/stat.h>
     32 #include <fcntl.h>
     33 #include <signal.h>
     34 #include <locale.h>
     35 #ifdef _WIN32
     36 #define WIN32_LEAN_AND_MEAN
     37 #include <windows.h>
     38 #endif
     39 
     40 #ifndef EXCLUDE_CONFIG_H
     41 #include "config.h"
     42 #endif
     43 
     44 #ifdef HAVE_GETOPT_H
     45 #include <getopt.h>
     46 #endif
     47 
     48 #ifdef HAVE_NCURSES_H
     49 #include <ncurses.h>
     50 #else
     51 #include <curses.h>
     52 #endif
     53 
     54 #ifdef HAVE_SYS_IOCTL_H
     55 #include <sys/ioctl.h>
     56 #endif
     57 
     58 #ifdef HAVE_UNISTD_H
     59 #include <unistd.h>
     60 #endif
     61 
     62 #ifdef HAVE_TERMIOS_H
     63 #include <termios.h>
     64 #elif defined(HAVE_TERMIO_H)
     65 #include <termio.h>
     66 #endif
     67 
     68 /* Matrix typedef */
     69 typedef struct cmatrix {
     70     int val;
     71     bool is_head;
     72 } cmatrix;
     73 
     74 /* Global variables */
     75 int console = 0;
     76 int xwindow = 0;
     77 int lock = 0;
     78 cmatrix **matrix = (cmatrix **) NULL;
     79 int *length = NULL;  /* Length of cols in each line */
     80 int *spaces = NULL;  /* Spaces left to fill */
     81 int *updates = NULL; /* What does this do again? */
     82 #ifndef _WIN32
     83 volatile sig_atomic_t signal_status = 0; /* Indicates a caught signal */
     84 #endif
     85 
     86 int va_system(char *str, ...) {
     87 
     88     va_list ap;
     89     char buf[133];
     90 
     91     va_start(ap, str);
     92     vsnprintf(buf, sizeof(buf), str, ap);
     93     va_end(ap);
     94     return system(buf);
     95 }
     96 
     97 /* What we do when we're all set to exit */
     98 void finish(void) {
     99     curs_set(1);
    100     clear();
    101     refresh();
    102     resetty();
    103     endwin();
    104     if (console) {
    105 #ifdef HAVE_CONSOLECHARS
    106         va_system("consolechars -d");
    107 #elif defined(HAVE_SETFONT)
    108         va_system("setfont");
    109 #endif
    110     }
    111     exit(0);
    112 }
    113 
    114 /* What we do when we're all set to exit */
    115 void c_die(char *msg, ...) {
    116 
    117     va_list ap;
    118 
    119     curs_set(1);
    120     clear();
    121     refresh();
    122     resetty();
    123     endwin();
    124 
    125     if (console) {
    126 #ifdef HAVE_CONSOLECHARS
    127         va_system("consolechars -d");
    128 #elif defined(HAVE_SETFONT)
    129         va_system("setfont");
    130 #endif
    131     }
    132 
    133     va_start(ap, msg);
    134     vfprintf(stderr, msg, ap);
    135     va_end(ap);
    136     exit(0);
    137 }
    138 
    139 void usage(void) {
    140     printf(" Usage: cmatrix -[abBcfhlsmVxk] [-u delay] [-C color] [-t tty] [-M message]\n");
    141     printf(" -a: Asynchronous scroll\n");
    142     printf(" -b: Bold characters on\n");
    143     printf(" -B: All bold characters (overrides -b)\n");
    144     printf(" -c: Use Japanese characters as seen in the original matrix. Requires appropriate fonts\n");
    145     printf(" -f: Force the linux $TERM type to be on\n");
    146     printf(" -l: Linux mode (uses matrix console font)\n");
    147     printf(" -L: Lock mode (can be closed from another terminal)\n");
    148     printf(" -o: Use old-style scrolling\n");
    149     printf(" -h: Print usage and exit\n");
    150     printf(" -n: No bold characters (overrides -b and -B, default)\n");
    151     printf(" -s: \"Screensaver\" mode, exits on first keystroke\n");
    152     printf(" -x: X window mode, use if your xterm is using mtx.pcf\n");
    153     printf(" -V: Print version information and exit\n");
    154     printf(" -M [message]: Prints your message in the center of the screen. Overrides -L's default message.\n");
    155     printf(" -u delay (0 - 10, default 4): Screen update delay\n");
    156     printf(" -C [color]: Use this color for matrix (default green)\n");
    157     printf(" -r: rainbow mode\n");
    158     printf(" -m: lambda mode\n");
    159     printf(" -k: Characters change while scrolling. (Works without -o opt.)\n");
    160     printf(" -t [tty]: Set tty to use\n");
    161 }
    162 
    163 void version(void) {
    164     printf(" CMatrix version %s (compiled %s, %s)\n",
    165         VERSION, __TIME__, __DATE__);
    166     printf("Email: abishekvashok@gmail.com\n");
    167     printf("Web: https://github.com/abishekvashok/cmatrix\n");
    168 }
    169 
    170 
    171 /* nmalloc from nano by Big Gaute */
    172 void *nmalloc(size_t howmuch) {
    173     void *r;
    174 
    175     if (!(r = malloc(howmuch))) {
    176         c_die("CMatrix: malloc: out of memory!");
    177     }
    178 
    179     return r;
    180 }
    181 
    182 /* Initialize the global variables */
    183 void var_init() {
    184     int i, j;
    185 
    186     if (matrix != NULL) {
    187         free(matrix[0]);
    188         free(matrix);
    189     }
    190 
    191     matrix = nmalloc(sizeof(cmatrix *) * (LINES + 1));
    192     matrix[0] = nmalloc(sizeof(cmatrix) * (LINES + 1) * COLS);
    193     for (i = 1; i <= LINES; i++) {
    194         matrix[i] = matrix[i - 1] + COLS;
    195     }
    196 
    197     if (length != NULL) {
    198         free(length);
    199     }
    200     length = nmalloc(COLS * sizeof(int));
    201 
    202     if (spaces != NULL) {
    203         free(spaces);
    204     }
    205     spaces = nmalloc(COLS* sizeof(int));
    206 
    207     if (updates != NULL) {
    208         free(updates);
    209     }
    210     updates = nmalloc(COLS * sizeof(int));
    211 
    212     /* Make the matrix */
    213     for (i = 0; i <= LINES; i++) {
    214         for (j = 0; j <= COLS - 1; j += 2) {
    215             matrix[i][j].val = -1;
    216         }
    217     }
    218 
    219     for (j = 0; j <= COLS - 1; j += 2) {
    220         /* Set up spaces[] array of how many spaces to skip */
    221         spaces[j] = (int) rand() % LINES + 1;
    222 
    223         /* And length of the stream */
    224         length[j] = (int) rand() % (LINES - 3) + 3;
    225 
    226         /* Sentinel value for creation of new objects */
    227         matrix[1][j].val = ' ';
    228 
    229         /* And set updates[] array for update speed. */
    230         updates[j] = (int) rand() % 3 + 1;
    231     }
    232 
    233 }
    234 
    235 #ifndef _WIN32
    236 void sighandler(int s) {
    237     signal_status = s;
    238 }
    239 #endif
    240 
    241 void resize_screen(void) {
    242 #ifdef _WIN32
    243     BOOL result;
    244     HANDLE hStdHandle;
    245     CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
    246 
    247     hStdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    248     if(hStdHandle == INVALID_HANDLE_VALUE)
    249         return;
    250 #else
    251     char *tty;
    252     int fd = 0;
    253     int result = 0;
    254     struct winsize win;
    255 
    256     tty = ttyname(0);
    257     if (!tty) {
    258         return;
    259 #endif
    260 #ifdef _WIN32
    261     result = GetConsoleScreenBufferInfo(hStdHandle, &csbiInfo);
    262     if(!result)
    263         return;
    264     LINES = csbiInfo.dwSize.Y;
    265     COLS = csbiInfo.dwSize.X;
    266 #else
    267     }
    268     fd = open(tty, O_RDWR);
    269     if (fd == -1) {
    270         return;
    271     }
    272     result = ioctl(fd, TIOCGWINSZ, &win);
    273     if (result == -1) {
    274         return;
    275     }
    276 
    277     COLS = win.ws_col;
    278     LINES = win.ws_row;
    279 #endif
    280 
    281     if(LINES <10){
    282         LINES = 10;
    283     }
    284     if(COLS <10){
    285         COLS = 10;
    286     }
    287 
    288 #ifdef HAVE_RESIZETERM
    289     resizeterm(LINES, COLS);
    290 #ifdef HAVE_WRESIZE
    291     if (wresize(stdscr, LINES, COLS) == ERR) {
    292         c_die("Cannot resize window!");
    293     }
    294 #endif /* HAVE_WRESIZE */
    295 #endif /* HAVE_RESIZETERM */
    296 
    297     var_init();
    298     /* Do these because width may have changed... */
    299     clear();
    300     refresh();
    301 }
    302 
    303 int main(int argc, char *argv[]) {
    304     int i, y, z, optchr, keypress;
    305     int j = 0;
    306     int count = 0;
    307     int screensaver = 0;
    308     int asynch = 0;
    309     int bold = 0;
    310     int force = 0;
    311     int firstcoldone = 0;
    312     int oldstyle = 0;
    313     int random = 0;
    314     int update = 4;
    315     int highnum = 0;
    316     int mcolor = COLOR_GREEN;
    317     int rainbow = 0;
    318     int lambda = 0;
    319     int randnum = 0;
    320     int randmin = 0;
    321     int pause = 0;
    322     int classic = 0;
    323     int changes = 0;
    324     char *msg = "";
    325     char *tty = NULL;
    326 
    327     srand((unsigned) time(NULL));
    328     setlocale(LC_ALL, "");
    329 
    330     /* Many thanks to morph- (morph@jmss.com) for this getopt patch */
    331     opterr = 0;
    332     while ((optchr = getopt(argc, argv, "abBcfhlLnrosmxkVM:u:C:t:")) != EOF) {
    333         switch (optchr) {
    334         case 's':
    335             screensaver = 1;
    336             break;
    337         case 'a':
    338             asynch = 1;
    339             break;
    340         case 'b':
    341             if (bold != 2) {
    342                 bold = 1;
    343             }
    344             break;
    345         case 'B':
    346             bold = 2;
    347             break;
    348         case 'C':
    349             if (!strcasecmp(optarg, "green")) {
    350                 mcolor = COLOR_GREEN;
    351             } else if (!strcasecmp(optarg, "red")) {
    352                 mcolor = COLOR_RED;
    353             } else if (!strcasecmp(optarg, "blue")) {
    354                 mcolor = COLOR_BLUE;
    355             } else if (!strcasecmp(optarg, "white")) {
    356                 mcolor = COLOR_WHITE;
    357             } else if (!strcasecmp(optarg, "yellow")) {
    358                 mcolor = COLOR_YELLOW;
    359             } else if (!strcasecmp(optarg, "cyan")) {
    360                 mcolor = COLOR_CYAN;
    361             } else if (!strcasecmp(optarg, "magenta")) {
    362                 mcolor = COLOR_MAGENTA;
    363             } else if (!strcasecmp(optarg, "black")) {
    364                 mcolor = COLOR_BLACK;
    365             } else {
    366                 c_die(" Invalid color selection\n Valid "
    367                        "colors are green, red, blue, "
    368                        "white, yellow, cyan, magenta " "and black.\n");
    369             }
    370             break;
    371         case 'c':
    372             classic = 1;
    373             break;
    374         case 'f':
    375             force = 1;
    376             break;
    377         case 'l':
    378             console = 1;
    379             break;
    380         case 'L':
    381             lock = 1;
    382             //if -M was used earlier, don't override it
    383             if (0 == strncmp(msg, "", 1)) {
    384                 msg = "Computer locked.";
    385             }
    386             break;
    387         case 'M':
    388             msg = strdup(optarg);
    389             break;
    390         case 'n':
    391             bold = -1;
    392             break;
    393         case 'h':
    394         case '?':
    395             usage();
    396             exit(0);
    397         case 'o':
    398             oldstyle = 1;
    399             break;
    400         case 'u':
    401             update = atoi(optarg);
    402             break;
    403         case 'x':
    404             xwindow = 1;
    405             break;
    406         case 'V':
    407             version();
    408             exit(0);
    409         case 'r':
    410             rainbow = 1;
    411             break;
    412         case 'm':
    413             lambda = 1;
    414             break;
    415         case 'k':
    416             changes = 1;
    417             break;
    418         case 't':
    419             tty = optarg;
    420             break;
    421         }
    422     }
    423 
    424     if (force && strcmp("linux", getenv("TERM"))) {
    425 #ifdef _WIN32
    426         SetEnvironmentVariableW(L"TERM", L"linux");
    427 #else
    428         /* setenv is much more safe to use than putenv */
    429         setenv("TERM", "linux", 1);
    430 #endif
    431     }
    432     if (tty) {
    433         FILE *ftty = fopen(tty, "r+");
    434         if (!ftty) {
    435             fprintf(stderr, "cmatrix: error: '%s' couldn't be opened: %s.\n",
    436                     tty, strerror(errno));
    437             exit(EXIT_FAILURE);
    438         }
    439         SCREEN *ttyscr;
    440         ttyscr = newterm(NULL, ftty, ftty);
    441         if (ttyscr == NULL)
    442             exit(EXIT_FAILURE);
    443         set_term(ttyscr);
    444     } else
    445         initscr();
    446     savetty();
    447     nonl();
    448 #ifdef _WIN32
    449     raw();
    450 #else
    451     cbreak();
    452 #endif
    453     noecho();
    454     timeout(0);
    455     leaveok(stdscr, TRUE);
    456     curs_set(0);
    457 #ifndef _WIN32
    458     signal(SIGINT, sighandler);
    459     signal(SIGQUIT, sighandler);
    460     signal(SIGWINCH, sighandler);
    461     signal(SIGTSTP, sighandler);
    462 #endif
    463 
    464 if (console) {
    465 #ifdef HAVE_CONSOLECHARS
    466         if (va_system("consolechars -f matrix") != 0) {
    467             c_die
    468                 (" There was an error running consolechars. Please make sure the\n"
    469                  " consolechars program is in your $PATH.  Try running \"consolechars -f matrix\" by hand.\n");
    470         }
    471 #elif defined(HAVE_SETFONT)
    472         if (va_system("setfont matrix") != 0) {
    473             c_die
    474                 (" There was an error running setfont. Please make sure the\n"
    475                  " setfont program is in your $PATH.  Try running \"setfont matrix\" by hand.\n");
    476         }
    477 #else
    478         c_die(" Unable to use both \"setfont\" and \"consolechars\".\n");
    479 #endif
    480 }
    481     if (has_colors()) {
    482         start_color();
    483         /* Add in colors, if available */
    484 #ifdef HAVE_USE_DEFAULT_COLORS
    485         if (use_default_colors() != ERR) {
    486             init_pair(COLOR_BLACK, -1, -1);
    487             init_pair(COLOR_GREEN, COLOR_GREEN, -1);
    488             init_pair(COLOR_WHITE, COLOR_WHITE, -1);
    489             init_pair(COLOR_RED, COLOR_RED, -1);
    490             init_pair(COLOR_CYAN, COLOR_CYAN, -1);
    491             init_pair(COLOR_MAGENTA, COLOR_MAGENTA, -1);
    492             init_pair(COLOR_BLUE, COLOR_BLUE, -1);
    493             init_pair(COLOR_YELLOW, COLOR_YELLOW, -1);
    494         } else {
    495 #else
    496         { /* Hack to deal the after effects of else in HAVE_USE_DEFAULT_COLOURS*/
    497 #endif
    498             init_pair(COLOR_BLACK, COLOR_BLACK, COLOR_BLACK);
    499             init_pair(COLOR_GREEN, COLOR_GREEN, COLOR_BLACK);
    500             init_pair(COLOR_WHITE, COLOR_WHITE, COLOR_BLACK);
    501             init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK);
    502             init_pair(COLOR_CYAN, COLOR_CYAN, COLOR_BLACK);
    503             init_pair(COLOR_MAGENTA, COLOR_MAGENTA, COLOR_BLACK);
    504             init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_BLACK);
    505             init_pair(COLOR_YELLOW, COLOR_YELLOW, COLOR_BLACK);
    506         }
    507     }
    508 
    509 	randmin = 65;
    510 	highnum = 66;
    511     randnum = highnum - randmin;
    512 
    513     var_init();
    514 
    515     while (1) {
    516 #ifndef _WIN32
    517         /* Check for signals */
    518         if (signal_status == SIGINT || signal_status == SIGQUIT) {
    519             if(lock != 1)
    520                 finish();
    521             /* exits */
    522         }
    523         if (signal_status == SIGWINCH) {
    524             resize_screen();
    525             signal_status = 0;
    526         }
    527 
    528         if(signal_status == SIGTSTP){
    529             if(lock != 1)
    530                     finish();
    531         }
    532 #endif
    533 
    534         count++;
    535         if (count > 4) {
    536             count = 1;
    537         }
    538 
    539         if ((keypress = wgetch(stdscr)) != ERR) {
    540             if (screensaver == 1) {
    541 #ifdef USE_TIOCSTI
    542                 char *str = malloc(0);
    543                 size_t str_len = 0;
    544                 do {
    545                     str = realloc(str, str_len + 1);
    546                     str[str_len++] = keypress;
    547                 } while ((keypress = wgetch(stdscr)) != ERR);
    548                 size_t i;
    549                 for (i = 0; i < str_len; i++)
    550                     ioctl(STDIN_FILENO, TIOCSTI, (char*)(str + i));
    551                 free(str);
    552 #endif
    553                 finish();
    554             } else {
    555                 switch (keypress) {
    556 #ifdef _WIN32
    557                 case 3: /* Ctrl-C. Fall through */
    558 #endif
    559                 case 'q':
    560                     if(lock != 1)
    561                         finish();
    562                     break;
    563                 case 'a':
    564                     asynch = 1 - asynch;
    565                     break;
    566                 case 'b':
    567                     bold = 1;
    568                     break;
    569                 case 'B':
    570                     bold = 2;
    571                     break;
    572                 case 'L':
    573                     lock = 1;
    574                     break;
    575                 case 'n':
    576                     bold = 0;
    577                     break;
    578                 case '0': /* Fall through */
    579                 case '1': /* Fall through */
    580                 case '2': /* Fall through */
    581                 case '3': /* Fall through */
    582                 case '4': /* Fall through */
    583                 case '5': /* Fall through */
    584                 case '6': /* Fall through */
    585                 case '7': /* Fall through */
    586                 case '8': /* Fall through */
    587                 case '9':
    588                     update = keypress - 48;
    589                     break;
    590                 case '!':
    591                     mcolor = COLOR_RED;
    592                     rainbow = 0;
    593                     break;
    594                 case '@':
    595                     mcolor = COLOR_GREEN;
    596                     rainbow = 0;
    597                     break;
    598                 case '#':
    599                     mcolor = COLOR_YELLOW;
    600                     rainbow = 0;
    601                     break;
    602                 case '$':
    603                     mcolor = COLOR_BLUE;
    604                     rainbow = 0;
    605                     break;
    606                 case '%':
    607                     mcolor = COLOR_MAGENTA;
    608                     rainbow = 0;
    609                     break;
    610                 case 'r':
    611                      rainbow = 1;
    612                      break;
    613                 case 'm':
    614                      lambda = !lambda;
    615                      break;
    616                 case '^':
    617                     mcolor = COLOR_CYAN;
    618                     rainbow = 0;
    619                     break;
    620                 case '&':
    621                     mcolor = COLOR_WHITE;
    622                     rainbow = 0;
    623                     break;
    624                 case 'p':
    625                 case 'P':
    626                     pause = (pause == 0)?1:0;
    627                     break;
    628 
    629                 }
    630             }
    631         }
    632         for (j = 0; j <= COLS - 1; j += 2) {
    633             if ((count > updates[j] || asynch == 0) && pause == 0) {
    634 
    635                 /* I dont like old-style scrolling, yuck */
    636                 if (oldstyle) {
    637                     for (i = LINES - 1; i >= 1; i--) {
    638                         matrix[i][j].val = matrix[i - 1][j].val;
    639                     }
    640                     random = (int) rand() % (randnum + 8) + randmin;
    641 
    642                     if (matrix[1][j].val == 0) {
    643                         matrix[0][j].val = 1;
    644                     } else if (matrix[1][j].val == ' '
    645                              || matrix[1][j].val == -1) {
    646                         if (spaces[j] > 0) {
    647                             matrix[0][j].val = ' ';
    648                             spaces[j]--;
    649                         } else {
    650 
    651                             /* Random number to determine whether head of next column
    652                                of chars has a white 'head' on it. */
    653 
    654                             if (((int) rand() % 3) == 1) {
    655                                 matrix[0][j].val = 0;
    656                             } else {
    657                                 matrix[0][j].val = (int) rand() % randnum + randmin;
    658                             }
    659                             spaces[j] = (int) rand() % LINES + 1;
    660                         }
    661                     } else if (random > highnum && matrix[1][j].val != 1) {
    662                         matrix[0][j].val = ' ';
    663                     } else {
    664                         matrix[0][j].val = (int) rand() % randnum + randmin;
    665                     }
    666 
    667                 } else { /* New style scrolling (default) */
    668                     if (matrix[0][j].val == -1 && matrix[1][j].val == ' '
    669                         && spaces[j] > 0) {
    670                         spaces[j]--;
    671                     } else if (matrix[0][j].val == -1
    672                         && matrix[1][j].val == ' ') {
    673                         length[j] = (int) rand() % (LINES - 3) + 3;
    674                         matrix[0][j].val = (int) rand() % randnum + randmin;
    675 
    676                         spaces[j] = (int) rand() % LINES + 1;
    677                     }
    678                     i = 0;
    679                     y = 0;
    680                     firstcoldone = 0;
    681                     while (i <= LINES) {
    682 
    683                         /* Skip over spaces */
    684                         while (i <= LINES && (matrix[i][j].val == ' ' ||
    685                                matrix[i][j].val == -1)) {
    686                             i++;
    687                         }
    688 
    689                         if (i > LINES) {
    690                             break;
    691                         }
    692 
    693                         /* Go to the head of this column */
    694                         z = i;
    695                         y = 0;
    696                         while (i <= LINES && (matrix[i][j].val != ' ' &&
    697                                matrix[i][j].val != -1)) {
    698                             matrix[i][j].is_head = false;
    699                             if(changes) {
    700                                 if(rand() % 8 == 0)
    701                                     matrix[i][j].val = (int) rand() % randnum + randmin;
    702                             }
    703                             i++;
    704                             y++;
    705                         }
    706 
    707                         if (i > LINES) {
    708                             matrix[z][j].val = ' ';
    709                             continue;
    710                         }
    711 
    712                         matrix[i][j].val = (int) rand() % randnum + randmin;
    713                         matrix[i][j].is_head = true;
    714 
    715                         /* If we're at the top of the column and it's reached its
    716                            full length (about to start moving down), we do this
    717                            to get it moving.  This is also how we keep segments not
    718                            already growing from growing accidentally =>
    719                          */
    720                         if (y > length[j] || firstcoldone) {
    721                             matrix[z][j].val = ' ';
    722                             matrix[0][j].val = -1;
    723                         }
    724                         firstcoldone = 1;
    725                         i++;
    726                     }
    727                 }
    728             }
    729             /* A simple hack */
    730             if (!oldstyle) {
    731                 y = 1;
    732                 z = LINES;
    733             } else {
    734                 y = 0;
    735                 z = LINES - 1;
    736             }
    737             for (i = y; i <= z; i++) {
    738                 move(i - y, j);
    739 
    740                 if (matrix[i][j].val == 0 || (matrix[i][j].is_head && !rainbow)) {
    741                     if (console || xwindow) {
    742                         attron(A_ALTCHARSET);
    743                     }
    744                     attron(COLOR_PAIR(COLOR_WHITE));
    745                     if (bold) {
    746                         attron(A_BOLD);
    747                     }
    748                     if (matrix[i][j].val == 0) {
    749                         if (console || xwindow) {
    750                             addch(183);
    751                         } else {
    752                             addch('&');
    753                         }
    754                     } else if (matrix[i][j].val == -1) {
    755                         addch(' ');
    756                     } else {
    757                         addch(matrix[i][j].val);
    758                     }
    759 
    760                     attroff(COLOR_PAIR(COLOR_WHITE));
    761                     if (bold) {
    762                         attroff(A_BOLD);
    763                     }
    764                     if (console || xwindow) {
    765                         attroff(A_ALTCHARSET);
    766                     }
    767                 } else {
    768                     if(rainbow) {
    769                         int randomColor = rand() % 6;
    770 
    771                         switch(randomColor){
    772                             case 0:
    773                                 mcolor = COLOR_GREEN;
    774                                 break;
    775                             case 1:
    776                                 mcolor = COLOR_BLUE;
    777                                 break;
    778                             case 2:
    779                                 mcolor = COLOR_BLACK;
    780                                 break;
    781                             case 3:
    782                                 mcolor = COLOR_YELLOW;
    783                                 break;
    784                             case 4:
    785                                 mcolor = COLOR_CYAN;
    786                                 break;
    787                             case 5:
    788                                 mcolor = COLOR_MAGENTA;
    789                                 break;
    790                        }
    791                     }
    792                     attron(COLOR_PAIR(mcolor));
    793                     if (matrix[i][j].val == 1) {
    794                         if (bold) {
    795                             attron(A_BOLD);
    796                         }
    797                         addch('|');
    798                         if (bold) {
    799                             attroff(A_BOLD);
    800                         }
    801                     } else {
    802                         if (console || xwindow) {
    803                             attron(A_ALTCHARSET);
    804                         }
    805                         if (bold == 2 ||
    806                             (bold == 1 && matrix[i][j].val % 2 == 0)) {
    807                             attron(A_BOLD);
    808                         }
    809                         if (matrix[i][j].val == -1) {
    810                             addch(' ');
    811                         } else if (lambda && matrix[i][j].val != ' ') {
    812                             addstr("λ");
    813                         } else {
    814                             addch(matrix[i][j].val);
    815                         }
    816                         if (bold == 2 ||
    817                             (bold == 1 && matrix[i][j].val % 2 == 0)) {
    818                             attroff(A_BOLD);
    819                         }
    820                         if (console || xwindow) {
    821                             attroff(A_ALTCHARSET);
    822                         }
    823                     }
    824                     attroff(COLOR_PAIR(mcolor));
    825                 }
    826             }
    827         }
    828 
    829         //check if -M and/or -L was used
    830         if (msg[0] != '\0'){
    831             //Add our message to the screen
    832             int msg_x = LINES/2;
    833             int msg_y = COLS/2 - strlen(msg)/2;
    834             int i = 0;
    835 
    836             //Add space before message
    837             move(msg_x-1, msg_y-2);
    838             for(i = 0; i < strlen(msg)+4; i++)
    839                 addch(' ');
    840 
    841             //Write message
    842             move(msg_x, msg_y-2);
    843             addch(' ');
    844             addch(' ');
    845             addstr(msg);
    846             addch(' ');
    847             addch(' ');
    848 
    849             //Add space after message
    850             move(msg_x+1, msg_y-2);
    851             for(i = 0; i < strlen(msg)+4; i++)
    852                 addch(' ');
    853         }
    854 
    855         napms(update * 10);
    856     }
    857     finish();
    858 }
    859