xref: /titanic_41/usr/src/cmd/krb5/kadmin/gui/visualrt/sunsoft/jws/visual/rt/base/Util.java (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * ident	"%Z%%M%	%I%	%E% SMI"
24  *
25  * Copyright (c) 2001 by Sun Microsystems, Inc.
26  * All rights reserved.
27  */
28 
29 /*
30  *        Copyright (C) 1996  Active Software, Inc.
31  *                  All rights reserved.
32  *
33  * @(#) Util.java 1.43 - last change made 07/16/97
34  */
35 
36 package sunsoft.jws.visual.rt.base;
37 
38 import java.awt.*;
39 import java.util.*;
40 import java.io.*;
41 
42 import java.awt.image.RGBImageFilter;
43 import java.awt.image.FilteredImageSource;
44 import java.net.URL;
45 import java.net.MalformedURLException;
46 import java.applet.Applet;
47 
48 /**
49  * Utilities needed by run-time.
50  *
51  * @version 	1.32, 03/09/97
52  */
53 public class Util {
54 	// Relief constants
55 	public static final int RELIEF_FLAT   = 0;
56 	public static final int RELIEF_RAISED = 1;
57 	public static final int RELIEF_SUNKEN = 2;
58 	public static final int RELIEF_RIDGE  = 3;
59 	public static final int RELIEF_GROOVE = 4;
60 	public static final int WIN95_RAISED = 6;
61 	public static final int WIN95_SUNKEN = 7;
62 	public static final int WIN95_FIELD_BORDER = 8;
63 	public static final int WIN95_WINDOW_BORDER = 9;
64 	public static final int BLACK_BORDER = 10;
65 
66 	// Character constants
67 	public static final char BACKSLASH	= /* NOI18N */ '\\';
68 	public static final char COLON	= /* NOI18N */ ':';
69 	public static final char NEWLINE	= /* NOI18N */ '\n';
70 	public static final char RETURN	= /* NOI18N */ '\r';
71 	public static final char SLASH	= /* NOI18N */ '/';
72 	public static final char SPACE	= /* NOI18N */ ' ';
73 
74 
75 	// codebase the user specified in the project - used at design time
76 	private String codebaseStr = null;
77 
78 	// default class loader
79 	private CustomClassLoader classLoader;
80 
81 	// Darkness constants
82 	private static final double BFACTOR = 0.82;
83 	private static final double DFACTOR = 0.7;
84 
85 	// Buffer size for reading files
86 	private static final int BUFSIZE = 2048;
87 
Util()88 	public Util() {
89 		classLoader = new VBClassLoader();
90 	}
91 
92 	/**
93 	 * Returns a brighter version of this color.
94 	 *
95 	 * This version is adjusted to compensate for border cases:
96 	 * If the base is white, the brighter color sometimes gets lost
97 	 * against the background, so the border of the panel (or whatever)
98 	 * is not seen. (Sun Bug # 4035733)
99 	 * The solution is to check if the "brighter" color
100 	 * is too bright, and if
101 	 * so, set it to a light grey.
102 	 *
103 	 */
104 
brighter(Color c)105 	public Color brighter(Color c) {
106 		int r = c.getRed();
107 		int g = c.getGreen();
108 		int b = c.getBlue();
109 
110 		r = Math.min((int)(r * (1/BFACTOR)), 255);
111 		g = Math.min((int)(g * (1/BFACTOR)), 255);
112 		b = Math.min((int)(b * (1/BFACTOR)), 255);
113 
114 		if (r > 250 && g > 250 && b > 250) {
115 			// note: we use the JDK darker, which simply makes
116 			// the color darker,
117 			//       rather than this.darker, which will turn
118 			// values of 255 into
119 			//       128.
120 			return new Color(225, 225, 225);
121 		}
122 		/* JSTYLED */
123 		return new Color(r, g, b);
124 	}
125 
126 	/**
127 	 * Returns a darker version of this color.
128 	 */
darker(Color c)129 	public Color darker(Color c) {
130 		int r = c.getRed();
131 		int g = c.getGreen();
132 		int b = c.getBlue();
133 
134 		if (r == 255)
135 			r = 128;
136 		else
137 			r = Math.max((int)(r * DFACTOR), 0);
138 
139 		if (g == 255)
140 			g = 128;
141 		else
142 			g = Math.max((int)(g * DFACTOR), 0);
143 
144 		if (b == 255)
145 			b = 128;
146 		else
147 			b = Math.max((int)(b * DFACTOR), 0);
148 
149 		return new Color(r, g, b);
150 	}
151 
152 	/**
153 	 * Draw a 3D rectable with the given relief and border width.
154 	 */
draw3DRect(Graphics g, int x, int y, int w, int h, int relief, int bd)155 	public void draw3DRect(Graphics g, int x, int y, int w, int h,
156 			    int relief, int bd) {
157 		int bd2 = (bd+1)/2;
158 		for (int i = 0; i < bd; i++)
159 			draw3DRect(g, x+i, y+i, w-2*i, h-2*i, relief,
160 				(i < bd2));
161 	}
162 
163 	/**
164 	 * Draw a 3D rectable with the given relief and outer boolean.
165 	 */
draw3DRect(Graphics g, int x, int y, int w, int h, int relief, boolean isOuter)166 	private void draw3DRect(Graphics g, int x, int y, int w, int h,
167 				int relief, boolean isOuter) {
168 		Color color = g.getColor();
169 
170 		g.setColor(getEdgeColor(color, relief, true, isOuter));
171 		g.drawLine(x, y, x+w, y);
172 		g.drawLine(x, y, x, y+h);
173 
174 		g.setColor(getEdgeColor(color, relief, false, isOuter));
175 		g.drawLine(x, y+h, x+w, y+h);
176 		g.drawLine(x+w, y, x+w, y+h);
177 
178 		g.setColor(color);
179 	}
180 
181 
182 	/**
183 	 * Returns an adjusted color for the given
184 	 * edge and the given relief.
185 	 */
getEdgeColor(Color base, int relief, boolean isTopEdge, boolean isOuter)186 	private Color getEdgeColor(Color base, int relief,
187 				boolean isTopEdge, boolean isOuter) {
188 
189 		Color color = null;
190 
191 		switch (relief) {
192 		case RELIEF_RAISED:
193 			if (isTopEdge)
194 				color = brighter(base);
195 			else
196 				color = darker(base);
197 			break;
198 
199 		case RELIEF_SUNKEN:
200 			if (isTopEdge)
201 				color = darker(base);
202 			else
203 				color = brighter(base);
204 			break;
205 
206 		case RELIEF_RIDGE:
207 			if (isTopEdge) {
208 				if (isOuter)
209 					color = brighter(base);
210 				else
211 					color = darker(base);
212 			} else {
213 				if (isOuter)
214 					color = darker(base);
215 				else
216 					color = brighter(base);
217 			}
218 			break;
219 
220 		case RELIEF_GROOVE:
221 			if (isTopEdge) {
222 				if (isOuter)
223 					color = darker(base);
224 				else
225 					color = brighter(base);
226 			} else {
227 				if (isOuter)
228 					color = brighter(base);
229 				else
230 					color = darker(base);
231 			}
232 			break;
233 
234 		case WIN95_RAISED:
235 			if (isTopEdge) {
236 				if (isOuter)
237 					color = Color.white;
238 				else
239 					color = brighter(base);
240 			} else {
241 				if (isOuter)
242 					color = Color.black;
243 				else
244 					color = darker(base);
245 			}
246 			break;
247 
248 		case WIN95_SUNKEN:
249 			if (isTopEdge) {
250 				if (isOuter)
251 					color = Color.black;
252 				else
253 					color = darker(base);
254 			} else {
255 				if (isOuter)
256 					color = Color.white;
257 				else
258 					color =  brighter(base);
259 
260 			}
261 			break;
262 
263 		case WIN95_FIELD_BORDER:
264 			if (isTopEdge) {
265 				if (isOuter)
266 					color = darker(base);
267 				else
268 					color = Color.black;
269 			} else {
270 				if (isOuter)
271 					color = Color.white;
272 				else
273 					color = brighter(base);
274 				// was: base; // brighter(base);
275 			}
276 			break;
277 
278 		case WIN95_WINDOW_BORDER:
279 			if (isTopEdge) {
280 				if (isOuter)
281 					color =  brighter(base);
282 				else
283 					color = Color.white;
284 			} else {
285 				if (isOuter)
286 					color = Color.black;
287 				else
288 					color = darker(base);
289 			}
290 			break;
291 
292 		case BLACK_BORDER:
293 			color = Color.black;
294 			break;
295 
296 		case RELIEF_FLAT:
297 		default:
298 			color = base;
299 			break;
300 		}
301 
302 		return color;
303 	}
304 
305 	/**
306 	 * Get an image given a url.  If we are on Windows 95, then we
307 	 * need to use a filter to get around the transparency bugs.
308 	 */
getWorkaroundImage(URL url, Component comp)309 	public Image getWorkaroundImage(URL url, Component comp) {
310 		Image image = comp.getToolkit().getImage(url);
311 		return getWorkaroundImage(image, comp);
312 	}
313 
314 	/**
315 	 * Get an image given another.  If we are on Windows 95, then we
316 	 * need to use a filter to get around the transparency bugs.
317 	 * Otherwise, just return the image directly.
318 	 */
getWorkaroundImage(Image image, Component comp)319 	public Image getWorkaroundImage(Image image, Component comp) {
320 		if (image == null)
321 			return null;
322 
323 		if (Global.isWindows95() && Global.javaVersion() == 1.0) {
324 			RGBImageFilter filter = new TransFilter(comp);
325 			image = comp.createImage(
326 				new FilteredImageSource(image.getSource(),
327 							filter));
328 		}
329 
330 		return image;
331 	}
332 
333 	/**
334 	 * When the user specifies/changes the codebase attribute
335 	 * in the project,
336 	 * this method is called to update the value of "codebase" here.
337 	 * When  we calculate an URL relative to codebase(such as the
338 	 * ImageLabel "image"  attribute at design time, we use this
339 	 * codebase value.
340 	 */
setUserCodebase(String newCodebase)341 	public boolean setUserCodebase(String newCodebase) {
342 		codebaseStr = newCodebase;
343 		return true;
344 	}
345 
getClassLoader()346 	public CustomClassLoader getClassLoader() {
347 		return (classLoader);
348 	}
349 
setClassLoader(CustomClassLoader newLoader)350 	public void setClassLoader(CustomClassLoader newLoader) {
351 		classLoader = newLoader;
352 	}
353 
354 	/**
355 	 * Returns a URL based on a relative path to a file or directory.
356 	 * If we are running under a browser, then a URL is created based
357 	 * off of the code base.  Otherwise, a file URL will be created
358 	 * by searching the CLASSPATH for the file.
359 	 */
pathToURL(String path, Applet applet)360 	public URL pathToURL(String path, Applet applet) {
361 		// general info: determine delimiter and urlPrefix
362 		String delimiter, urlPrefix;
363 		if (Global.isWindows()) {
364 			delimiter = /* NOI18N */";";
365 			urlPrefix = /* NOI18N */"file:/";
366 		} else {
367 			delimiter = /* NOI18N */":";
368 			urlPrefix = /* NOI18N */"file:";
369 		}
370 
371 		// First see if the path is a full URL path
372 		// Note that the user must specify "file:" for files
373 		try {
374 			URL url = new URL(path);
375 			// System.out.println(
376 			// "           detected full URL - URL=" + url);
377 			return url;
378 		}
379 		catch (MalformedURLException ex) {
380 		}
381 
382 		// Are we running as an applet?  If running as the Visual Java
383 		// applet in JWS can't use applet.getCodeBase because it is the
384 		// codebase of Visual Java, not the users applet, so fall
385 		// through
386 		// and use the CLASSPATH
387 		// Note: There's probably a better way to check if we're the
388 		// Visual Java applet than checking for classname starting
389 		// with "sun.jws"
390 		if ((applet != null) &&
391 		    !(applet.getClass().getName().startsWith(/* NOI18N */
392 			    "sun.jws"))) {
393 			String s = applet.getCodeBase().toExternalForm();
394 			if (s.charAt(s.length()-1) != SLASH)
395 				path = /* NOI18N */"/" + path;
396 
397 			URL url;
398 			try {
399 				url = new URL(applet.getCodeBase(), path);
400 			}
401 			catch (MalformedURLException ex) {
402 				url = null;
403 			}
404 			// System.out.println("           based on codebase="
405 			// + s + " URL=" + url);
406 			return url;
407 		}
408 
409 // Search the CLASSPATH for the file
410 		String classpath;
411 		try {
412 			classpath = System.getProperty(
413 					/* NOI18N */"java.class.path");
414 		}
415 		catch (SecurityException ex) {
416 			throw new Error(Global.fmtMsg(
417 			"sunsoft.jws.visual.rt.base.Util.NeedAppletparam",
418 				Global.newline()));
419 		}
420 
421 		classpath = DesignerAccess.getCWD() + delimiter + classpath;
422 
423 		StringTokenizer st = new StringTokenizer(classpath, delimiter);
424 		boolean keepGoing = true;
425 		while (st.hasMoreTokens() && keepGoing) {
426 			String p = st.nextToken();
427 
428 			if (p == /* NOI18N */"")
429 				p = /* NOI18N */".";
430 
431 			p = makeAbsolute(p);
432 
433 			char c = p.charAt(p.length()-1);
434 			if (c != SLASH && c != BACKSLASH)
435 				p = p + separator;
436 
437 			p = p + path;
438 
439 			if (Global.isWindows()) {
440 // Java allows the use of SLASH in the classpath,
441 // so we need
442 // convert SLASH to BACKSLASH.
443 				char buf[] = p.toCharArray();
444 				for (int i = 0; i < buf.length; i++) {
445 					if (buf[i] == SLASH)
446 						buf[i] = BACKSLASH;
447 				}
448 				p = new String(buf);
449 			}
450 
451 			File f = new File(p);
452 			if (f.exists()) {
453 				try {
454 					URL url = new URL(urlPrefix + p);
455 // System.out.println("           based on
456 // classpath; found in " + p
457 //			+ "; URL=" + url +
458 // " classpath=" + classpath);
459 					return url;
460 				}
461 				catch (MalformedURLException ex) {
462 			// System.out.println("           based on
463 			// classpath=" + classpath
464 			//						+
465 			// " URL=null");
466 					keepGoing = false;
467 				}
468 			}
469 		}
470 
471 // Search relative to project's codebase attrib
472 // (meant for design time only)
473 		if (codebaseStr != null) {
474 			URL url;
475 			String tmpPath;
476 			if (!codebaseStr.endsWith(/* NOI18N */"/") &&
477 			    !codebaseStr.endsWith(File.separator)) {
478 				tmpPath = codebaseStr + /* NOI18N */"/" + path;
479 			} else {
480 				tmpPath = codebaseStr + path;
481 			}
482 			File f = new File(tmpPath);
483 			if (f.exists()) {
484 				tmpPath = urlPrefix + tmpPath;
485 			}
486 			try {
487 				url = new URL(tmpPath);
488 				// System.out.println("           based on proj
489 				// codebase=" + codebase + " URL=" + url);
490 				return url;
491 			}
492 			catch (MalformedURLException e) {
493 				url = null;
494 			}
495 		}
496 
497 // System.out.println("           all attempts
498 // failed - returning null");
499 		return null;
500 	}
501 
502 	private static String separator;
503 	private static String cwd;
504 
makeAbsolute(String path)505 	private String makeAbsolute(String path) {
506 		if (separator == null) {
507 			separator = System.getProperty(/* NOI18N */
508 				"file.separator");
509 		}
510 
511 		if (cwd == null) {
512 			cwd = System.getProperty(/* NOI18N */"user.dir");
513 			if (cwd.charAt(cwd.length()-1) != separator.charAt(0))
514 				cwd = cwd + separator;
515 		}
516 
517 		if (Global.isWindows()) {
518 			if (path.length() < 3 ||
519 			    (path.charAt(1) != COLON ||
520 			    (path.charAt(2) != SLASH && path.charAt(2)
521 			    		!= BACKSLASH))) {
522 				path = cwd + path;
523 			}
524 		} else {
525 			if (path.charAt(0) != SLASH)
526 				path = cwd + path;
527 		}
528 
529 		return path;
530 	}
531 
532 /**
533  * Compares two objects and returns if they are equal.
534  * Will work with
535  * null objects
536  */
537 
isEqual(Object o1, Object o2)538 	public boolean isEqual(Object o1, Object o2) {
539 		if (o1 == null) {
540 			return (o2 == null);
541 		} else {
542 			return (o1.equals(o2));
543 		}
544 	}
545 
546 /**
547  * Quicksort for strings.  Could not get James Gosling's
548  * example working
549  * properly, or the "fixed" example, so wrote my own using
550  * algorithms
551  * book.
552  */
553 
qsort(String[] list)554 	public void qsort(String[] list) {
555 		quicksort(list, 0, list.length-1);
556 	}
557 
quicksort(String[] list, int p, int r)558 	private void quicksort(String[] list, int p, int r) {
559 		if (p < r) {
560 			int q = partition(list, p, r);
561 			if (q == r) {
562 				q--;
563 			}
564 			quicksort(list, p, q);
565 			quicksort(list, q+1, r);
566 		}
567 	}
568 
partition(String[] list, int p, int r)569 	private int partition(String[] list, int p, int r) {
570 		String pivot = list[p];
571 		int lo = p;
572 		int hi = r;
573 
574 		while (true) {
575 			while (list[hi].compareTo(pivot) >= 0 &&
576 			    lo < hi) {
577 				hi--;
578 			}
579 			while (list[lo].compareTo(pivot) < 0 &&
580 			    lo < hi) {
581 				lo++;
582 			}
583 			if (lo < hi) {
584 				String T = list[lo];
585 				list[lo] = list[hi];
586 				list[hi] = T;
587 			} else return hi;
588 		}
589 	}
590 
591 /**
592  * Quicksort for objects.  The is a parameter for a
593  * QSortCompare object that is used to do the sorting.
594  */
595 
qsort(Object[] list, QSortCompare comp)596 	public void qsort(Object[] list, QSortCompare comp) {
597 		if (list != null)
598 			quicksort(list, 0, list.length-1, comp);
599 	}
600 
quicksort(Object[] list, int p, int r, QSortCompare comp)601 	private void quicksort(Object[] list, int p, int r,
602 			    QSortCompare comp) {
603 		if (p < r) {
604 			int q = partition(list, p, r, comp);
605 			if (q == r) {
606 				q--;
607 			}
608 			quicksort(list, p, q, comp);
609 			quicksort(list, q+1, r, comp);
610 		}
611 	}
612 
partition(Object[] list, int p, int r, QSortCompare comp)613 	private int partition(Object[] list, int p, int r,
614 			    QSortCompare comp) {
615 		Object pivot = list[p];
616 		int lo = p;
617 		int hi = r;
618 
619 		while (true) {
620 			while (comp.qsortCompare(list[hi], pivot) >= 0 &&
621 			    lo < hi) {
622 				hi--;
623 			}
624 			while (comp.qsortCompare(list[lo], pivot) < 0 &&
625 			    lo < hi) {
626 				lo++;
627 			}
628 			if (lo < hi) {
629 				Object T = list[lo];
630 				list[lo] = list[hi];
631 				list[hi] = T;
632 			} else return hi;
633 		}
634 	}
635 
636 /**
637  * A workaround routine for the Windows95 pack bug in 1.0.2
638  *
639  * @param c The component to pack
640  */
pack(Window c)641 	static public void pack(Window c) {
642 		c.pack();
643 		if (Global.isWindows95() || Global.isWindowsNT()) {
644 			Thread.yield();
645 			c.pack();
646 		}
647 	}
648 }
649 
650 
651 /**
652 * A Work-around filter.
653 *
654 * Transparent gifs don't display properly on Windows 95.
655 * The work-around
656 * is to replace transparent pixels with the background color of the
657 * component they're being displayed in before drawing them.
658 */
659 class TransFilter extends RGBImageFilter {
660 	private Color bg;
661 	private Component comp;
662 
TransFilter(Component comp)663 	TransFilter(Component comp) {
664 		if (comp == null)
665 			throw new Error(Global.fmtMsg(
666 				"sunsoft.jws.visual.rt.base.Util.NullComp",
667 						    "TransWorkAroundFilter"));
668 
669 		this.comp = comp;
670 		canFilterIndexColorModel = false;
671 	}
672 
filterRGB(int x, int y, int rgb)673 	public int filterRGB(int x, int y, int rgb) {
674 		if (bg == null)
675 			bg = comp.getBackground();
676 
677 		if ((rgb & 0xff000000) == 0)
678 			return (bg.getRGB());
679 		else
680 			return (rgb);
681 	}
682 
683 }
684