From 05a7f14f8dbf46fa64c035127ff1e04cfffb841b Mon Sep 17 00:00:00 2001 From: Dave Chapman Date: Fri, 15 Sep 2006 11:11:16 +0000 Subject: Initial commit of zxbox - a ZX Spectrum emulator ported by Anton Romanov. It theoretically runs on all targets, but I have not included it in the Archos builds because it is just too slow to be usable. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10950 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/zxbox/ax.c | 815 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 815 insertions(+) create mode 100644 apps/plugins/zxbox/ax.c (limited to 'apps/plugins/zxbox/ax.c') diff --git a/apps/plugins/zxbox/ax.c b/apps/plugins/zxbox/ax.c new file mode 100644 index 0000000000..c7db7f5c6b --- /dev/null +++ b/apps/plugins/zxbox/ax.c @@ -0,0 +1,815 @@ +/* + * Copyright (C) 1996-1998 Szeredi Miklos + * Email: mszeredi@inf.bme.hu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. See the file COPYING. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * + * ax.c + * + * + * + * Created: 94/11/11 Szeredi Miklos + * + * Version: 0.1 94/11/11 + * 0.2 95/06/12 + * + */ + +/* #define DEBUG_EVENTS */ + +#include "ax.h" +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +typedef int boolean; +#define max(x, y) ((x) < (y) ? (y) : (x)) +#define min(x, y) ((x) < (y) ? (x) : (y)) +#define minmax(a, l, u) ((a) < (l) ? (l) : ((a) > (u) ? (u) : (a))) + +#define MAX_PROG_NAME_LEN 128 +#define MAX_CLASS_NAME_LEN MAX_PROG_NAME_LEN +#define MAX_PRES_LEN 256 +#define MAX_FILENAME_LEN 1024 + +static const char *empty_str = ""; + +typedef void (*eventproc_t)(XEvent *, void *); + +typedef struct _event_proc_struct { + eventproc_t event_proc; + unsigned long event_mask; + Display *disp; + void *ptr; + Window event_win; + boolean done_proc; + struct _event_proc_struct *next_proc; +} event_proc_struct; + +typedef struct { + const char *event_name; + boolean win_given; + event_proc_struct *next_proc; +} event_struct; + +typedef struct _disp_struct{ + Display *disp; + XFontStruct *font; + struct _disp_struct *next_disp; +} disp_struct; + + +#define EVENT_NUM LASTEvent + +static event_struct event_info[EVENT_NUM]; + +static disp_struct disp_start = {NULL, NULL, NULL}; + +static boolean disp_chain_modified; + +static char prog_name[MAX_PROG_NAME_LEN + 1]; +static char class_name[MAX_CLASS_NAME_LEN + 1]; + +static XrmDatabase rDB = NULL; /* Has to be global otherwise Xlib hangs */ + +static int opTableEntries = 19; +static aX_options opTable[] = { + {"-display", ".display", XrmoptionSepArg, NULL}, + {"-geometry", ".geometry", XrmoptionSepArg, NULL}, + {"-bg", ".background", XrmoptionSepArg, NULL}, + {"-background", ".background", XrmoptionSepArg, NULL}, + {"-bd", ".borderColor", XrmoptionSepArg, NULL}, + {"-bordercolor", ".borderColor", XrmoptionSepArg, NULL}, + {"-bw", ".borderWidth", XrmoptionSepArg, NULL}, + {"-borderwidth", ".borderWidth", XrmoptionSepArg, NULL}, + {"-fg", ".foreground", XrmoptionSepArg, NULL}, + {"-foreground", ".foreground", XrmoptionSepArg, NULL}, + {"-fn", ".font", XrmoptionSepArg, NULL}, + {"-font", ".font", XrmoptionSepArg, NULL}, + {"-name", ".name", XrmoptionSepArg, NULL}, + {"-rv", ".reverseVideo", XrmoptionNoArg, "on"}, + {"-reverse", ".reverseVideo", XrmoptionNoArg, "on"}, + {"+rv", ".reverseVideo", XrmoptionNoArg, "off"}, + {"-bg", ".background", XrmoptionSepArg, NULL}, + {"-title", ".title", XrmoptionSepArg, NULL}, + {"-xrm", NULL, XrmoptionResArg, NULL} +}; + +static char *addstr(const char str1[], const char str2[], char str12[], + unsigned int str12len) +{ + unsigned int i, j, k; + + str12[str12len-1] = '\0'; + + for(i=0, j=0, k=0; i + 1 < str12len; ) { + if(str1[j]) str12[i] = str1[j++]; + else str12[i] = str2[k++]; + if(! str12[i++]) break; + } + return str12; +} + + +static char *pname(const char *resource) { + static char pnameres[MAX_PRES_LEN]; + + return addstr(prog_name, resource, pnameres, MAX_PRES_LEN); +} + +static char *pclass(const char *resource) { + static char pclassres[MAX_PRES_LEN]; + + return addstr(class_name, resource, pclassres, MAX_PRES_LEN); +} + + +static void fill_event_info(void) +{ + int i; + + for(i = 0; i < EVENT_NUM; i++) { + event_info[i].event_name = empty_str; + event_info[i].win_given = TRUE; + event_info[i].next_proc = NULL; + } + + event_info[MappingNotify].win_given = FALSE; + + event_info[ButtonPress].event_name = "ButtonPress"; + event_info[ButtonRelease].event_name = "ButtonRelease"; + event_info[CirculateNotify].event_name = "CirculateNotify"; + event_info[CirculateRequest].event_name = "CirculateRequest"; + event_info[ClientMessage].event_name = "ClientMessage"; + event_info[ColormapNotify].event_name = "ColormapNotify"; + event_info[ConfigureNotify].event_name = "ConfigureNotify"; + event_info[ConfigureRequest].event_name = "ConfigureRequest"; + event_info[CreateNotify].event_name = "CreateNotify"; + event_info[DestroyNotify].event_name = "DestroyNotify"; + event_info[EnterNotify].event_name = "EnterNotify"; + event_info[LeaveNotify].event_name = "LeaveNotify"; + event_info[Expose].event_name = "Expose"; + event_info[FocusIn].event_name = "FocusIn"; + event_info[FocusOut].event_name = "FocusOut"; + event_info[GraphicsExpose].event_name = "GraphicsExpose"; + event_info[NoExpose].event_name = "NoExpose"; + event_info[GravityNotify].event_name = "GravityNotify"; + event_info[KeymapNotify].event_name = "KeymapNotify"; + event_info[KeyPress].event_name = "KeyPress"; + event_info[KeyRelease].event_name = "KeyRelease"; + event_info[MapNotify].event_name = "MapNotify"; + event_info[UnmapNotify].event_name = "UnmapNotify"; + event_info[MappingNotify].event_name = "MappingNotify"; + event_info[MapRequest].event_name = "MapRequest"; + event_info[MotionNotify].event_name = "MotionNotify"; + event_info[PropertyNotify].event_name = "PropertyNotify"; + event_info[ReparentNotify].event_name = "ReparentNotify"; + event_info[ResizeRequest].event_name = "ResizeRequest"; + event_info[SelectionClear].event_name = "SelectionClear"; + event_info[SelectionNotify].event_name = "SelectionNotify"; + event_info[SelectionRequest].event_name = "SelectionRequest"; + event_info[VisibilityNotify].event_name = "VisibilityNotify"; + +} + +static void get_def_res(aX_default_resources *defres) +{ + XrmValue value; + char *str_type; + int flags; + XColor color_def; + unsigned long tmp_pixel; + Colormap def_map; + int font_spec; + + + defres->window_name = prog_name; + defres->icon_name = prog_name; + + + defres->scr = DefaultScreen(defres->disp); + defres->scr_ptr = ScreenOfDisplay(defres->disp, defres->scr); + def_map = DefaultColormapOfScreen(defres->scr_ptr); + + + if(XrmGetResource(rDB, pname(".title"), pclass(".Title"), + &str_type, &value)) + defres->window_name = (char *) value.addr; + + defres->sflags = PSize; + if(XrmGetResource(rDB, pname(".geometry"), pclass(".Geometry"), + &str_type, &value)) { + flags = XParseGeometry((char *) value.addr, &(defres->x), &(defres->y), + &(defres->width), &(defres->height)); + if((XValue | YValue) & flags) defres->sflags |= USPosition; + if((WidthValue | HeightValue) & flags) + defres->sflags = (defres->sflags & ~PSize) | USSize; + } + + defres->background = defres->background ? + WhitePixel(defres->disp, defres->scr) : + BlackPixel(defres->disp, defres->scr); + + if(XrmGetResource(rDB, pname(".background"), pclass(".Background"), + &str_type, &value)) { + if(XParseColor(defres->disp, def_map, value.addr, &color_def)) { + if(XAllocColor(defres->disp, def_map, &color_def)) + defres->background = color_def.pixel; + } + else fprintf(stderr, "%s: aX: warning: Invalid color specification %s\n", + prog_name, value.addr); + } + + defres->foreground = defres->foreground ? + WhitePixel(defres->disp, defres->scr) : + BlackPixel(defres->disp, defres->scr); + + if(XrmGetResource(rDB, pname(".foreground"), pclass(".Foreground"), + &str_type, &value)) { + if(XParseColor(defres->disp, def_map, value.addr, &color_def)) { + if(XAllocColor(defres->disp, def_map, &color_def)) + defres->foreground = color_def.pixel; + } + else fprintf(stderr, "%s: aX: warning: Invalid color specification %s\n", + prog_name, value.addr); + } + + if(XrmGetResource(rDB, pname(".borderWidth"), pclass(".BorderWidth"), + &str_type, &value)) { + defres->border_width = atoi(value.addr); + } + + defres->border_color = defres->foreground; + if(XrmGetResource(rDB, pname(".borderColor"), pclass(".BorderColor"), + &str_type, &value)) { + if(XParseColor(defres->disp, def_map, value.addr, &color_def)) { + if(XAllocColor(defres->disp, def_map, &color_def)) + defres->border_color = color_def.pixel; + } + else fprintf(stderr, "%s: aX: warning: Invalid color specification %s\n", + prog_name, value.addr); + } + + font_spec = 0; + if(XrmGetResource(rDB, pname(".font"), pclass(".Font"), + &str_type, &value)) { + defres->font_name = value.addr; + if(defres->font_name != NULL) font_spec = 1; + + } + + if(XrmGetResource(rDB, pname(".fallbackFont"), pclass(".Font"), + &str_type, &value)) + defres->fallback_font_name = value.addr; + + if(defres->font_name == NULL || + (defres->font = XLoadQueryFont(defres->disp, defres->font_name)) + == NULL) { + + if(font_spec) + fprintf(stderr, "%s: aX: warning: cannot open %s font, ", + prog_name, defres->font_name); + + defres->font_name = defres->fallback_font_name; + + if(font_spec && defres->font_name != NULL) + fprintf(stderr, "trying %s...\n",defres->font_name); + + if(defres->font_name == NULL || + (defres->font = + XLoadQueryFont(defres->disp, defres->fallback_font_name)) == NULL) { + + if(defres->font_name != NULL) { + + fprintf(stderr, "%s: aX: warning: cannot open %s font, ", + prog_name, defres->font_name); + } + + defres->font_name = "fixed"; + + fprintf(stderr, "trying %s...\n",defres->font_name); + + if((defres->font = XLoadQueryFont(defres->disp, defres->font_name)) + == NULL) { + + fprintf(stderr, "%s: aX: warning: cannot open %s font\n", + prog_name, defres->font_name); + + exit(-1); + } + } + else defres->font_name = defres->fallback_font_name; + } + + if(XrmGetResource(rDB, pname(".reverseVideo"), pclass(".ReverseVideo"), + &str_type, &value)) + if(strcmp(value.addr, "on") == 0) { + tmp_pixel = defres->foreground; + defres->foreground = defres->background; + defres->background = tmp_pixel; + } + +} + + +static void add_disp(aX_default_resources *defres) +{ + disp_struct *last; + + for(last = &disp_start; last->next_disp != NULL; last = last->next_disp); + + if((last->next_disp = malloc(sizeof(disp_struct))) == NULL) { + fprintf(stderr, "%s: aX: Not enough memory.\n", prog_name); + exit(-1); + }; + + last = last->next_disp; + + last->disp = defres->disp; + last->font = defres->font; + last->next_disp = NULL; + + + disp_chain_modified = TRUE; +} + +void aX_open_disp(aX_options *useropt, int useroptlen, + int *argcp, char *argv[], + aX_default_resources *defres) +{ + + XrmValue value; + char *str_type; + char *disp_res; + char *environment; + char *display_name = NULL; + char filename[MAX_FILENAME_LEN]; + int i; + XrmDatabase commandlineDB = NULL, usercommandlineDB = NULL; + XrmDatabase homeDB, serverDB, applicationDB; + +/* + if(disp_start.next_disp != NULL) { + fprintf(stderr, "aX_open_disp: Cannot open first display twice.\n"); + exit(-1); + } +*/ + + XrmInitialize(); + + class_name[0] = '\0'; + class_name[MAX_CLASS_NAME_LEN] = '\0'; + if(defres->class_name != NULL) + strncpy(class_name, defres->class_name, MAX_CLASS_NAME_LEN); + + + fill_event_info(); + + for(i = 1; i < *argcp; i++) + if(strcmp(argv[i], "-name") == 0 && ++i < *argcp){ + defres->prog_name = argv[i]; + break; + } + + + prog_name[0] = '\0'; + prog_name[MAX_PROG_NAME_LEN] = '\0'; + if(defres->prog_name != NULL) + strncpy(prog_name, defres->prog_name, MAX_PROG_NAME_LEN); + else + strncpy(prog_name, argv[0], MAX_PROG_NAME_LEN); + + defres->prog_name = prog_name; + + XrmParseCommand(&commandlineDB, (XrmOptionDescRec *) opTable, + opTableEntries, prog_name, argcp, argv); + + if(useropt != NULL) + XrmParseCommand(&usercommandlineDB, (XrmOptionDescRec *) useropt, + useroptlen, prog_name, argcp, argv); + else usercommandlineDB = NULL; + +/* + if(*argcp != 1) { + fprintf(stderr, + "%s: aX_open_disp: Unrecognised options in command line!\n", + prog_name); + exit(-1); + } +*/ + + if(XrmGetResource(commandlineDB, pname(".display"), pclass(".Display"), + &str_type, &value)) display_name = (char *) value.addr; + + if((defres->disp = XOpenDisplay(display_name)) == NULL) { + fprintf(stderr, "%s: aX_open_disp: cannot connect to X server %s\n", + prog_name, XDisplayName(display_name)); + exit(-1); + } + + applicationDB = XrmGetFileDatabase( + addstr("/usr/lib/X11/app-defaults/", + class_name, + filename, + MAX_FILENAME_LEN)); +/* + if(defres->disp->xdefaults) + serverDB = XrmGetStringDatabase(defres->disp->xdefaults); + else serverDB = NULL; +*/ + + + disp_res = XResourceManagerString(defres->disp); + + if(disp_res) serverDB = XrmGetStringDatabase(disp_res); + else serverDB = NULL; + + + if((environment = getenv("XENVIRONMENT")) != NULL) + homeDB = XrmGetFileDatabase(environment); + else homeDB = NULL; + + + XrmMergeDatabases(applicationDB, &rDB); + XrmMergeDatabases(serverDB, &rDB); + XrmMergeDatabases(homeDB, &rDB); + XrmMergeDatabases(commandlineDB, &rDB); + XrmMergeDatabases(usercommandlineDB, &rDB); + + get_def_res(defres); + + add_disp(defres); + +} + + +void aX_open_second_disp(char *display_name, + aX_default_resources *defres) +{ + char *disp_res; + + XrmDatabase serverDB; + + + if((defres->disp = XOpenDisplay(display_name)) == NULL) { + fprintf(stderr, + "%s: aX_open_second_disp: cannot connect to X server %s\n", + prog_name, XDisplayName(display_name)); + exit(-1); + } + + + disp_res = XResourceManagerString(defres->disp); + + if(disp_res) serverDB = XrmGetStringDatabase(disp_res); + else serverDB = NULL; + + + XrmMergeDatabases(serverDB, &rDB); + + get_def_res(defres); + + add_disp(defres); +} + +/* + +void smallwait(boolean event_prev) +{ + event_prev = event_prev; + sleep(1); +} + +*/ + + +static void sigalrm_handler(int i) +{ + i = i; + signal(SIGALRM, SIG_IGN); +} + + +static void smallwait(boolean event_prev) +{ + struct itimerval value; + + signal(SIGALRM, sigalrm_handler); + + event_prev = event_prev; + + value.it_interval.tv_sec = 0L; + value.it_interval.tv_usec = 0L; + value.it_value.tv_sec = 0L; + value.it_value.tv_usec = 100000L; + setitimer(ITIMER_REAL, &value, NULL); + + pause(); +} + +/* This aX_wait_all_muck needs to be cleared out! */ + +void aX_wait_event(int eventtype) +{ + XEvent ev; + event_proc_struct **curr; + int i; + disp_struct *dsp, *dsp1; + + boolean event_prev; + + +start:; + + if(disp_start.next_disp == NULL) { + fprintf(stderr, "%s: aX_wait_event: No connection to any display\n", + prog_name); + exit(-1); + } + + dsp = disp_start.next_disp; + + + do { + event_prev = TRUE; + + dsp1 = dsp; + if((disp_start.next_disp)->next_disp != NULL || + eventtype == AX_LOOK_EVENTS) + while(XPending(dsp->disp) == 0) { + dsp = dsp->next_disp; + if(dsp == NULL) dsp = disp_start.next_disp; + + if(dsp == dsp1) { + if(eventtype == AX_LOOK_EVENTS) return; + + smallwait(event_prev); + event_prev = FALSE; + dsp = dsp1 = disp_start.next_disp; + } + } + + XNextEvent(dsp->disp, &ev); +#ifdef DEBUG_EVENTS + fprintf(stderr,"Event: %s (%i) in win: %li)\n", + event_info[ev.type].event_name, + ev.type, + ev.xany.window); +#endif + + + if(dsp->disp != ev.xany.display) + fprintf(stderr, "Ha! Event read from wrong display! Stupid XLib!!!\n"); + + curr = &(event_info[ev.type].next_proc); + i = 0; + while(*curr != NULL) { + if((*curr)->disp == dsp->disp && + (!event_info[ev.type].win_given || + ev.xany.window == (*curr)->event_win) && + !(*curr)->done_proc) { + i++; + (*curr)->done_proc = TRUE; + disp_chain_modified = FALSE; + + if((*curr)->event_proc != NULL) { + (*((*curr)->event_proc))(&ev, (*curr)->ptr); + } + + if(disp_chain_modified) goto start; + curr = &(event_info[ev.type].next_proc); + } + else curr = &((*curr)->next_proc); + } + curr = &(event_info[ev.type].next_proc); + while(*curr != NULL) { + (*curr)->done_proc = FALSE; + curr = &((*curr)->next_proc); + } + + if(i == 0) + fprintf(stderr, "%s: aX_wait_event: warning: " + "Unexpected event: %s (%i) in win: %li)\n", + prog_name, + event_info[ev.type].event_name, + ev.type, + ev.xany.window); + + } while(eventtype != ev.type && eventtype != AX_ANY_EVENT); +} + + +void aX_look_events(void) +{ + aX_wait_event(AX_LOOK_EVENTS); +} + +char *aX_get_prog_res(const char *resname, const char* resclass) +{ + XrmValue value; + char *str_type; + + if(XrmGetResource(rDB, pname(resname), pclass(resclass), + &str_type, &value)) + return (char *)value.addr; + else return NULL; +} + +char *aX_get_resource(const char *resname, const char* resclass) +{ + XrmValue value; + char *str_type; + + if(XrmGetResource(rDB, resname, resclass, + &str_type, &value)) + return (char *)value.addr; + else return NULL; +} + +static long get_win_mask(Display *disp, Window win) +{ + int evt; + event_proc_struct *ep; + long winmask; + + for(evt = 0, winmask = 0; evt < EVENT_NUM; evt++) { + ep = event_info[evt].next_proc; + while(ep != NULL) { + if(ep->event_win == win && ep->disp == disp) winmask |= ep->event_mask; + ep = ep->next_proc; + } + } + return winmask; +} + + + +void aX_add_event_proc(Display *disp, + Window win, + int eventtype, + void (*eventproc)(XEvent *, void *), + unsigned long eventmask, + void *ptr) +{ + event_proc_struct **epp; + long winmask; + + epp = &(event_info[eventtype].next_proc); + while(*epp != NULL) epp = &((*epp)->next_proc); + + if((*epp = (event_proc_struct *) + malloc((size_t) sizeof(event_proc_struct))) == NULL) { + fprintf(stderr, + "%s: aX_add_event_proc_disp: Not enough memory.\n", prog_name); + exit(-1); + } + + (*epp)->event_proc = eventproc; + (*epp)->ptr = ptr; + (*epp)->event_mask = eventmask; + (*epp)->disp = disp; + (*epp)->event_win = win; + (*epp)->done_proc = FALSE; + (*epp)->next_proc = NULL; + + if(win) { + winmask = get_win_mask(disp, win); + XSelectInput(disp, win, winmask); + } +} + +void aX_remove_event_proc(Display *disp, + Window win, + int eventtype, + void (*eventproc)(XEvent *, void *)) +{ + event_proc_struct **epp; + event_proc_struct *tmp; + long winmask; + + epp = &(event_info[eventtype].next_proc); + while(*epp != NULL) { + if((*epp)->disp == disp && + (*epp)->event_win == win && + (*epp)->event_proc == eventproc) { + tmp = (*epp)->next_proc; + free(*epp); + *epp = tmp; + if(win) { + winmask = get_win_mask(disp, win); + XSelectInput(disp, win, winmask); + } + return; + } + else epp = &((*epp)->next_proc); + } + fprintf(stderr, "%s: aX_remove_event_proc_disp: warning: " + "Could not remove event proc (event: %s (%i), window: %lX)\n", + prog_name, event_info[eventtype].event_name, eventtype, win); + +} + +void aX_close_one_disp(Display *disp) +{ +/* int evt; + event_proc_struct **curr; */ + disp_struct *dsp, *dsp_tmp; + +/* + for(evt = 0; evt < EVENT_NUM; evt++) { + curr = &(event_info[evt].next_proc); + while(*curr != NULL) { + if(disp == (*curr)->disp) { + aX_remove_event_proc_disp((*curr)->disp, (*curr)->event_win, + evt, (*curr)->event_proc); + curr = &(event_info[evt].next_proc); + } + else curr = &((*curr)->next_proc); + } + } + +*/ + + for(dsp = &disp_start; dsp->next_disp->disp != disp; dsp = dsp->next_disp) + if(dsp->next_disp == NULL) { + fprintf(stderr, + "%s: aX_close_one_disp: warning: Trying to close unopened display.\n", + prog_name); + return; + } + + XUnloadFont(dsp->next_disp->disp, dsp->next_disp->font->fid); + XCloseDisplay(dsp->next_disp->disp); + + dsp_tmp = dsp->next_disp; + dsp->next_disp = dsp->next_disp->next_disp; + free(dsp_tmp); + + disp_chain_modified = TRUE; + +} + +void aX_close_disp(void) +{ + + while(disp_start.next_disp != NULL) + aX_close_one_disp(disp_start.next_disp->disp); + +} + + +unsigned long aX_get_color(Display *disp, int scr, unsigned long def_col, + const char *color_name) +{ + XColor color_def; + Colormap def_map; + Screen *scr_ptr; + + + if(color_name == NULL) return def_col; + + scr_ptr = ScreenOfDisplay(disp, scr); + def_map = DefaultColormapOfScreen(scr_ptr); + + if(XParseColor(disp, def_map, color_name, &color_def)) { + if(XAllocColor(disp, def_map, &color_def)) + return color_def.pixel; + } + else fprintf(stderr, + "%s: aX_get_color: warning: Invalid color specification %s\n", + prog_name, color_name); + + return def_col; + +} -- cgit v1.2.3