Compare commits

...

10 Commits

Author SHA1 Message Date
Andrew Pamment
da12067099 Made it work! 2021-12-21 21:15:08 +10:00
Andrew Pamment
23cfeba63c Work in progress 2021-12-21 16:53:29 +10:00
Andrew Pamment
a189d44134 Improvements to editor 2021-12-14 22:15:06 +10:00
Andrew Pamment
0aa48c58e2 Modified! 2021-12-14 21:42:16 +10:00
PyGamer0
4a0558d24f Fix readme markdown 2021-07-11 16:01:13 -07:00
Mazar Farran
ef6e723491
Create LICENSE 2021-05-22 22:51:13 -07:00
Mazar Farran
d8371d8e74 Merge pull request #2 from ingver/master
Fixed file_exists()
2015-10-24 14:44:07 -07:00
Igor Schelkonogov
4f898d38bb Fixed file_exists() 2015-10-25 00:22:43 +05:00
Mazar Farran
4e174661ed Readme changes
Also added static function prototypes to prompt.c
2015-09-05 12:19:55 -07:00
Mazar Farran
c3f21b2cbc Added horizontal line to prompts. 2015-08-30 11:45:38 -07:00
13 changed files with 728 additions and 136 deletions

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Mazar Farran
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,13 +1,11 @@
Text Editor
===========
I learned ncurses and figured why not.
Posting this now (9/30/15) because school is starting
so I don't plan on working on it anymore.
![Image of the program in use.](res/text.bmp)
Probably the most well-developed program I made this summer.
Functional lightweight text editor written in C using ncurses.
##How to use:
## How to use:
usage: text [ file ]
@ -16,8 +14,9 @@ Probably the most well-developed program I made this summer.
* F6 saves the current file and allows you to specify the filename.
(WARNING: no confirmation screen or error checking yet).
##Current issues:
## Current issues:
* Code could be organized better
* Some arguments/variables don't do anything
* Tabs are always 4 spaces. This is likely a permanent solution.
* Need to add copy/paste/undo.

21
line.c
View File

@ -5,6 +5,7 @@ void init_line(LINE *s)
s->size = LINE_SIZE;
s->line = (char *)malloc(LINE_SIZE * sizeof(char));
s->line[0] = '\0';
s->lines_in_screen = 1;
} // init_line
@ -19,16 +20,28 @@ void insert_char(LINE *s, char c, int index)
s->line[i + 1] = s->line[i];
s->line[index] = c;
s->lines_in_screen = strlen(s->line) / 75;
if (strlen(s->line) % 75) s->lines_in_screen++;
if (s->lines_in_screen == 0) {
s->lines_in_screen = 1;
}
} // insert
void remove_char(LINE *s, int index)
{
int i;
int len = strlen(s->line);
for(i = index; i < len; i++)
s->line[i] = s->line[i + 1];
int i;
int len = strlen(s->line);
for(i = index; i < len; i++)
s->line[i] = s->line[i + 1];
s->lines_in_screen = strlen(s->line) / 75;
if (strlen(s->line) % 75) s->lines_in_screen++;
if (s->lines_in_screen == 0) {
s->lines_in_screen = 1;
}
} // remove_char

1
line.h
View File

@ -12,6 +12,7 @@ typedef struct
{
char *line;
int size; // size of array, not string
int lines_in_screen;
} LINE;
void init_line(LINE *s);

View File

@ -1,13 +1,13 @@
# makefile for text.c
CC=gcc
CFLAGS=-Wall -g
CC=i686-quinn-gcc
CFLAGS=-Wall
OBJS=text.o page.o line.o prompt.o
HEADERS=$(subst .o,.h,$(OBJS)) # text.h page.h ...
LIBS=-lncurses
LIBS=-lpdcurses -lSDL -lquinn -lfreetype -lpng -lz
text: $(OBJS)
$(CC) $(CFLAGS) -o text $(OBJS) $(LIBS)
$(CC) $(CFLAGS) -o text.exe $(OBJS) $(LIBS)
text.o: text.c $(HEADERS)
$(CC) $(CFLAGS) -c text.c
@ -24,7 +24,7 @@ page.o: page.c page.h line.h
cleanall: clean cleantxt
clean:
rm -f $(OBJS) text
rm -f $(OBJS) text.exe
cleantxt:
rm -f *.txt

37
page.c
View File

