1    	package acl2s.plugin.graphics;
2    	
3    	import java.io.BufferedReader;
4    	import java.io.IOException;
5    	import java.io.InputStreamReader;
6    	
7    	import org.eclipse.swt.graphics.Color;
8    	
9    	import acl2s.lib.parse.obj.Cons;
10   	import acl2s.lib.parse.obj.Int;
11   	import acl2s.lib.parse.obj.LispObject;
12   	import acl2s.lib.parse.obj.NotListException;
13   	import acl2s.lib.parse.obj.Str;
14   	import acl2s.lib.parse.obj.Sym;
15   	import acl2s.plugin.misc.Colors;
16   	
17   	public final class ColorParser {
18   		public static Color parseColor(LispObject spec) throws OperationArgumentException {
19   			if (spec instanceof Str) {
20   				Color c = stringToColor(((Str)spec).value);
21   				if (c != null) {
22   					return c;
23   				} else {
24   					throw new OperationArgumentException("Not a valid color spec: " + spec);
25   				}
26   			} else if (spec instanceof Sym) {
27   				Color c = stringToColor(((Sym)spec).sym);
28   				if (c != null) {
29   					return c;
30   				} else {
31   					throw new OperationArgumentException("Not a valid color spec: " + spec);
32   				}
33   			} else if (spec instanceof Int) {
34   				int v = ((Int)spec).v.intValue();
35   				if (v > 0xFFFFFF || v < 0) {
36   					throw new OperationArgumentException("Not a valid color spec: " + spec);
37   				}
38   				return Colors.get((v >> 16) & 0xFF,
39   						          (v >> 8)  & 0xFF,
40   						          (v >> 0)  & 0xFF);
41   			} else {
42   				LispObject[] lst;
43   				try {
44   					lst = Cons.listToArray(spec);
45   				} catch (NotListException e) {
46   					throw new OperationArgumentException("Not a valid color spec: " + spec);
47   				}
48   				if (lst.length != 3 ||
49   						!(lst[0] instanceof Int) ||
50   						!(lst[1] instanceof Int) ||
51   						!(lst[2] instanceof Int)) {
52   					throw new OperationArgumentException("Not a valid color spec: " + spec);
53   				}
54   				try {
55   					return Colors.get(((Int)lst[0]).v.intValue(),
56   							          ((Int)lst[1]).v.intValue(),
57   							          ((Int)lst[2]).v.intValue());
58   				} catch (IllegalArgumentException e) {
59   					throw new OperationArgumentException("Not a valid color spec: " + spec);
60   				}
61   			}		
62   		}
63   		
64   		public static boolean isHexDigit(char c) {
65   			return (c >= '0' && c <= '9') ||
66   			       (c >= 'A' && c <= 'F') ||
67   			       (c >= 'a' && c <= 'f');
68   		}
69   		
70   		public static int getHexValue(char c) {
71   			if (c >= '0' && c <= '9') return c - '0';
72   			if (c >= 'A' && c <= 'F') return c - 'A' + 10;
73   			if (c >= 'a' && c <= 'f') return c - 'a' + 10;
74   			throw new IllegalArgumentException("Not a hex digit: '" + c + "'");
75   		}
76   		
77   		public static Color hexToColor(String hexStr) {
78   			int len = hexStr.length();
79   			int pos = 0;
80   			
81   			for (;;) {
82   				if (pos >= len) return null;
83   				if (isHexDigit(hexStr.charAt(pos))) break;
84   				pos++;
85   			}
86   			
87   			if (pos + 6 > len ||
88   				!isHexDigit(hexStr.charAt(pos + 1)) ||
89   				!isHexDigit(hexStr.charAt(pos + 2)) ||
90   				!isHexDigit(hexStr.charAt(pos + 3)) ||
91   				!isHexDigit(hexStr.charAt(pos + 4)) ||
92   				!isHexDigit(hexStr.charAt(pos + 5))) return null;
93   			
94   			int red   = (getHexValue(hexStr.charAt(pos+0)) * 16) + getHexValue(hexStr.charAt(pos+1));
95   			int green = (getHexValue(hexStr.charAt(pos+2)) * 16) + getHexValue(hexStr.charAt(pos+3));
96   			int blue  = (getHexValue(hexStr.charAt(pos+4)) * 16) + getHexValue(hexStr.charAt(pos+5));
97   			
98   			// ensure no more hex digits
99   			pos += 6;
100  			for (;;) {
101  				if (pos >= len) break;
102  				if (isHexDigit(hexStr.charAt(pos))) return null;
103  				pos++;
104  			}
105  			
106  			return Colors.get(red, green, blue);
107  		}
108  		
109  		public static Color rgbToColor(String rgbStr) {
110  			int len = rgbStr.length();
111  			int pos = 0;
112  	
113  			for (;;) {
114  				if (pos >= len) return null;
115  				if (Character.isDigit(rgbStr.charAt(pos))) break;
116  				pos++;
117  			}
118  			int red = 0;
119  			for (;;) {
120  				red = (10 * red) + (rgbStr.charAt(pos) - '0');
121  				pos++;
122  				if (red > 255 || pos >= len) return null;
123  				if (!Character.isDigit(rgbStr.charAt(pos))) break;
124  			}
125  			pos++;
126  	
127  			for (;;) {
128  				if (pos >= len) return null;
129  				if (Character.isDigit(rgbStr.charAt(pos))) break;
130  				pos++;
131  			}
132  			int green = 0;
133  			for (;;) {
134  				green = (10 * green) + (rgbStr.charAt(pos) - '0');
135  				pos++;
136  				if (green > 255 || pos >= len) return null;
137  				if (!Character.isDigit(rgbStr.charAt(pos))) break;
138  			}
139  			pos++;
140  			
141  			for (;;) {
142  				if (pos >= len) return null;
143  				if (Character.isDigit(rgbStr.charAt(pos))) break;
144  				pos++;
145  			}
146  			int blue = 0;
147  			for (;;) {
148  				blue = (10 * blue) + (rgbStr.charAt(pos) - '0');
149  				pos++;
150  				if (blue > 255) return null;
151  				if (pos >= len || !Character.isDigit(rgbStr.charAt(pos))) break;
152  			}
153  			
154  			return Colors.get(red, green, blue);
155  		}
156  		
157  		
158  		public static Color stringToColor(String str) {
159  			if (str.length() == 0)
160  				return Colors.BLACK;
161  			else if (str.startsWith("rgb("))
162  				return rgbToColor(str);
163  			else if (str.charAt(0) == '#')
164  				return hexToColor(str);
165  			else if (str.equalsIgnoreCase("Black"))
166  				return hexToColor("#000000");
167  			else if(str.equalsIgnoreCase("Silver"))
168  				return hexToColor("#C0C0C0");
169  			else if(str.equalsIgnoreCase("Gray"))
170  				return hexToColor("#808080");
171  			else if(str.equalsIgnoreCase("White"))
172  				return hexToColor("#FFFFFF");
173  			else if(str.equalsIgnoreCase("Maroon"))
174  				return hexToColor("#800000");
175  			else if(str.equalsIgnoreCase("Red"))
176  				return hexToColor("#FF0000");
177  			else if(str.equalsIgnoreCase("Purple"))
178  				return hexToColor("#800080");
179  			else if(str.equalsIgnoreCase("Fuchsia"))
180  				return hexToColor("#FF00FF");
181  			else if(str.equalsIgnoreCase("Green"))
182  				return hexToColor("#008000");
183  			else if(str.equalsIgnoreCase("Lime"))
184  				return hexToColor("#00FF00");
185  			else if(str.equalsIgnoreCase("Olive"))
186  				return hexToColor("#808000");
187  			else if(str.equalsIgnoreCase("Yellow"))
188  				return hexToColor("#FFFF00");
189  			else if(str.equalsIgnoreCase("Navy"))
190  				return hexToColor("#000080");
191  			else if(str.equalsIgnoreCase("Blue"))
192  				return hexToColor("#0000FF");
193  			else if(str.equalsIgnoreCase("Teal"))
194  				return hexToColor("#008080");
195  			else if(str.equalsIgnoreCase("Aqua"))
196  				return hexToColor("#00FFFF");
197  			else
198  				return hexToColor("#" + str);
199  		}
200  		
201  		public static void main(String[] args) throws IOException {
Event do_not_call: "java.io.InputStreamReader(java.io.InputStream arg1)" implicitly uses the environment's default character set, which might lead to unexpected behavior. Consider using InputStreamReader(InputStream in, String charsetName).
202  			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
203  			for (;;) {
204  				String line = br.readLine();
205  				if (line == null) return;
206  				Color c = stringToColor(line);
207  				if (c == null) {
208  					System.out.println("INVALID");
209  				} else {
210  					System.out.println(c.toString());
211  				}
212  			}
213  		}
214  	}