mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
Moving ede-autostart code in separate directory, since is pretty unrelated to evoke.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
# GNU General Public License version 2 or newer.
|
||||
# See COPYING for details.
|
||||
|
||||
SubDir TOP ede-autostart;
|
||||
SubDir TOP ede-autostart ;
|
||||
|
||||
EdeProgram ede-autostart : ede-autostart.cpp ;
|
||||
#ObjectC++Flags ede-autostart : -DDEBUG_AUTOSTART_RUN ;
|
||||
|
382
ede-autostart/ede-autostart.cpp
Normal file
382
ede-autostart/ede-autostart.cpp
Normal file
@ -0,0 +1,382 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* ede-autostart
|
||||
* Part of Equinox Desktop Environment (EDE).
|
||||
* Copyright (c) 2007-2009 EDE Authors.
|
||||
*
|
||||
* This program is licensed under terms of the
|
||||
* GNU General Public License version 2 or newer.
|
||||
* See COPYING for details.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <FL/Fl_Pixmap.H>
|
||||
#include <FL/Fl_Check_Browser.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Window.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/Fl.H>
|
||||
|
||||
#include <edelib/String.h>
|
||||
#include <edelib/StrUtil.h>
|
||||
#include <edelib/List.h>
|
||||
#include <edelib/Util.h>
|
||||
#include <edelib/DesktopFile.h>
|
||||
#include <edelib/Directory.h>
|
||||
#include <edelib/Nls.h>
|
||||
#include <edelib/Debug.h>
|
||||
#include <edelib/Run.h>
|
||||
#include <edelib/FileTest.h>
|
||||
#include <edelib/MessageBox.h>
|
||||
|
||||
#include "icons/warning.xpm"
|
||||
|
||||
EDELIB_NS_USING(String)
|
||||
EDELIB_NS_USING(DesktopFile)
|
||||
EDELIB_NS_USING(list)
|
||||
EDELIB_NS_USING(dir_list)
|
||||
EDELIB_NS_USING(system_config_dirs)
|
||||
EDELIB_NS_USING(user_config_dir)
|
||||
EDELIB_NS_USING(str_ends)
|
||||
EDELIB_NS_USING(run_async)
|
||||
EDELIB_NS_USING(ask)
|
||||
EDELIB_NS_USING(file_test)
|
||||
EDELIB_NS_USING(FILE_TEST_IS_REGULAR)
|
||||
EDELIB_NS_USING(FILE_TEST_IS_EXECUTABLE)
|
||||
|
||||
#define CHECK_ARGV(argv, pshort, plong) ((strcmp(argv, pshort) == 0) || (strcmp(argv, plong) == 0))
|
||||
|
||||
#ifdef DEBUG_AUTOSTART_RUN
|
||||
#define AUTOSTART_RUN(s) E_DEBUG("Executing %s\n", s)
|
||||
#else
|
||||
#define AUTOSTART_RUN(s) run_async(s)
|
||||
#endif
|
||||
|
||||
#define AUTOSTART_DIRNAME "/autostart/"
|
||||
|
||||
/* ordered names that will be searched */
|
||||
static const char* autostart_names[] = {
|
||||
".autorun",
|
||||
"autorun",
|
||||
"autorun.sh",
|
||||
0
|
||||
};
|
||||
|
||||
struct DialogEntry {
|
||||
String name;
|
||||
String exec;
|
||||
String comment;
|
||||
};
|
||||
|
||||
typedef list<String> StringList;
|
||||
typedef list<String>::iterator StringListIter;
|
||||
|
||||
typedef list<DialogEntry*> DialogEntryList;
|
||||
typedef list<DialogEntry*>::iterator DialogEntryListIter;
|
||||
|
||||
static Fl_Window* dialog_win;
|
||||
static Fl_Check_Browser* cbrowser;
|
||||
static Fl_Pixmap warnpix((const char**)warning_xpm);
|
||||
|
||||
static char* get_basename(const char* path) {
|
||||
char* p = strrchr(path, '/');
|
||||
if(p)
|
||||
return (p + 1);
|
||||
|
||||
return (char*)path;
|
||||
}
|
||||
|
||||
/*
|
||||
* 'Remove' duplicate entries by looking at their basename
|
||||
* (aka. filename, but ignoring directory path). Item is not actually removed from
|
||||
* the list (will mess up list pointers, but this can be resolved), but data it points
|
||||
* to is cleared, which is a sort of marker to caller to skip it. Dumb yes, but very simple.
|
||||
*
|
||||
* It will use brute force for lookup and 'removal' and (hopfully) it should not have
|
||||
* a large impact on startup since, afaik, no one keeps hundreds of files in autostart
|
||||
* directories (if keeps them, then that issue is not up to this program :-P).
|
||||
*
|
||||
* Alternative would be to sort items (by their basename) and apply consecutive unique on
|
||||
* them, but... is it worth ?
|
||||
*/
|
||||
static void unique_by_basename(StringList& lst) {
|
||||
if(lst.empty())
|
||||
return;
|
||||
|
||||
StringListIter first, last, first1, last1;
|
||||
first = lst.begin();
|
||||
last = lst.end();
|
||||
|
||||
if(first == last)
|
||||
return;
|
||||
|
||||
const char* p1, *p2;
|
||||
for(; first != last; ++first) {
|
||||
for(first1 = lst.begin(), last1 = lst.end(); first1 != last1; ++first1) {
|
||||
p1 = (*first).c_str();
|
||||
p2 = (*first1).c_str();
|
||||
|
||||
if(first != first1 && strcmp(get_basename(p1), get_basename(p2)) == 0)
|
||||
(*first1).clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void entry_list_run_clear(DialogEntryList& l, bool run) {
|
||||
DialogEntryListIter dit = l.begin(), dit_end = l.end();
|
||||
for(; dit != dit_end; ++dit) {
|
||||
if(run)
|
||||
AUTOSTART_RUN((*dit)->exec.c_str());
|
||||
delete *dit;
|
||||
}
|
||||
|
||||
l.clear();
|
||||
}
|
||||
|
||||
static void dialog_runsel_cb(Fl_Widget*, void* e) {
|
||||
DialogEntryList* lst = (DialogEntryList*)e;
|
||||
E_ASSERT(lst->size() == (unsigned int)cbrowser->nitems() && "Size mismatch in local list and browser widget");
|
||||
|
||||
DialogEntryListIter it = lst->begin();
|
||||
for(int i = 1; i <= cbrowser->nitems(); i++, ++it) {
|
||||
if(cbrowser->checked(i))
|
||||
AUTOSTART_RUN((*it)->exec.c_str());
|
||||
}
|
||||
|
||||
dialog_win->hide();
|
||||
entry_list_run_clear(*lst, false);
|
||||
}
|
||||
|
||||
static void dialog_runall_cb(Fl_Widget*, void* e) {
|
||||
DialogEntryList* lst = (DialogEntryList*)e;
|
||||
E_ASSERT(lst->size() == (unsigned int)cbrowser->nitems() && "Size mismatch in local list and browser widget");
|
||||
|
||||
dialog_win->hide();
|
||||
entry_list_run_clear(*lst, true);
|
||||
}
|
||||
|
||||
static void dialog_close_cb(Fl_Widget*, void* e) {
|
||||
dialog_win->hide();
|
||||
|
||||
DialogEntryList* lst = (DialogEntryList*)e;
|
||||
entry_list_run_clear(*lst, false);
|
||||
}
|
||||
|
||||
static void run_autostart_dialog(DialogEntryList& l) {
|
||||
DialogEntryList* ptr = (DialogEntryList*)&l;
|
||||
|
||||
dialog_win = new Fl_Window(370, 305, _("Autostart warning"));
|
||||
dialog_win->begin();
|
||||
Fl_Box* img = new Fl_Box(10, 10, 65, 60);
|
||||
img->image(warnpix);
|
||||
Fl_Box* txt = new Fl_Box(80, 10, 280, 60, _("The following applications are registered for starting. Please chose what to do next"));
|
||||
txt->align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT | FL_ALIGN_WRAP);
|
||||
cbrowser = new Fl_Check_Browser(10, 75, 350, 185);
|
||||
|
||||
DialogEntryListIter it = l.begin(), it_end = l.end();
|
||||
for(; it != it_end; ++it) {
|
||||
if((*it)->comment.empty())
|
||||
cbrowser->add((*it)->name.c_str());
|
||||
else {
|
||||
char buf[256];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s (%s)", (*it)->name.c_str(), (*it)->comment.c_str());
|
||||
cbrowser->add(buf);
|
||||
}
|
||||
}
|
||||
|
||||
Fl_Button* rsel = new Fl_Button(45, 270, 125, 25, _("Run &selected"));
|
||||
rsel->callback(dialog_runsel_cb, ptr);
|
||||
|
||||
Fl_Button* rall = new Fl_Button(175, 270, 90, 25, _("&Run all"));
|
||||
rall->callback(dialog_runall_cb, ptr);
|
||||
|
||||
Fl_Button* cancel = new Fl_Button(270, 270, 90, 25, _("&Cancel"));
|
||||
cancel->callback(dialog_close_cb, ptr);
|
||||
cancel->take_focus();
|
||||
dialog_win->end();
|
||||
dialog_win->show();
|
||||
|
||||
while(dialog_win->shown())
|
||||
Fl::wait();
|
||||
}
|
||||
|
||||
static void perform_autostart(bool safe) {
|
||||
String adir = edelib::user_config_dir();
|
||||
adir += AUTOSTART_DIRNAME;
|
||||
|
||||
StringList dfiles, sysdirs, tmp;
|
||||
StringListIter it, it_end, tmp_it, tmp_it_end;
|
||||
|
||||
dir_list(adir.c_str(), dfiles, true);
|
||||
|
||||
system_config_dirs(sysdirs);
|
||||
if(!sysdirs.empty()) {
|
||||
for(it = sysdirs.begin(), it_end = sysdirs.end(); it != it_end; ++it) {
|
||||
*it += AUTOSTART_DIRNAME;
|
||||
|
||||
/*
|
||||
* append content
|
||||
* FIXME: too much of copying. There should be some way to merge list items
|
||||
* probably via merge() member
|
||||
*/
|
||||
dir_list((*it).c_str(), tmp, true);
|
||||
for(tmp_it = tmp.begin(), tmp_it_end = tmp.end(); tmp_it != tmp_it_end; ++tmp_it)
|
||||
dfiles.push_back(*tmp_it);
|
||||
}
|
||||
}
|
||||
|
||||
if(dfiles.empty())
|
||||
return;
|
||||
|
||||
/*
|
||||
* Remove duplicates where first one seen have priority to be keept.
|
||||
* This way is required by spec.
|
||||
*
|
||||
* Also handle this case (noted in spec):
|
||||
* if $XDG_CONFIG_HOME/autostart/foo.desktop and $XDG_CONFIG_DIRS/autostart/foo.desktop
|
||||
* exists, but $XDG_CONFIG_HOME/autostart/foo.desktop have 'Hidden = true',
|
||||
* $XDG_CONFIG_DIRS/autostart/foo.autostart is ignored too.
|
||||
*
|
||||
* Latter is implied via unique_by_basename().
|
||||
*/
|
||||
unique_by_basename(dfiles);
|
||||
|
||||
const char* name;
|
||||
char buf[1024];
|
||||
DesktopFile df;
|
||||
DialogEntryList entry_list;
|
||||
|
||||
for(it = dfiles.begin(), it_end = dfiles.end(); it != it_end; ++it) {
|
||||
if((*it).empty())
|
||||
continue;
|
||||
|
||||
name = (*it).c_str();
|
||||
|
||||
if(!str_ends(name, ".desktop"))
|
||||
continue;
|
||||
|
||||
if(!df.load(name)) {
|
||||
E_WARNING(E_STRLOC ": Can't load '%s'. Skipping...\n", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* files marked as hidden must be skipped */
|
||||
if(df.hidden())
|
||||
continue;
|
||||
|
||||
if(!df.exec(buf, sizeof(buf)))
|
||||
continue;
|
||||
|
||||
DialogEntry* en = new DialogEntry;
|
||||
en->exec = buf;
|
||||
|
||||
/* figure out the name */
|
||||
if(df.name(buf, sizeof(buf)))
|
||||
en->name = buf;
|
||||
else
|
||||
en->name = name;
|
||||
|
||||
/* get the comment */
|
||||
if(df.comment(buf, sizeof(buf)))
|
||||
en->comment = buf;
|
||||
|
||||
entry_list.push_back(en);
|
||||
}
|
||||
|
||||
if(safe)
|
||||
run_autostart_dialog(entry_list);
|
||||
else
|
||||
entry_list_run_clear(entry_list, true);
|
||||
}
|
||||
|
||||
static void perform_autostart_scripts(const char* path) {
|
||||
int i;
|
||||
String name;
|
||||
|
||||
for(i = 0; autostart_names[i]; i++) {
|
||||
name = path;
|
||||
name += E_DIR_SEPARATOR_STR;
|
||||
name += autostart_names[i];
|
||||
|
||||
if(file_test(name.c_str(), FILE_TEST_IS_REGULAR | FILE_TEST_IS_EXECUTABLE)) {
|
||||
if(ask(_("Mounted media at '%s' would like to start some files. "
|
||||
"Content of these files is not checked and could be malicious. "
|
||||
"Would you like to start them?"), path))
|
||||
{
|
||||
/* spec said how we must chdir to the root of the medium */
|
||||
chdir(path);
|
||||
AUTOSTART_RUN(name.c_str());
|
||||
}
|
||||
|
||||
/* we only match the one file */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void help(void) {
|
||||
puts("Usage: ede-autostart [OPTIONS]");
|
||||
puts("EDE autostart utility");
|
||||
puts("Options:");
|
||||
puts(" -h, --help this help");
|
||||
puts(" -s, --safe show dialog of commands to be executed");
|
||||
puts(" -m, --media [DEST] execute autostart scripts from mounted [DEST]");
|
||||
}
|
||||
|
||||
static const char* next_param(int curr, char** argv, int argc) {
|
||||
int j = curr + 1;
|
||||
if(j >= argc)
|
||||
return NULL;
|
||||
if(argv[j][0] == '-')
|
||||
return NULL;
|
||||
return argv[j];
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if(argc == 1) {
|
||||
perform_autostart(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *a, *media = NULL;
|
||||
bool safe = false;
|
||||
|
||||
for(int i = 1; i < argc; i++) {
|
||||
a = argv[i];
|
||||
if(CHECK_ARGV(a, "-h", "--help")) {
|
||||
help();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(CHECK_ARGV(a, "-s", "--safe")) {
|
||||
safe = true;
|
||||
} else if(CHECK_ARGV(a, "-m", "--media")) {
|
||||
media = next_param(i, argv, argc);
|
||||
if(!media) {
|
||||
puts("Missing media parameter");
|
||||
return 1;
|
||||
}
|
||||
|
||||
i++;
|
||||
} else {
|
||||
printf("Unknown '%s' parameter. Run 'ede-autostart -h' for options\n", a);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(media == NULL)
|
||||
perform_autostart(safe);
|
||||
else
|
||||
perform_autostart_scripts(media);
|
||||
return 0;
|
||||
}
|
319
ede-autostart/icons/warning.xpm
Normal file
319
ede-autostart/icons/warning.xpm
Normal file
@ -0,0 +1,319 @@
|
||||
/* XPM */
|
||||
static char * warning_xpm[] = {
|
||||
"32 32 284 2",
|
||||
" c None",
|
||||
". c #D04D00",
|
||||
"+ c #D24E00",
|
||||
"@ c #C64900",
|
||||
"# c #E37B00",
|
||||
"$ c #D14E00",
|
||||
"% c #D55600",
|
||||
"& c #FCBF00",
|
||||
"* c #EE9A00",
|
||||
"= c #FFC700",
|
||||
"- c #DA6500",
|
||||
"; c #FFD32E",
|
||||
"> c #FFFDCB",
|
||||
", c #CB4C00",
|
||||
"' c #F4AA02",
|
||||
") c #FFF3AB",
|
||||
"! c #FFFFE1",
|
||||
"~ c #B44300",
|
||||
"{ c #E37C00",
|
||||
"] c #FFDE58",
|
||||
"^ c #FFFFE0",
|
||||
"/ c #FFFFDF",
|
||||
"( c #FFDE56",
|
||||
"_ c #F9BF0D",
|
||||
": c #FFF9C3",
|
||||
"< c #C6C6B8",
|
||||
"[ c #969696",
|
||||
"} c #FFF8C1",
|
||||
"| c #BD4600",
|
||||
"1 c #E99002",
|
||||
"2 c #FFEA7C",
|
||||
"3 c #EDEDD4",
|
||||
"4 c #979797",
|
||||
"5 c #989898",
|
||||
"6 c #949494",
|
||||
"7 c #D9D9C6",
|
||||
"8 c #FFEA7A",
|
||||
"9 c #E98F01",
|
||||
"0 c #D85F00",
|
||||
"a c #FFDA26",
|
||||
"b c #FFFCCD",
|
||||
"c c #E5E5C8",
|
||||
"d c #C9C9B6",
|
||||
"e c #FFFCCB",
|
||||
"f c #FFD924",
|
||||
"g c #C94B00",
|
||||
"h c #F1AB01",
|
||||
"i c #FFF292",
|
||||
"j c #FFFFD3",
|
||||
"k c #EBEBC7",
|
||||
"l c #959595",
|
||||
"m c #929292",
|
||||
"n c #DCDCBC",
|
||||
"o c #FFFFD1",
|
||||
"p c #FFF28C",
|
||||
"q c #DD7100",
|
||||
"r c #FFE43F",
|
||||
"s c #FFFEC5",
|
||||
"t c #FFFFCB",
|
||||
"u c #FFFFCC",
|
||||
"v c #989894",
|
||||
"w c #919191",
|
||||
"x c #909090",
|
||||
"y c #8E8E8E",
|
||||
"z c #F8F8C6",
|
||||
"A c #FFFFC7",
|
||||
"B c #FFFEBF",
|
||||
"C c #FFE236",
|
||||
"D c #F9CC0A",
|
||||
"E c #FFF99D",
|
||||
"F c #FFFFC4",
|
||||
"G c #FFFFC3",
|
||||
"H c #B7B7A1",
|
||||
"I c #8B8B8B",
|
||||
"J c #8A8A8A",
|
||||
"K c #9E9E93",
|
||||
"L c #FFFFC1",
|
||||
"M c #FFFFBE",
|
||||
"N c #FFFFBC",
|
||||
"O c #FFF892",
|
||||
"P c #F9CB06",
|
||||
"Q c #B84500",
|
||||
"R c #E68D00",
|
||||
"S c #FFEC51",
|
||||
"T c #FFFFBA",
|
||||
"U c #FFFFB9",
|
||||
"V c #FFFFBB",
|
||||
"W c #D1D1A6",
|
||||
"X c #838383",
|
||||
"Y c #B8B898",
|
||||
"Z c #FFFFB6",
|
||||
"` c #FFFFB3",
|
||||
" . c #FFFFAF",
|
||||
".. c #FFFFAB",
|
||||
"+. c #FFEA43",
|
||||
"@. c #D55700",
|
||||
"#. c #FCDB13",
|
||||
"$. c #FFFB97",
|
||||
"%. c #FFFFAE",
|
||||
"&. c #EEEEA8",
|
||||
"*. c #7A7A7A",
|
||||
"=. c #797979",
|
||||
"-. c #DCDC9E",
|
||||
";. c #FFFFA9",
|
||||
">. c #FFFFA5",
|
||||
",. c #FFFFA1",
|
||||
"'. c #FFFF9E",
|
||||
"). c #FFFB82",
|
||||
"!. c #FCDA0C",
|
||||
"~. c #EEAC00",
|
||||
"{. c #FFF356",
|
||||
"]. c #FFFFA4",
|
||||
"^. c #FFFFA2",
|
||||
"/. c #FFFFA3",
|
||||
"(. c #8B8B79",
|
||||
"_. c #6E6E6E",
|
||||
":. c #FFFF9D",
|
||||
"<. c #FFFF9B",
|
||||
"[. c #FFFF98",
|
||||
"}. c #FFFF93",
|
||||
"|. c #FFFF8D",
|
||||
"1. c #FFFF8B",
|
||||
"2. c #FFF243",
|
||||
"3. c #DA6B00",
|
||||
"4. c #FFEB18",
|
||||
"5. c #FFFE8A",
|
||||
"6. c #FFFF92",
|
||||
"7. c #FFFF94",
|
||||
"8. c #A7A776",
|
||||
"9. c #88886C",
|
||||
"0. c #FFFF8A",
|
||||
"a. c #FFFF87",
|
||||
"b. c #FFFF82",
|
||||
"c. c #FFFF7C",
|
||||
"d. c #FFFF78",
|
||||
"e. c #FFFD6D",
|
||||
"f. c #FFEA0E",
|
||||
"g. c #F4C400",
|
||||
"h. c #FFF854",
|
||||
"i. c #FFFF81",
|
||||
"j. c #FFFF80",
|
||||
"k. c #F4F47C",
|
||||
"l. c #E9E978",
|
||||
"m. c #FFFF7A",
|
||||
"n. c #FFFF77",
|
||||
"o. c #FFFF73",
|
||||
"p. c #FFFF6F",
|
||||
"q. c #FFFF6B",
|
||||
"r. c #FFFF65",
|
||||
"s. c #FFFF62",
|
||||
"t. c #FFF73A",
|
||||
"u. c #E38A00",
|
||||
"v. c #FFF21E",
|
||||
"w. c #FFFF69",
|
||||
"x. c #FFFF6E",
|
||||
"y. c #FFFF6C",
|
||||
"z. c #FFFF66",
|
||||
"A. c #FFFF5F",
|
||||
"B. c #FFFF5C",
|
||||
"C. c #FFFF57",
|
||||
"D. c #FFFF53",
|
||||
"E. c #FFFF4D",
|
||||
"F. c #FFFF4A",
|
||||
"G. c #FFF111",
|
||||
"H. c #D55800",
|
||||
"I. c #F9DD01",
|
||||
"J. c #FFFC43",
|
||||
"K. c #FFFF58",
|
||||
"L. c #FFFF5B",
|
||||
"M. c #B5B54D",
|
||||
"N. c #46463C",
|
||||
"O. c #373737",
|
||||
"P. c #9A9A44",
|
||||
"Q. c #FFFF50",
|
||||
"R. c #FFFF4C",
|
||||
"S. c #FFFF49",
|
||||
"T. c #FFFF45",
|
||||
"U. c #FFFF40",
|
||||
"V. c #FFFF3D",
|
||||
"W. c #FFFF3A",
|
||||
"X. c #FFFB29",
|
||||
"Y. c #F9DD00",
|
||||
"Z. c #E9A100",
|
||||
"`. c #FFF819",
|
||||
" + c #FFFF41",
|
||||
".+ c #FFFF43",
|
||||
"++ c #FFFF48",
|
||||
"@+ c #FFFF47",
|
||||
"#+ c #FFFF46",
|
||||
"$+ c #3C3C31",
|
||||
"%+ c #2E2E2E",
|
||||
"&+ c #2C2C2C",
|
||||
"*+ c #292929",
|
||||
"=+ c #E4E43A",
|
||||
"-+ c #FFFF39",
|
||||
";+ c #FFFF37",
|
||||
">+ c #FFFF33",
|
||||
",+ c #FFFF30",
|
||||
"'+ c #FFFF2C",
|
||||
")+ c #FFFF29",
|
||||
"!+ c #FFFF27",
|
||||
"~+ c #FFF70D",
|
||||
"{+ c #D86300",
|
||||
"]+ c #FCED05",
|
||||
"^+ c #FFFE25",
|
||||
"/+ c #FFFF2D",
|
||||
"(+ c #FFFF32",
|
||||
"_+ c #FFFF31",
|
||||
":+ c #323225",
|
||||
"<+ c #232323",
|
||||
"[+ c #202020",
|
||||
"}+ c #1E1E1E",
|
||||
"|+ c #E3E326",
|
||||
"1+ c #FFFF25",
|
||||
"2+ c #FFFF22",
|
||||
"3+ c #FFFF20",
|
||||
"4+ c #FFFF1E",
|
||||
"5+ c #FFFF1B",
|
||||
"6+ c #FFFF19",
|
||||
"7+ c #FFFF17",
|
||||
"8+ c #FFFE13",
|
||||
"9+ c #FCED02",
|
||||
"0+ c #C54900",
|
||||
"a+ c #F1C500",
|
||||
"b+ c #FFFB0E",
|
||||
"c+ c #FFFF1A",
|
||||
"d+ c #FFFF1D",
|
||||
"e+ c #FFFF1F",
|
||||
"f+ c #A9A91C",
|
||||
"g+ c #191919",
|
||||
"h+ c #181818",
|
||||
"i+ c #6E6E16",
|
||||
"j+ c #FFFF14",
|
||||
"k+ c #FFFF13",
|
||||
"l+ c #FFFF11",
|
||||
"m+ c #FFFF0F",
|
||||
"n+ c #FFFF0D",
|
||||
"o+ c #FFFF0B",
|
||||
"p+ c #FFFF0A",
|
||||
"q+ c #FFFF08",
|
||||
"r+ c #FFFB04",
|
||||
"s+ c #DD7A00",
|
||||
"t+ c #FFFE00",
|
||||
"u+ c #FFFE0F",
|
||||
"v+ c #FFFF15",
|
||||
"w+ c #FFFF16",
|
||||
"x+ c #FFFF12",
|
||||
"y+ c #FFFF10",
|
||||
"z+ c #FFFF0E",
|
||||
"A+ c #FFFF0C",
|
||||
"B+ c #FFFF09",
|
||||
"C+ c #FFFF07",
|
||||
"D+ c #FFFF06",
|
||||
"E+ c #FFFF05",
|
||||
"F+ c #FFFE02",
|
||||
"G+ c #E08500",
|
||||
"H+ c #F4D300",
|
||||
"I+ c #F5D50C",
|
||||
"J+ c #F5D50D",
|
||||
"K+ c #F5D50E",
|
||||
"L+ c #F5D60F",
|
||||
"M+ c #F5D610",
|
||||
"N+ c #F4D50B",
|
||||
"O+ c #F4D509",
|
||||
"P+ c #F4D408",
|
||||
"Q+ c #F4D407",
|
||||
"R+ c #F4D406",
|
||||
"S+ c #F4D405",
|
||||
"T+ c #F4D404",
|
||||
"U+ c #F4D403",
|
||||
"V+ c #F4D302",
|
||||
"W+ c #F4D301",
|
||||
"X+ c #CA4B00",
|
||||
"Y+ c #D35104",
|
||||
"Z+ c #D35307",
|
||||
"`+ c #D35408",
|
||||
" @ c #D45409",
|
||||
".@ c #D4550A",
|
||||
"+@ c #D35206",
|
||||
"@@ c #D35105",
|
||||
"#@ c #D35003",
|
||||
"$@ c #D24F02",
|
||||
"%@ c #D24F01",
|
||||
"&@ c #B14200",
|
||||
" ",
|
||||
" ",
|
||||
" . + + @ ",
|
||||
" + # # + ",
|
||||
" $ % & & % @ ",
|
||||
" + * = = * + ",
|
||||
" $ - ; > > ; - , ",
|
||||
" . + ' ) ! ! ) ' + ~ ",
|
||||
" $ { ] ^ / / / ( { . ",
|
||||
" . % _ : < [ [ < } _ % | ",
|
||||
" + 1 2 3 [ 4 5 6 7 8 9 + ",
|
||||
" $ 0 a b c [ [ [ 6 d e f 0 g ",
|
||||
" + h i j k l l 6 m n o p h + ",
|
||||
" + q r s t u v w x y z A B C q . ",
|
||||
" . + D E F G F H I J K L M N O P + Q ",
|
||||
" + R S T U T V W X X Y Z ` ...+.R + ",
|
||||
" $ @.#.$. .%. . .&.*.=.-.;.>.,.'.).!.@.@ ",
|
||||
" + ~.{.].,.,.^./.,.(._.:.<.[.}.|.1.2.~.+ ",
|
||||
" $ 3.4.5.6.6.7.7.7.6.8.9.|.0.a.b.c.d.e.f.3., ",
|
||||
" . + g.h.i.j.i.b.b.i.i.k.l.m.n.o.p.q.r.s.t.g.+ ~ ",
|
||||
" $ u.v.w.q.x.x.p.x.x.y.q.w.z.s.A.B.C.D.E.F.G.u.. ",
|
||||
" . H.I.J.C.K.L.B.B.L.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.H.| ",
|
||||
" + Z.`. +.+T.++++++@+#+$+%+&+*+=+-+;+>+,+'+)+!+~+Z.+ ",
|
||||
" $ {+]+^+/+,+(+(+(+(+(+_+:+<+[+}+|+1+2+3+4+5+6+7+8+9+{+0+ ",
|
||||
" + a+b+c+5+d+e+e+3+3+e+e+f+g+h+i+7+j+k+l+m+n+o+p+q+r+a++ ",
|
||||
"$ s+t+u+k+j+v+w+7+w+7+v+v+j+k+x+y+m+z+A+A+B+q+C+D+E+F+t+s+, ",
|
||||
"+ G+H+I+J+K+L+L+M+M+M+L+L+K+J+J+N+O+O+P+Q+R+S+T+U+V+W+H+G++ ",
|
||||
"X++ + Y+Z+`+`+ @.@.@ @ @ @`+`+Z++@@@+@@@Y+Y+#@$@%@%@%@+ + &@ ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
Reference in New Issue
Block a user