@ -12,6 +12,9 @@ void init_page(PAGE *p, char *filename, int size)
strcpy(p->filename, filename);
p->numlines = 0;
p->size = size;
p->x = 0;
p->y = 0;
p->saved = 1;
} // init_page
void dest_page(PAGE *p)
@ -77,21 +80,31 @@ void expand_page(PAGE *p)
} // expand_page
// NOTE: This moves the cursor to the end of the displayed text
void print_page(const PAGE *p, int start, int end)
void print_page(WINDOW *win, WINDOW *lnos, const PAGE *p, int start)
{
int i, line;
for(i = start, line = 0; i < p->numlines && i < end; i++, line++)
for(i = start, line = 0; i < p->numlines && line < EDITOR_SIZE; i++)
{
move(line, 0);
clrtoeol();
printw(" %s", p->text[i].line);
for (int j=0;j < p->text[i].lines_in_screen; j++) {
wmove(lnos, line, 0);
wclrtoeol(lnos);
if (j == 0) {
wprintw(lnos, "%5d", i + 1);
}
wmove(win, line++, 0);
wprintw(win, "%.*s", strlen(&p->text[i].line[j * 75]) < 75 ? strlen(&p->text[i].line[j * 75]) : 75, &p->text[i].line[j * 75]);
wclrtoeol(win);
}
}
if(start < end)
{
move(line, 0);
clrtoeol(); // if we deleted a line this may be necessary
move(line-1, 1);
}
refresh();
for (int j=line; j < EDITOR_SIZE; j++) {
wmove(lnos, j, 0);
wclrtoeol(lnos);
wmove(win, j, 0);
wclrtoeol(win);
}
wrefresh(lnos);
//refresh();
} // print_page

8
page.h
View File

@ -2,11 +2,11 @@
#define PAGE_H
/* PAGE struct definition and related functions */
#include <ncurses.h> // might have to move this
#include <curses.h> // might have to move this
#include "line.h"
#define PAGE_SIZE 500 /* Default number of lines */
#define WIN_SIZE (LINES - 2) /* Size of window, making room for bottom prompt */
#define EDITOR_SIZE (LINES - 2) /* Size of window, making room for bottom prompt */
#define NAME_LIMIT 256 /* Max size of a unix filename + 1 */
typedef struct
@ -15,6 +15,8 @@ typedef struct
LINE *text; // lines of text
int numlines;
int size; // size of array
int x, y;
int saved;
} PAGE;
void init_page(PAGE *p, char *filename, int size);
@ -22,6 +24,6 @@ void dest_page(PAGE *p);
void insert_line(PAGE *p, int index);
void remove_line(PAGE *p, int index);
void expand_page(PAGE *p);
void print_page(const PAGE *p, int start, int end);
void print_page(WINDOW *win, WINDOW *lnos, const PAGE *p, int start);
#endif

View File

@ -1,5 +1,10 @@
#include "prompt.h"
static int center_x(int width);
static int center_y(int height);
static WINDOW* create_prompt(const char *message, int height, int width);
static void dest_prompt(WINDOW *prompt);
static int center_x(int width)
{
return (COLS - width) / 2;
@ -16,6 +21,8 @@ static WINDOW* create_prompt(const char *message, int height, int width)
center_y(height), center_x(width));
werase(prompt);
mvwprintw(prompt, 1, 1, message);
wmove(prompt, 2, 0);
whline(prompt, ACS_HLINE, 1000);
box(prompt, 0, 0);
wmove(prompt, PROMPT_OFFY, PROMPT_OFFX);
return prompt;

View File

@ -1,7 +1,7 @@
#ifndef PROMPT_H
#define PROMPT_H
#include <ncurses.h>
#include <curses.h>
#include <string.h>
#define PROMPT_STRING_LINES 5

BIN
res/text.bmp Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

378
text.c
View File

