XSettings.java :  » 6.0-JDK-Platform » solaris » sun » awt » Java Open Source

Java Open Source » 6.0 JDK Platform » solaris 
solaris » sun » awt » XSettings.java
/*
 * Copyright 2003-2004 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.awt;

import java.awt.Color;

import java.io.UnsupportedEncodingException;

import java.util.HashMap;
import java.util.Map;


/**
 * Per-screen XSETTINGS.
 */
public class XSettings {

    /**
     */
    private long serial = -1;


    /**
     * Update these settings with <code>data</code> obtained from
     * XSETTINGS manager.
     *
     * @param data settings data obtained from
     *     <code>_XSETTINGS_SETTINGS</code> window property of the
     *     settings manager.
     * @return a <code>Map</code> of changed settings.
     */
    public Map update(byte[] data) {
  return (new Update(data)).update();
    }


    /**
     * TBS ...
     */
    class Update {

  /* byte order mark */
  private static final int LITTLE_ENDIAN = 0;
  private static final int BIG_ENDIAN    = 1;

  /* setting type */
  private static final int TYPE_INTEGER = 0;
  private static final int TYPE_STRING  = 1;
  private static final int TYPE_COLOR   = 2;

  private byte[] data;
  private int dlen;
  private int idx;
  private boolean isLittle;
  private long serial = -1;
  private int nsettings = 0;
  private boolean isValid;

  private HashMap updatedSettings;


  /**
   * Construct an Update object for the data read from
   * <code>_XSETTINGS_SETTINGS</code> property of the XSETTINGS
   * selection owner.
   *
   * @param data <code>_XSETTINGS_SETTINGS</code> contents.
   */
  Update(byte[] data) {
      this.data = data;

      dlen = data.length;
      if (dlen < 12) {
    // XXX: debug trace?
    return;
      }

      // first byte gives endianness of the data
      // next 3 bytes are unused (pad to 32 bit)
      idx = 0;
      isLittle = (getCARD8() == LITTLE_ENDIAN);

      idx = 4;
      serial = getCARD32();

      // N_SETTINGS is actually CARD32 (i.e. unsigned), but
      // since java doesn't have an unsigned int type, and
      // N_SETTINGS cannot realistically exceed 2^31 (so we
      // gonna use int anyway), just read it as INT32.
      idx = 8;
      nsettings = getINT32();

      updatedSettings = new HashMap();

      isValid = true;
  }


  private void needBytes(int n)
      throws IndexOutOfBoundsException
  {
      if (idx + n <= dlen) {
    return;
      }

      throw new IndexOutOfBoundsException("at " + idx
            + " need " + n
            + " length " + dlen);
  }


  private int getCARD8()
      throws IndexOutOfBoundsException
  {
      needBytes(1);

      int val = data[idx] & 0xff;

      ++idx;
      return val;
  }


  private int getCARD16()
      throws IndexOutOfBoundsException
  {
      needBytes(2);

      int val;
      if (isLittle) {
    val = ((data[idx + 0] & 0xff)      )
        | ((data[idx + 1] & 0xff) <<  8);
      } else {
    val = ((data[idx + 0] & 0xff) <<  8)
        | ((data[idx + 1] & 0xff)      );
      }

      idx += 2;
      return val;
  }


  private int getINT32()
      throws IndexOutOfBoundsException
  {
      needBytes(4);

      int val;
      if (isLittle) {
    val = ((data[idx + 0] & 0xff)      )
        | ((data[idx + 1] & 0xff) <<  8)
        | ((data[idx + 2] & 0xff) << 16)
        | ((data[idx + 3] & 0xff) << 24);
      } else {
    val = ((data[idx + 0] & 0xff) << 24)
        | ((data[idx + 1] & 0xff) << 16)
        | ((data[idx + 2] & 0xff) <<  8)
        | ((data[idx + 3] & 0xff) <<  0);
      }

      idx += 4;
      return val;
  }


  private long getCARD32()
      throws IndexOutOfBoundsException
  {
      return getINT32() & 0x00000000ffffffffL;
  }


  private String getString(int len)
      throws IndexOutOfBoundsException
  {
      needBytes(len);

      String str = null;
      try {
    str = new String(data, idx, len, "UTF-8");
      } catch (UnsupportedEncodingException e) {
    // XXX: cannot happen, "UTF-8" is always supported
      }

      idx = (idx + len + 3) & ~0x3;
      return str;
  }


  /**
   * Update settings.
   */
  public Map update() {
      if (!isValid) {
    return null;
      }

      synchronized (XSettings.this) {
    long currentSerial = XSettings.this.serial;

    if (this.serial <= currentSerial) {
        return null;
    }

    for (int i = 0; i < nsettings && idx < dlen; ++i) {
        updateOne(currentSerial);
    }

    XSettings.this.serial = this.serial;
      }

      return updatedSettings;
  }


  /**
   * Parses a particular x setting.
   *
   * @exception IndexOutOfBoundsException if there isn't enough
   *     data for a setting.
   */
  private void updateOne(long currentSerial)
      throws IndexOutOfBoundsException,
       IllegalArgumentException
  {
      int type = getCARD8();
      ++idx;    // pad to next CARD16

      // save position of the property name, skip to serial
      int nameLen = getCARD16();
      int nameIdx = idx;

      // check if we should bother
      idx = (idx + nameLen + 3) & ~0x3; // pad to 32 bit
      long lastChanged = getCARD32();

      // Avoid constructing garbage for properties that has not
      // changed, skip the data for this property.
      if (lastChanged <= currentSerial) {  // skip
    if (type == TYPE_INTEGER) {
        idx += 4;
    } else if (type == TYPE_STRING) {
        int len = getINT32();
        idx = (idx + len + 3) & ~0x3;
    } else if (type == TYPE_COLOR) {
        idx += 8;  // 4 CARD16
    } else {
        throw new IllegalArgumentException("Unknown type: "
                   + type);
    }

    return;
      }

      idx = nameIdx;
      String name = getString(nameLen);
      idx += 4;    // skip serial, parsed above

      Object value = null;
      if (type == TYPE_INTEGER) {
    value = Integer.valueOf(getINT32());
      }
      else if (type == TYPE_STRING) {
    value = getString(getINT32());
      }
      else if (type == TYPE_COLOR) {
    int r = getCARD16();
    int g = getCARD16();
    int b = getCARD16();
    int a = getCARD16();

    value = new Color(r / 65535.0f,
          g / 65535.0f,
          b / 65535.0f,
          a / 65535.0f);
      }
      else {
    throw new IllegalArgumentException("Unknown type: " + type);
      }

      if (name == null) {
    // dtrace???
    return;
      }

      updatedSettings.put(name, value);
  }

    } // class XSettings.Update
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.