@ -1,5 +1,5 @@
#include "text.h"
#include "text.xpm"
/**
* Word Processing Program
* Features:
@ -8,25 +8,114 @@
* -Loading
**/
int winx, winy;
int y_offset = 0; // TODO: move to local scope
int tab_offset = 0;
extern void convert_xpm(char **xpm, unsigned char **buffer);
extern unsigned char *QUINN_Icon;
WINDOW *menu;
WINDOW *editor;
WINDOW *linenos;
short curs_color(int fg)
{
switch (7 & fg) { /* RGB */
case 0: /* 000 */
return (COLOR_BLACK);
case 1: /* 001 */
return (COLOR_BLUE);
case 2: /* 010 */
return (COLOR_GREEN);
case 3: /* 011 */
return (COLOR_CYAN);
case 4: /* 100 */
return (COLOR_RED);
case 5: /* 101 */
return (COLOR_MAGENTA);
case 6: /* 110 */
return (COLOR_YELLOW);
case 7: /* 111 */
return (COLOR_WHITE);
}
}
void init_colorpairs(void)
{
int fg, bg;
int colorpair;
for (bg = 0; bg <= 7; bg++) {
for (fg = 0; fg <= 7; fg++) {
colorpair = colornum(fg, bg);
init_pair(colorpair, curs_color(fg), curs_color(bg));
}
}
}
int colornum(int fg, int bg)
{
int B, bbb, ffff;
B = 1 << 7;
bbb = (7 & bg) << 4;
ffff = 7 & fg;
return (B | bbb | ffff);
}
void setcolor(int fg, int bg)
{
/* set the color pair (colornum) and bold/bright (A_BOLD) */
attron(COLOR_PAIR(colornum(fg, bg)));
if (is_bold(fg)) {
attron(A_BOLD);
}
}
void unsetcolor(int fg, int bg)
{
/* unset the color pair (colornum) and
bold/bright (A_BOLD) */
attroff(COLOR_PAIR(colornum(fg, bg)));
if (is_bold(fg)) {
attroff(A_BOLD);
}
}
int is_bold(int fg)
{
/* return the intensity bit */
int i;
i = 1 << 3;
return (i & fg);
}
#define DEBUG
void print_loc(int x, int y)
{
#ifdef DEBUG
int oldx, oldy;
getyx(stdscr, oldy, oldx);
mvprintw(0, COLS - 20, "x: %d y: %d o: %d", x, y, y_offset);
wmove(menu, 0, COLS - 30);
wprintw(menu, "X: %d Y: %d Offset: %d", x + 1, y + 1, y_offset);
wclrtoeol(menu);
move(oldy, oldx);
#endif
}
int main(int argc, char *argv[])
{
PAGE page;
convert_xpm(text_xpm, &QUINN_Icon);
if(argc > 1)
{
if(file_exists(argv[1]))
@ -48,95 +137,111 @@ int main(int argc, char *argv[])
/* curses interface */
initscr();
noecho();
keypad(stdscr, true);
keypad(stdscr, 1);
start_color();
init_colorpairs();
winx = 0;
winy = 0;
menu = subwin(stdscr, 2, 80, 23, 0);
wbkgd(menu, COLOR_PAIR(colornum(COLOR_BLACK, COLOR_CYAN)));
editor = subwin(stdscr, 23, 75, 0, 5);
wbkgd(editor, COLOR_PAIR(colornum(COLOR_WHITE, COLOR_BLUE)));
linenos = subwin(stdscr, 23, 5, 0, 0);
wbkgd(linenos, COLOR_PAIR(colornum(COLOR_BLUE, COLOR_WHITE)));
int beg = 0;
int end = WIN_SIZE;
int y, x; // position on screen
int i;
int i;
update_status(&page, "");
update_status("Press F4 to quit");
print_page(&page, beg, end);
getyx(stdscr, y, x);
char status[NAME_LIMIT + 10];
while(true)
print_page(editor, linenos, &page, beg);
wmove(editor, winy, winx);
while(1)
{
print_loc(x, y);
beg = 0 + y_offset;
end = WIN_SIZE + y_offset;
int ch = getch();
update_status("Press F4 to quit"); // default text
beg = y_offset;
int ch = wgetch(editor);
update_status(&page, ""); // default text
switch(ch)
{
case KEY_F(4):
if(prompt_yesno("Are you sure you want to quit?"))
goto endnc;
print_page(&page, beg, end);
print_page(editor, linenos, &page, beg);
break;
case KEY_F(5):
save_file(&page);
sprintf(status, "Saved as \'%s\'", page.filename);
update_status(status);
update_status(&page, "Saved!");
break;
case KEY_F(6):
prompt_string("Save As:", page.filename, NAME_LIMIT);
save_file(&page);
sprintf(status, "Saved as \'%s\'", page.filename);
print_page(&page, beg, end);
update_status(status);
print_page(editor, linenos, &page, beg);
update_status(&page, "Saved!");
break;
case KEY_UP:
move_up(&page, &x, &y);
move_up(&page);
break;
case KEY_DOWN:
move_down(&page, &x, &y);
move_down(&page);
break;
case KEY_LEFT:
move_left(&x, &y);
move_left(&page);
break;
case KEY_RIGHT:
move_right(&page, &x, &y);
move_right(&page);
break;
case KEY_END:
move_to_eol(&page);
case KEY_DC:
case 127: // backspace key...
case KEY_BACKSPACE:
if(strlen(page.text[y + y_offset].line) == 0)
case '\b':
if(strlen(page.text[page.y].line) == 0)
{ // can only delete blank lines for now
remove_line(&page, y + y_offset);
move_up(&page, &x, &y);
remove_line(&page, page.y);
move_up(&page);
}
else if( x > 1 )
else if( page.x > 0 )
{
remove_char(&page.text[y + y_offset], x - 2); // delete
move_left(&x, &y); // char behind cursor
remove_char(&page.text[page.y], page.x - 1); // delete
move_left(&page); // char behind cursor
}
print_page(&page, beg, end);
move(y, x);
print_page(editor, linenos, &page, beg);
wmove(editor, winy, winx);
page.saved = 0;
break;
case '\t':
for(i = 0; i < TAB_WIDTH; i++)
{
insert_char(&page.text[y + y_offset], ' ', x - 1);
print_page(&page, beg, end);
move_right(&page, &x, &y);
insert_char(&page.text[page.y], ' ', page.x);
print_page(editor, linenos, &page, beg);
move_right(&page);
}
page.saved = 0;
break;
case '\n': // newline
insert_line(&page, y + y_offset + 1);
print_page(&page, beg, end);
move_down(&page, &x, &y);
insert_line(&page, page.y + 1);
print_page(editor, linenos, &page, beg);
move_down(&page);
break;
default: // all other chars
if( isprint(ch) )
{
insert_char(&page.text[y + y_offset], ch, x - 1);
print_page(&page, beg, end);
move_right(&page, &x, &y);
insert_char(&page.text[page.y], ch, page.x);
print_page(editor, linenos, &page, beg);
move_right(&page);
page.saved = 0;
}
}
print_loc(page.x, page.y);
wrefresh(menu);
wrefresh(editor);
}
endnc:
/* end curses */
@ -146,68 +251,146 @@ endnc:
} // main
// prints a message at the bottom of the window
void update_status(char *info)
void update_status(PAGE *p, char *info)
{
int oldy, oldx; getyx(stdscr, oldy, oldx);
char title[61];
attron(A_REVERSE);
move(LINES - 1, 0);
clrtoeol();
printw(info);
attroff(A_REVERSE);
snprintf(title, 60, "Text: %s%c", p->filename, p->saved == 1 ? ' ' : '*');
move(oldy, oldx);
PDC_set_title(title);
wmove(menu, 0, 0);
wprintw(menu, "%s", info);
wmove(menu, 1, 0);
wprintw(menu, "F4: Quit F5: Save F6: Save As ");
wrefresh(menu);
} // update_status
/* movement */
void move_left(int *x, int *y)
void move_to_eol(PAGE *p)
{
if(*x - 1 > 0) move(*y, --(*x));
while (p->x <= strlen(p->text[p->y].line)) {
move_right(p);
}
}
void move_left(PAGE *p)
{
if(p->x - 1 > 0) {
p->x--;
winx--;
winy = 0;
if (p->x > 75) {
winx = p->x % 75;
winy = p->x / 75;
} else {
winx = p->x;
}
for (int j = y_offset; j < p->y; j++) {
winy += p->text[j].lines_in_screen;
}
wmove(editor, winy, winx);
} else if (p->x - 1 == 0){
p->x = 0;
winx = 0;
}
}
void move_right(PAGE *p, int *x, int *y)
void move_right(PAGE *p)
{
if(*x <= strlen(p->text[*y + y_offset].line))
if(p->x <= strlen(p->text[p->y].line))
{
if(p->text[*y + y_offset].line[*x + tab_offset] == '\t') {
move(*y, ++(*x));
} else {
move(*y, ++(*x));
}
p->x++;
winy = 0;
if (p->x > 75) {
winx = p->x % 75;
winy = p->x / 75;
} else {
winx++;
}
for (int j = y_offset; j < p->y; j++) {
if (strlen(p->text[j].line) > 75) {
winy += p->text[j].lines_in_screen;
} else {
winy++;
}
}
wmove(editor, winy, winx);
}
}
void move_up(PAGE *p, int *x, int *y)
void move_up(PAGE *p)
{
if( *y > 0 )
{
--(*y);
}
else if (y_offset > 0)
{
--(y_offset);
print_page(p, 0 + y_offset, WIN_SIZE + y_offset);
}
if( *x > strlen(p->text[*y + y_offset].line) + 1 ) // cursor adjusts
*x = strlen(p->text[*y + y_offset].line) + 1; // to smaller lines
move(*y, *x);
}
void move_down(PAGE *p, int *x, int *y)
{
if( *y < WIN_SIZE - 1 && *y < p->numlines - 1 )
{
++(*y);
}
else if ( *y + y_offset < p->numlines - 1 )
{
++(y_offset);
print_page(p, 0 + y_offset, WIN_SIZE + y_offset);
}
if (p->y == y_offset && y_offset > 0) {
p->y--;
y_offset--;
if( *x > strlen(p->text[*y + y_offset].line) + 1 )
*x = strlen(p->text[*y + y_offset].line) + 1;
move(*y, *x);
if( p->x > strlen(p->text[p->y].line) ) { // cursor adjusts
p->x = strlen(p->text[p->y].line); // to smaller lines
int oldy = p->x / 75;
p->x = strlen(p->text[p->y].line);
winx = p->x % 75;
winy = winy - (oldy - p->x / 75);
}
print_page(editor, linenos, p, y_offset);
wmove(editor, winy, winx);
} else if (p->y > 0) {
p->y--;
winy -= p->text[p->y].lines_in_screen;
if( p->x > strlen(p->text[p->y].line) ) { // cursor adjusts
int oldy = p->x / 75;
p->x = strlen(p->text[p->y].line);
winx = p->x % 75;
winy = winy - (oldy - p->x / 75);
}
wmove(editor, winy, winx);
}
}
void move_down(PAGE *p)
{
if (p->y < p->numlines - 1) {
winy += p->text[p->y].lines_in_screen;
p->y++;
int new_y_offset = y_offset;
while (1) {
int count = 0;
for (int i = new_y_offset; i <= p->y; i++) {
count += p->text[i].lines_in_screen;
}
if (count > EDITOR_SIZE) {
new_y_offset++;
} else {
break;
}
}
if (new_y_offset != y_offset) {
winy = 0;
for (int i = new_y_offset;i < p->y; i++) {
winy += p->text[i].lines_in_screen;
}
y_offset = new_y_offset;
print_page(editor, linenos, p, y_offset);
}
if( p->x > strlen(p->text[p->y].line)) {
int oldy = p->x / 75;
p->x = strlen(p->text[p->y].line);
winx = p->x % 75;
winy = winy - (oldy - p->x / 75);
}
wmove(editor, winy, winx);
}
}
/* movement */
@ -287,15 +470,16 @@ void save_file(PAGE *p)
}
fclose(fp);
p->saved = 1;
} // save_file
int file_exists(char *filename)
{
FILE *fp = fopen(filename, "r");
int result = (fp == NULL);
if(result)
if(fp != NULL) {
fclose(fp);
return !result;
return 1;
}
return 0;
}
/* saving and loading */

13
text.h
View File

@ -5,22 +5,23 @@
#include <stdlib.h> // declared in line.h
#include <ctype.h>
#include <string.h> // declared in line.h
#include <ncurses.h> // -lncurses. declared in page.h
#include <curses.h> // -lncurses. declared in page.h
#include "page.h"
#include "prompt.h"
void update_status(char *info);
void update_status(PAGE *p, char *info);
int count_lines(FILE *fp);
void load_file(PAGE *p, char* filename);
void save_file(PAGE *p);
int file_exists(char *filename);
void move_left(int *x, int *y);
void move_right(PAGE *p, int *x, int *y);
void move_up(PAGE *p, int *x, int *y);
void move_down(PAGE *p, int *x, int *y);
void move_to_eol(PAGE *p);
void move_left(PAGE *p);
void move_right(PAGE *p);
void move_up(PAGE *p);
void move_down(PAGE *p);
#endif

351
text.xpm Normal file
View File

@ -0,0 +1,351 @@
/* XPM */
static char * text_xpm[] = {
"64 64 284 2",
" c None",
". c #1C0F16",
"+ c #1F1118",
"@ c #180D13",
"# c #4A293B",
"$ c #B1618B",
"% c #AB5E87",
"& c #402332",
"* c #1C0F17",
"= c #A75C83",
"- c #AD5F88",
"; c #1C1016",
"> c #120C0E",
", c #130F11",
"' c #73415C",
") c #24141C",
"! c #1F1D1E",
"~ c #848484",
"{ c #3E393C",
"] c #442A38",
"^ c #74405B",
"/ c #0B0B07",
"( c #050505",
"_ c #1B1B1B",
": c #161615",
"< c #0F0F0F",
"[ c #0C0C0C",
"} c #0B0B0B",
"| c #0E0E0C",
"1 c #090908",
"2 c #060606",
"3 c #141012",
"4 c #646364",
"5 c #898989",
"6 c #585556",
"7 c #2A1D24",
"8 c #1D1016",
"9 c #12110C",
"0 c #564E39",
"a c #756A4D",
"b c #22211E",
"c c #707070",
"d c #22201D",
"e c #524A36",
"f c #1B1B07",
"g c #1A1919",
"h c #7B7B7B",
"i c #302D2E",
"j c #181610",
"k c #C3B080",
"l c #9A8B65",
"m c #8F815E",
"n c #8E805D",
"o c #252420",
"p c #25231F",
"q c #A19169",
"r c #504D24",
"s c #D8E511",
"t c #868E0C",
"u c #111010",
"v c #6D6D6D",
"w c #6F6E6E",
"x c #161315",
"y c #191711",
"z c #645C47",
"A c #575552",
"B c #73726F",
"C c #72716E",
"D c #232322",
"E c #222121",
"F c #484642",
"G c #5D563D",
"H c #858B13",
"I c #F0FF13",
"J c #B4C00E",
"K c #100F0E",
"L c #171616",
"M c #413E37",
"N c #FFFFFF",
"O c #FCFCFC",
"P c #323232",
"Q c #343434",
"R c #F4F4F4",
"S c #35370C",
"T c #ECFB13",
"U c #8C930B",
"V c #0E0F02",
"W c #44413A",
"X c #848573",
"Y c #B1BC0E",
"Z c #E4F212",
"` c #292C04",
" . c #FBFBFB",
".. c #141414",
"+. c #313131",
"@. c #353535",
"#. c #383838",
"$. c #373737",
"%. c #3D3D3D",
"&. c #3C3C3C",
"*. c #3E3E3E",
"=. c #242424",
"-. c #E2E2E2",
";. c #676C25",
">. c #636908",
",. c #FEFEFE",
"'. c #DDDDDD",
"). c #D2D2D2",
"!. c #CCCCCC",
"~. c #C8C8C8",
"{. c #BBBBBB",
"]. c #AEAEAE",
"^. c #AAAAAA",
"/. c #B2B2B2",
"(. c #5D5F42",
"_. c #D8E611",
":. c #C9D510",
"<. c #272903",
"[. c #B8B9B2",
"}. c #8E961C",
"|. c #3B3E05",
"1. c #F8F8F8",
"2. c #55582C",
"3. c #EDFC13",
"4. c #969F0D",
"5. c #ECECEC",
"6. c #C0C0C0",
"7. c #666753",
"8. c #BAC613",
"9. c #E7F512",
"0. c #2A2C07",
"a. c #C4C4C4",
"b. c #444444",
"c. c #555A0E",
"d. c #6E7213",
"e. c #1C1A10",
"f. c #5C5E40",
"g. c #DCEA11",
"h. c #CCD910",
"i. c #5E592F",
"j. c #201E15",
"k. c #B0B1A9",
"l. c #91991A",
"m. c #41440C",
"n. c #B7A578",
"o. c #F6F6F6",
"p. c #52552A",
"q. c #EEFD13",
"r. c #A2AB15",
"s. c #343320",
"t. c #F7F7F7",
"u. c #D5D5D5",
"v. c #6B6D59",
"w. c #BBC712",
"x. c #575936",
"y. c #413E36",
"z. c #D6D6D6",
"A. c #2F2F2F",
"B. c #292929",
"C. c #555A0C",
"D. c #767C1D",
"E. c #CECECB",
"F. c #5B5D3E",
"G. c #DDEB12",
"H. c #CEDB11",
"I. c #717359",
"J. c #ACADA4",
"K. c #959D1A",
"L. c #5A5D27",
"M. c #525528",
"N. c #A4AE16",
"O. c #9D9E90",
"P. c #EBEBEB",
"Q. c #8F8F8F",
"R. c #4E4F3B",
"S. c #C0CC11",
"T. c #E8F612",
"U. c #3E401E",
"V. c #C6C6C6",
"W. c #E7E7E7",
"X. c #757575",
"Y. c #656564",
"Z. c #606513",
"`. c #6D7312",
" + c #5F5F5B",
".+ c #BCBCBC",
"++ c #5D5F3D",
"@+ c #E1EF12",
"#+ c #CFDC11",
"$+ c #6F7157",
"%+ c #A8A99E",
"&+ c #98A119",
"*+ c #5A5E26",
"=+ c #F5F5F5",
"-+ c #575A29",
";+ c #EFFE13",
">+ c #A7B116",
",+ c #9A9B8C",
"'+ c #CECECE",
")+ c #1E1F09",
"!+ c #C1CE0F",
"~+ c #272906",
"{+ c #939393",
"]+ c #F0F0F0",
"^+ c #C8C8C7",
"/+ c #6E741F",
"(+ c #787F1C",
"_+ c #BCBCB8",
":+ c #F9F9F9",
"<+ c #575939",
"[+ c #E2F012",
"}+ c #D0DD10",
"|+ c #6C6E54",
"1+ c #A4A59A",
"2+ c #9CA519",
"3+ c #5A5E25",
"4+ c #F2F2F2",
"5+ c #545727",
"6+ c #AEB816",
"7+ c #979889",
"8+ c #252711",
"9+ c #C3CF10",
"0+ c #E9F812",
"a+ c #2D300B",
"b+ c #DBDBDB",
"c+ c #A9A9A7",
"d+ c #70751D",
"e+ c #7A8019",
"f+ c #ACACA7",
"g+ c #37332D",
"h+ c #2A280E",
"i+ c #DCE911",
"j+ c #D2DF11",
"k+ c #6A6C52",
"l+ c #4E433D",
"m+ c #805D47",
"n+ c #1A150E",
"o+ c #90990D",
"p+ c #5C6025",
"q+ c #EAEAEA",
"r+ c #E3E3E3",
"s+ c #C1C1C1",
"t+ c #5F4A3D",
"u+ c #B18061",
"v+ c #A07357",
"w+ c #2C2219",
"x+ c #36350E",
"y+ c #848575",
"z+ c #EFEFEF",
"A+ c #212121",
"B+ c #1B1917",
"C+ c #87614A",
"D+ c #644938",
"E+ c #16120E",
"F+ c #59534E",
"G+ c #AC7C5E",
"H+ c #A8795C",
"I+ c #4C3F36",
"J+ c #8B8987",
"K+ c #4C423C",
"L+ c #8E684F",
"M+ c #423A36",
"N+ c #D1D1D1",
"O+ c #070605",
"P+ c #65605D",
"Q+ c #5E5C5C",
"R+ c #413E35",
"S+ c #423E35",
"T+ c #EEEEEE",
"U+ c #C3C3C3",
"V+ c #514B3D",
"W+ c #A2926A",
"X+ c #3D392F",
"Y+ c #2C2A24",
"Z+ c #454034",
"`+ c #AE9D72",
" @ c #201C15",
".@ c #14110D",
"+@ c #A4946C",
"@@ c #AB9A70",
"#@ c #13110C",
"$@ c #0C0B09",
"%@ c #060504",
"&@ c #0C0B08",
" ",
" . + @ ",
" # $ % & ",
" * = $ $ - ; ",
" > , ' $ $ $ ) ",
" ! ~ { ] - ^ ",
" / / / / / / / / / / / ( _ : : < < [ } | 1 [ 2 / / / / / / / / / / 3 4 5 5 6 7 8 ",
" 9 0 a a a a a a a a a a a b c c c c c c c c c c d a a a a a a a a a a e f g h 5 5 i ",
" j k k l m m m m m m m m n o c c c c c c c c c c p m m m m m m m m q k r s t u v w x ",
" y k z A B B B B B B B B C D c c c c c c c c c c E B B B B B B B B F G H I I J K L ",
" y k M N N N N N N N N N O P c c c c c c c c c c Q N N N N N N N N R S T I I I U V ",
" y k W N N N N N N N N N O P c c c c c c c c c c Q N N N N N N N N X Y I I I Z ` ",
" y k W N N N N N N N N N ...P +.@.#.#.$.%.%.&.*.=.N N N N N N N -.;.I I I I >. ",
" y k W N N N N N N N N N ,.'.'.).!.!.~.{.{.{.].^./.N N N N N N N (._.I I I :.<. ",
" y k W N N N N N N N N N N N N N N N N N N N N N N N N N N N N [.}.I I I I |. ",
" y k W N N N N N N N N N N N N N N N N N N N N N N N N N N N 1.2.3.I I I 4. ",
" y k W N 5.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.6.7.8.I I I 9.0. ",
" y k W N a.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.&.c.I I I I d.e. ",
" y k W N N N N N N N N N N N N N N N N N N N N N N N N N N f.g.I I I h.i.j. ",
" y k W N N N N N N N N N N N N N N N N N N N N N N N N N k.l.I I I I m.n.j. ",
" y k W N N N N N N N N N N N N N N N N N N N N N N N N o.p.q.I I I r.s.k j. ",
" y k W N t.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.u.v.w.I I I 9.x.y.k j. ",
" y k W N z.A.A.A.A.A.A.A.A.A.A.A.A.A.A.A.A.A.A.A.A.A.B.C.I I I I D.E.y.k j. ",
" y k W N N N N N N N N N N N N N N N N N N N N N N N F.G.I I I H.I.N y.k j. ",
" y k W N N N N N N N N N N N N N N N N N N N N N N J.K.I I I I L.5.N y.k j. ",
" y k W N N N N N N N N N N N N N N N N N N N N N o.M.q.I I I N.O.N N y.k j. ",
" y k W N P.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.R.S.I I I T.U.V.N N y.k j. ",
" y k W N W.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.X.Y.Z.I I I I `. +.+N N y.k j. ",
" y k W N N N N N N N N N N N N N N N N N N N N ++@+I I I #+$+N N N N y.k j. ",
" y k W N N N N N N N N N N N N N N N N N N N %+&+I I I I *+P.N N N N y.k j. ",
" y k W N N N N N N N N N N N N N N N N N N =+-+;+I I I >+,+N N N N N y.k j. ",
" y k W N '+................................)+!+I I I T.~+......{+N N y.k j. ",
" y k W N O ]+]+]+]+]+]+]+]+]+]+]+]+]+]+]+^+/+I I I I (+_+]+]+]+:+N N y.k j. ",
" y k W N N N N N N N N N N N N N N N N N <+[+I I I }+|+N N N N N N N y.k j. ",
" y k W N N N N N N N N N N N N N N N N 1+2+I I I I 3+P.N N N N N N N y.k j. ",
" y k W N N N N N N N N N N N N N N N 4+5+;+I I I 6+7+N N N N N N N N y.k j. ",
" y k W N P.B.B.B.B.B.B.B.B.B.B.B.B.B.8+9+I I I 0+a+B.B.B.B.B.B.~ N N y.k j. ",
" y k W N O b+b+b+b+b+b+b+b+b+b+b+b+c+d+I I I I e+f+b+b+b+b+b+b+P.N N y.k j. ",
" y k W N N N N N N N N N N N N N N g+h+i+I I j+k+N N N N N N N N N N y.k j. ",
" y k W N N N N N N N N N N N N N N l+m+n+o+I p+q+N N N N N N N N N N y.k j. ",
" y k W N ,.r+r+r+r+r+r+r+r+r+r+r+s+t+u+v+w+x+y+r+r+r+r+r+r+r+r+z+N N y.k j. ",
" y k W N ]+A+A+A+A+A+A+A+A+A+A+A+B+C+u+u+D+E+A+A+A+A+A+A+A+A+A+h N N y.k j. ",
" y k W N N N N N N N N N N N N N F+G+H+I+J+N N N N N N N N N N N N N y.k j. ",
" y k W N N N N N N N N N N N N N K+L+M+N+N N N N N N N N N N N N N N y.k j. ",
" y k W N N N N N N N N N N N N ^.O+P+o.N N N N N N N N N N N N N N N y.k j. ",
" y k W N N N N N N N N N N N N A.Q+N N N N N N N N N N N N N N N N N y.k j. ",
" y k W N N N N N N N N N N N N b+N N N N N N N N N N N N N N N N N N y.k j. ",
" y k W N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N y.k j. ",
" y k W N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N y.k j. ",
" y k W N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N N R+k j. ",
" y k S+z.T+T+T+T+T+T+T+T+T+T+T+T+T+T+T+T+T+T+T+T+T+T+T+T+T+T+T+T+T+U+V+k j. ",
" y k W+X+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Y+Z+`+k j. ",
" y k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k @ ",
" .@+@k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k @@#@ ",
" $@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@&@ ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};