Index: src/org/apache/lucene/luke/core/HighFreqTerms.java
===================================================================
--- src/org/apache/lucene/luke/core/HighFreqTerms.java	(revision 1655665)
+++ src/org/apache/lucene/luke/core/HighFreqTerms.java	(working copy)
@@ -100,10 +100,10 @@
   }
   
   /**
-   * 
-   * @param reader
-   * @param numTerms
-   * @param field
+   * // TODO move this method to org.apache.lucene.misc.HighFreqTerms
+   * @param reader IndexReader
+   * @param numTerms the max number of terms
+   * @param fieldNames tye array of field names
    * @return TermStats[] ordered by terms with highest docFreq first.
    * @throws Exception
    */
Index: src/org/apache/lucene/luke/core/IndexInfo.java
===================================================================
--- src/org/apache/lucene/luke/core/IndexInfo.java	(revision 1655665)
+++ src/org/apache/lucene/luke/core/IndexInfo.java	(working copy)
@@ -177,6 +177,7 @@
       }
     }
   }
+
   
   /**
    * @return the reader
Index: src/org/apache/lucene/luke/core/TableComparator.java
===================================================================
--- src/org/apache/lucene/luke/core/TableComparator.java	(revision 1655665)
+++ src/org/apache/lucene/luke/core/TableComparator.java	(working copy)
@@ -1,63 +0,0 @@
-package org.apache.lucene.luke.core;
-
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except in
- * compliance with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import java.util.Comparator;
-
-import org.apache.pivot.collections.Dictionary;
-import org.apache.pivot.collections.Map;
-import org.apache.pivot.wtk.SortDirection;
-import org.apache.pivot.wtk.TableView;
-
-public class TableComparator implements Comparator<Map<String,String>> {
-  private TableView tableView;
-  
-  public TableComparator(TableView fieldsTable) {
-    if (fieldsTable == null) {
-      throw new IllegalArgumentException();
-    }
-    
-    this.tableView = fieldsTable;
-  }
-  
-  @Override
-  public int compare(Map<String,String> o1, Map<String,String> o2) {
-    Dictionary.Pair<String, SortDirection> sort = tableView.getSort().get(0);
-
-    int result;
-    if (sort.key.equals("name")) {
-      // sort by name
-      result = o1.get(sort.key).compareTo(o2.get(sort.key));
-    } else if (sort.key.equals("termCount")) {
-      // sort by termCount
-      Integer c1 = Integer.parseInt(o1.get(sort.key));
-      Integer c2 = Integer.parseInt(o2.get(sort.key));
-      result = c1.compareTo(c2);
-    } else {
-      // other (ignored)
-      result = 0;
-    }
-    //int result = o1.get("name").compareTo(o2.get("name"));
-    //SortDirection sortDirection = tableView.getSort().get("name");
-    SortDirection sortDirection = sort.value;
-    result *= (sortDirection == SortDirection.DESCENDING ? 1 : -1);
-
-    return result * -1;
-  }
-  
-}
\ No newline at end of file
Index: src/org/apache/lucene/luke/core/TermStats.java
===================================================================
--- src/org/apache/lucene/luke/core/TermStats.java	(revision 1655665)
+++ src/org/apache/lucene/luke/core/TermStats.java	(working copy)
@@ -26,13 +26,15 @@
   public long totalTermFreq;
   
   TermStats(String field, BytesRef termtext, int df) {
-    this.termtext = (BytesRef)termtext.clone();
+    //this.termtext = (BytesRef)termtext.clone();
+    this.termtext = BytesRef.deepCopyOf(termtext);
     this.field = field;
     this.docFreq = df;
   }
   
   TermStats(String field, BytesRef termtext, int df, long tf) {
-    this.termtext = (BytesRef)termtext.clone();
+    //this.termtext = (BytesRef)termtext.clone();
+    this.termtext = BytesRef.deepCopyOf(termtext);
     this.field = field;
     this.docFreq = df;
     this.totalTermFreq = tf;
Index: src/org/apache/lucene/luke/core/Util.java
===================================================================
--- src/org/apache/lucene/luke/core/Util.java	(revision 1655665)
+++ src/org/apache/lucene/luke/core/Util.java	(working copy)
@@ -19,11 +19,18 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 
 import org.apache.lucene.document.DateTools.Resolution;
+import org.apache.lucene.index.FieldInfo;
 import org.apache.lucene.index.FieldInfo.IndexOptions;
 import org.apache.lucene.index.IndexableField;
+import org.apache.lucene.luke.core.decoders.*;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.FSDirectory;
 import org.apache.lucene.store.MMapDirectory;
@@ -161,18 +168,20 @@
     return sb.toString();
   }
   
-  public static String fieldFlags(IndexableField f) {
-    if (f == null) {
-      return "-----------";
-    }
+  public static String fieldFlags(IndexableField f, FieldInfo info) {
+    //if (f == null) {
+    //  return "-----------";
+    //}
     StringBuffer flags = new StringBuffer();
-    if (f != null && f.fieldType().indexed()) flags.append("I");
+    //if (f != null && f.fieldType().indexed()) flags.append("I");
+    if (info != null && info.isIndexed()) flags.append("I");
     else flags.append("-");
     if (f != null && f.fieldType().tokenized()) flags.append("T");
     else flags.append("-");
     if (f != null && f.fieldType().stored()) flags.append("S");
     else flags.append("-");
-    if (f != null && f.fieldType().storeTermVectors()) flags.append("V");
+    //if (f != null && f.fieldType().storeTermVectors()) flags.append("V");
+    if (info != null && info.hasVectors()) flags.append("V");
     else flags.append("-");
     if (f != null && f.fieldType().storeTermVectorOffsets()) flags.append("o");
     else flags.append("-");
@@ -180,9 +189,11 @@
     else flags.append("-");
     if (f != null && f.fieldType().storeTermVectorPayloads()) flags.append("a");
     else flags.append("-");
-    IndexOptions opts = f.fieldType().indexOptions();
+    //IndexOptions opts = f.fieldType().indexOptions();
+    IndexOptions opts = info.getIndexOptions();
     // TODO: how to handle these codes
-    if (f.fieldType().indexed() && opts != null) {
+    //if (f.fieldType().indexed() && opts != null) {
+    if (info.isIndexed() && opts != null) {
       switch (opts) {
       case DOCS_ONLY:
         flags.append("1");
@@ -199,13 +210,32 @@
     } else {
       flags.append("-");
     }
-    if (f != null && f.fieldType().omitNorms()) flags.append("O");
+    //if (f != null && f.fieldType().omitNorms()) flags.append("O");
+    if (info != null && !info.hasNorms()) flags.append("O");
     else flags.append("-");
+    // TODO lazy
+    flags.append("-");
+    if (f != null && f.binaryValue() != null) flags.append("B");
+    else flags.append("-");
 
 
     return flags.toString();
   }
-  
+
+  public static String docValuesType(FieldInfo info) {
+    if (info == null || !info.hasDocValues() || info.getDocValuesType() == null) {
+      return "---";
+    }
+    return info.getDocValuesType().name();
+  }
+
+  public static String normType(FieldInfo info) {
+    if (info == null || !info.hasNorms() || info.getNormType() == null) {
+      return "---";
+    }
+    return info.getNormType().name();
+  }
+
   public static Resolution getResolution(String key) {
     if (key == null || key.trim().length() == 0) {
       return Resolution.MILLISECOND;
@@ -270,4 +300,39 @@
       return String.valueOf(len / 1048576);
     }
   }
+
+  public static List<Decoder> loadDecoders() {
+    List decoders = new ArrayList();
+    // default decoders
+    decoders.add(new BinaryDecoder());
+    decoders.add(new DateDecoder());
+    decoders.add(new NumDoubleDecoder());
+    decoders.add(new NumFloatDecoder());
+    decoders.add(new NumIntDecoder());
+    decoders.add(new NumLongDecoder());
+    decoders.add(new StringDecoder());
+
+    // load external decoders
+    try {
+      String extLoaders = System.getProperty("luke.ext.decoder.loader");
+      if (extLoaders != null) {
+        String[] classes = extLoaders.split(",");
+        for (String className : classes) {
+          Class clazz = Class.forName(className);
+          Class[] interfaces = clazz.getInterfaces();
+          if (Arrays.asList(interfaces).indexOf(DecoderLoader.class) < 0) {
+            throw new Exception(className + " is not a DecoderLoader.");
+          }
+          DecoderLoader loader = (DecoderLoader)clazz.newInstance();
+          List<Decoder> extDecoders = loader.loadDecoders();
+          for (Decoder dec : extDecoders) {
+            decoders.add(dec);
+          }
+        }
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+    return decoders;
+  }
 }
Index: src/org/apache/lucene/luke/core/decoders/BinaryDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/BinaryDecoder.java	(revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/BinaryDecoder.java	(working copy)
@@ -19,23 +19,18 @@
 
 import org.apache.lucene.document.Field;
 import org.apache.lucene.luke.core.Util;
+import org.apache.lucene.util.BytesRef;
 
 public class BinaryDecoder implements Decoder {
 
   @Override
-  public String decodeTerm(String fieldName, Object value) throws Exception {
-    byte[] data;
-    if (value instanceof byte[]) {
-      data = (byte[])value;
-    } else {
-      data = value.toString().getBytes();
-    }
-    return Util.bytesToHex(data, 0, data.length, false);
+  public String decodeTerm(String fieldName, BytesRef value) throws Exception {
+    return Util.bytesToHex(value.bytes, 0, value.length, false);
   }
 
   @Override
   public String decodeStored(String fieldName, Field value) throws Exception {
-    return decodeTerm(fieldName, value);
+    return decodeTerm(fieldName, new BytesRef(value.stringValue()));
   }
   
   public String toString() {
Index: src/org/apache/lucene/luke/core/decoders/DateDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/DateDecoder.java	(revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/DateDecoder.java	(working copy)
@@ -19,17 +19,18 @@
 
 import org.apache.lucene.document.DateTools;
 import org.apache.lucene.document.Field;
+import org.apache.lucene.util.BytesRef;
 
 public class DateDecoder implements Decoder {
 
   @Override
-  public String decodeTerm(String fieldName, Object value) throws Exception {
+  public String decodeTerm(String fieldName, BytesRef value) throws Exception {
     return DateTools.stringToDate(value.toString()).toString();
   }
   
   @Override
   public String decodeStored(String fieldName, Field value) throws Exception {
-    return decodeTerm(fieldName, value.stringValue());
+    return decodeTerm(fieldName, new BytesRef(value.stringValue()));
   }
   
   public String toString() {
Index: src/org/apache/lucene/luke/core/decoders/Decoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/Decoder.java	(revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/Decoder.java	(working copy)
@@ -18,9 +18,10 @@
  */
 
 import org.apache.lucene.document.Field;
+import org.apache.lucene.util.BytesRef;
 
 public interface Decoder {
   
-  public String decodeTerm(String fieldName, Object value) throws Exception;
+  public String decodeTerm(String fieldName, BytesRef value) throws Exception;
   public String decodeStored(String fieldName, Field value) throws Exception;
 }
Index: src/org/apache/lucene/luke/core/decoders/DecoderLoader.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/DecoderLoader.java	(revision 0)
+++ src/org/apache/lucene/luke/core/decoders/DecoderLoader.java	(working copy)
@@ -0,0 +1,24 @@
+package org.apache.lucene.luke.core.decoders;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.List;
+
+public interface DecoderLoader {
+  public List<Decoder> loadDecoders();
+}
Index: src/org/apache/lucene/luke/core/decoders/NumDoubleDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/NumDoubleDecoder.java	(revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/NumDoubleDecoder.java	(working copy)
@@ -1,5 +1,22 @@
 package org.apache.lucene.luke.core.decoders;
 
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 import org.apache.lucene.document.Field;
 import org.apache.lucene.util.BytesRef;
 import org.apache.lucene.util.NumericUtils;
@@ -7,9 +24,8 @@
 public class NumDoubleDecoder implements Decoder {
 
   @Override
-  public String decodeTerm(String fieldName, Object value) {
-    BytesRef ref = new BytesRef(value.toString());
-    return Double.toString(NumericUtils.sortableLongToDouble(NumericUtils.prefixCodedToLong(ref)));
+  public String decodeTerm(String fieldName, BytesRef value) {
+    return Double.toString(NumericUtils.sortableLongToDouble(NumericUtils.prefixCodedToLong(value)));
   }
 
   @Override
@@ -18,7 +34,7 @@
   }
 
   public String toString() {
-    return "numeric-double";
+    return "numeric double";
   }
 
 }
Index: src/org/apache/lucene/luke/core/decoders/NumFloatDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/NumFloatDecoder.java	(revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/NumFloatDecoder.java	(working copy)
@@ -6,9 +6,9 @@
 
 public class NumFloatDecoder implements Decoder {
   @Override
-  public String decodeTerm(String fieldName, Object value) {
-    BytesRef ref = new BytesRef(value.toString());
-    return Float.toString(NumericUtils.sortableIntToFloat(NumericUtils.prefixCodedToInt(ref)));
+  public String decodeTerm(String fieldName, BytesRef value) {
+    //BytesRef ref = new BytesRef(value.toString());
+    return Float.toString(NumericUtils.sortableIntToFloat(NumericUtils.prefixCodedToInt(value)));
   }
 
   @Override
@@ -17,7 +17,7 @@
   }
 
   public String toString() {
-    return "numeric-float";
+    return "numeric float";
   }
 
 }
Index: src/org/apache/lucene/luke/core/decoders/NumIntDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/NumIntDecoder.java	(revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/NumIntDecoder.java	(working copy)
@@ -24,9 +24,8 @@
 public class NumIntDecoder implements Decoder {
 
   @Override
-  public String decodeTerm(String fieldName, Object value) {
-    BytesRef ref = new BytesRef(value.toString());
-    return Integer.toString(NumericUtils.prefixCodedToInt(ref));
+  public String decodeTerm(String fieldName, BytesRef value) {
+    return Integer.toString(NumericUtils.prefixCodedToInt(value));
   }
   
   @Override
@@ -35,7 +34,7 @@
   }
   
   public String toString() {
-    return "numeric-int";
+    return "numeric int";
   }
 
 }
Index: src/org/apache/lucene/luke/core/decoders/NumLongDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/NumLongDecoder.java	(revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/NumLongDecoder.java	(working copy)
@@ -24,9 +24,8 @@
 public class NumLongDecoder implements Decoder {
 
   @Override
-  public String decodeTerm(String fieldName, Object value) {
-    BytesRef ref = new BytesRef(value.toString());
-    return Long.toString(NumericUtils.prefixCodedToLong(ref));
+  public String decodeTerm(String fieldName, BytesRef value) {
+    return Long.toString(NumericUtils.prefixCodedToLong(value));
   }
   
   @Override
@@ -35,7 +34,7 @@
   }
   
   public String toString() {
-    return "numeric-long";
+    return "numeric long";
   }
 
 }
Index: src/org/apache/lucene/luke/core/decoders/SolrDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/SolrDecoder.java	(revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/SolrDecoder.java	(working copy)
@@ -24,8 +24,14 @@
 
 import org.apache.lucene.document.Field;
 import org.apache.lucene.luke.core.ClassFinder;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.CharsRef;
 import org.apache.solr.schema.FieldType;
 
+/**
+ * NOT Used.
+ * The logic here has moved to org.apache.lucene.ext.SolrDecoderLoader.
+ */
 public class SolrDecoder implements Decoder {
   private static final String solr_prefix = "org.apache.solr.schema.";
   
@@ -86,8 +92,9 @@
     name = type;
   }
   
-  public String decodeTerm(String fieldName, Object value) throws Exception {
-    return fieldType.indexedToReadable(value.toString());
+  public String decodeTerm(String fieldName, BytesRef value) throws Exception {
+    CharsRef chars = fieldType.indexedToReadable(value, new CharsRef());
+    return chars.toString();
   }
   
   public String decodeStored(String fieldName, Field value)
@@ -100,3 +107,4 @@
   }
   
 }
+
Index: src/org/apache/lucene/luke/core/decoders/StringDecoder.java
===================================================================
--- src/org/apache/lucene/luke/core/decoders/StringDecoder.java	(revision 1655665)
+++ src/org/apache/lucene/luke/core/decoders/StringDecoder.java	(working copy)
@@ -18,17 +18,18 @@
  */
 
 import org.apache.lucene.document.Field;
+import org.apache.lucene.util.BytesRef;
 
 public class StringDecoder implements Decoder {
 
   @Override
-  public String decodeTerm(String fieldName, Object value) {
-    return value != null ? value.toString() : "(null)";
+  public String decodeTerm(String fieldName, BytesRef value) {
+    return value != null ? value.utf8ToString() : "(null)";
   }
   
   @Override
   public String decodeStored(String fieldName, Field value) {
-    return decodeTerm(fieldName, value.stringValue());
+    return value.stringValue();
   }
 
   public String toString() {
Index: src/org/apache/lucene/luke/ext/SolrDecoderLoader.java
===================================================================
--- src/org/apache/lucene/luke/ext/SolrDecoderLoader.java	(revision 0)
+++ src/org/apache/lucene/luke/ext/SolrDecoderLoader.java	(working copy)
@@ -0,0 +1,81 @@
+package org.apache.lucene.luke.ext;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.document.Field;
+import org.apache.lucene.luke.core.ClassFinder;
+import org.apache.lucene.luke.core.decoders.Decoder;
+import org.apache.lucene.luke.core.decoders.DecoderLoader;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.CharsRef;
+import org.apache.solr.schema.FieldType;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SolrDecoderLoader implements DecoderLoader {
+  private static final String solr_prefix = "org.apache.solr.schema.";
+
+  @Override
+  public List<Decoder> loadDecoders() {
+    List<Decoder> decoders = new ArrayList<Decoder>();
+    try {
+      Class[] classes = ClassFinder.getInstantiableSubclasses(FieldType.class);
+      if (classes == null || classes.length == 0) {
+        throw new ClassNotFoundException("Missing Solr types???");
+      }
+      for (Class cls : classes) {
+        FieldType ft = (FieldType) cls.newInstance();
+        if (cls.getName().startsWith(solr_prefix)) {
+          String name = "solr." + cls.getName().substring(solr_prefix.length());
+          decoders.add(new SolrDecoder(name, ft));
+        }
+      }
+    } catch (Exception e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+    return decoders;
+  }
+}
+
+class SolrDecoder implements Decoder {
+  private String name;
+  private FieldType fieldType;
+
+  public SolrDecoder(String name, FieldType fieldType) {
+    this.name = name;
+    this.fieldType = fieldType;
+  }
+
+  public String decodeTerm(String fieldName, BytesRef value) throws Exception {
+    CharsRef chars = fieldType.indexedToReadable(value, new CharsRef());
+    return chars.toString();
+  }
+
+  public String decodeStored(String fieldName, Field value)
+    throws Exception {
+    return fieldType.storedToReadable(value);
+  }
+
+  public String toString() {
+    return name;
+  }
+
+}
+
Index: src/org/apache/lucene/luke/ui/DocumentsTab.bxml
===================================================================
--- src/org/apache/lucene/luke/ui/DocumentsTab.bxml	(revision 1655665)
+++ src/org/apache/lucene/luke/ui/DocumentsTab.bxml	(working copy)
@@ -1,169 +1,250 @@
 <?xml version="1.0" encoding="UTF-8"?>
 
 <luke:DocumentsTab bxml:id="DocumentsTab"
-	styles="{verticalSpacing:2,horizontalSpacing:2,padding:4,backgroundColor:11}"
 	xmlns:bxml="http://pivot.apache.org/bxml" xmlns:content="org.apache.pivot.wtk.content"
-	xmlns="org.apache.pivot.wtk" xmlns:luke="org.apache.lucene.luke.ui">
+	xmlns="org.apache.pivot.wtk" xmlns:luke="org.apache.lucene.luke.ui"
+	orientation="vertical" splitRatio="0.30">
+	<top>
+		<SplitPane orientation="horizontal" splitRatio="0.20" styles="{useShadow:true}">
+			<left>
+				<Border styles="{padding:1}">
+				<content>
+				<TablePane styles="{verticalSpacing:1,horizontalSpacing:1,padding:5,backgroundColor:11}">
+					<columns>
+						<TablePane.Column width="1*" />
+					</columns>
+					<rows>
+						<TablePane.Row>
+							<BoxPane orientation="vertical">
+								<Label text="%documentsTab_browseByDocNum" styles="{padding:2,font:{bold:true}}"/>
+								<Label text="Doc. #" styles="{padding:2}"/>
+								<BoxPane orientation="horizontal">
+									<Label text="0" styles="{padding:2}"/>
+									<PushButton preferredHeight="20" action="prevDoc">
+										<buttonData>
+											<content:ButtonData icon="/img/prev.png" />
+										</buttonData>
+									</PushButton>
+									<TextInput preferredWidth="48" bxml:id="docNum" />
+									<PushButton preferredHeight="20" action="nextDoc">
+										<buttonData>
+											<content:ButtonData icon="/img/next.png" />
+										</buttonData>
+									</PushButton>
+									<Label bxml:id="maxDocs" text="?" styles="{padding:2}"/>
+								</BoxPane>
+							</BoxPane>
+						</TablePane.Row>
+					</rows>
+				</TablePane>
+				</content>
+				</Border>
+			</left>
+			<right>
+				<SplitPane orientation="horizontal" splitRatio="0.50" styles="{useShadow:true}">
+					<left>
+						<Border styles="{padding:1}">
+						<content>
+						<TablePane styles="{verticalSpacing:2,horizontalSpacing:1,padding:5,backgroundColor:11}">
+							<columns>
+								<TablePane.Column width="1*" />
+							</columns>
+							<rows>
+								<TablePane.Row>
+									<BoxPane orientation="vertical">
+										<Label text="%documentsTab_browseByTerm" styles="{padding:1,font:{bold:true}}"/>
+										<Label text="%documentsTab_selectField" styles="{wrapText:true}"/>
+										<Label text="%documentsTab_enterTermHint" styles="{wrapText:true}"/>
+										<ListButton bxml:id="fieldsList" listSize="20" />
+										<Label text="%documentsTab_term" />
+										<BoxPane>
+											<PushButton buttonData="%documentsTab_firstTerm"
+																	action="showFirstTerm" />
+											<TextInput bxml:id="termText" />
+											<PushButton action="showNextTerm">
+												<buttonData>
+													<content:ButtonData icon="/img/next.png" />
+												</buttonData>
+											</PushButton>
+										</BoxPane>
+									</BoxPane>
+								</TablePane.Row>
 
+								<TablePane.Row>
+									<BoxPane>
+										<Label text="%documentsTab_decodedValue" />
+										<TextArea bxml:id="decText" />
+									</BoxPane>
+								</TablePane.Row>
+							</rows>
+						</TablePane>
+						</content>
+						</Border>
+					</left>
+					<right>
+						<Border styles="{padding:1}">
+						<content>
+						<TablePane styles="{verticalSpacing:2,horizontalSpacing:1,padding:5,backgroundColor:11}">
+							<columns>
+								<TablePane.Column width="1*" />
+							</columns>
+							<rows>
+								<TablePane.Row>
+									<BoxPane orientation="vertical">
+										<Label text="%documentsTab_browseDocsWithTerm" styles="{padding:1,font:{bold:true}}"/>
+										<Label text="%documentsTab_selectTerm" styles="{wrapText:true}"/>
+										<BoxPane>
+											<!--Label text="%documentsTab_document" /-->
+											<PushButton buttonData="%documentsTab_firstDoc" action="showFirstTermDoc" />
+											<PushButton action="showNextTermDoc">
+												<buttonData>
+													<content:ButtonData icon="/img/next.png" />
+												</buttonData>
+											</PushButton>
 
-	<columns>
-		<TablePane.Column width="1*" />
-	</columns>
-	<rows>
-		<TablePane.Row>
-			<FlowPane styles="{padding:10}">
-				<BoxPane orientation="vertical">
-					<Label text="%documentsTab_browseByDocNum" />
-					<BoxPane>
-						<Label text="Doc. #:" />
-						<Label text="0" />
-						<PushButton preferredHeight="20" action="prevDoc">
-							<buttonData>
-								<content:ButtonData icon="/img/prev.png" />
-							</buttonData>
-						</PushButton>
-						<TextInput preferredWidth="48" bxml:id="docNum" />
-						<PushButton preferredHeight="20" action="nextDoc">
-							<buttonData>
-								<content:ButtonData icon="/img/next.png" />
-							</buttonData>
-						</PushButton>
-						<Label bxml:id="maxDocs" text="?" />
+											<Label text=" ("/>
+											<Label bxml:id="tdNum" text="?" />
+											<Label text=" of " />
+											<Label bxml:id="tdMax" text="?" />
+											<Label text=" documents )" />
+										</BoxPane>
+									</BoxPane>
+								</TablePane.Row>
 
-					</BoxPane>
-				</BoxPane>
+								<TablePane.Row>
+									<BoxPane orientation="vertical">
+										<BoxPane>
+											<Label text="%documentsTab_termFreqInDoc" />
+											<Label bxml:id="tFreq" text="?" />
+										</BoxPane>
+										<!--PushButton bxml:id="bPos" buttonData="%documentsTab_showPositions"
+																action="showPositions" /-->
+										<BoxPane orientation="vertical">
+											<Label text="%documentsTab_showPositions" />
+											<TextArea bxml:id="posAndOffsets" text="?" />
+										</BoxPane>
+									</BoxPane>
+								</TablePane.Row>
 
-				<BoxPane orientation="vertical">
-					<Label text="%documentsTab_browseByTerm" />
-					<Label text="%documentsTab_enterTermHint" />
-					<BoxPane>
-						<PushButton buttonData="%documentsTab_firstTerm"
-							action="showFirstTerm" />
-						<Label text="%documentsTab_term" />
-						<ListButton bxml:id="fieldsList" listSize="20" />
-						<TextInput bxml:id="termText" />
-						<PushButton action="showNextTerm">
-							<buttonData>
-								<content:ButtonData icon="/img/next.png" />
-							</buttonData>
-						</PushButton>
-					</BoxPane>
-				</BoxPane>
+								<TablePane.Row>
+									<Separator/>
+								</TablePane.Row>
 
+								<TablePane.Row>
+									<BoxPane>
+										<PushButton buttonData="%documentsTab_showAllDocs"
+																action="showAllTermDoc"/>
+										<BoxPane>
+											<PushButton action="deleteTermDoc">
+												<buttonData>
+													<content:ButtonData icon="/img/delete.gif" />
+												</buttonData>
+											</PushButton>
+											<Label text="%documentsTab_deleteAllDocs" styles="{padding:1}"/>
+										</BoxPane>
+									</BoxPane>
+								</TablePane.Row>
 
-				<!-- second row -->
-				<Label text="%documentsTab_decodedValue" />
-				<TextArea bxml:id="decText" />
+							</rows>
+						</TablePane>
+						</content>
+						</Border>
+					</right>
+				</SplitPane>
+			</right>
+		</SplitPane>
+	</top>
 
-				<Separator />
-				<BoxPane orientation="vertical">
-					<BoxPane>
-						<Label text="%documentsTab_browseDocsWithTerm" />
-						<Label text="( " />
-						<Label bxml:id="dFreq" text="0" />
-						<Label text=" documents)" />
-					</BoxPane>
-
-					<BoxPane>
-						<Label text="%documentsTab_document" />
-						<Label bxml:id="tdNum" text="?" />
-						<Label text=" of " />
-						<Label bxml:id="tdMax" text="?" />
-						<PushButton buttonData="%documentsTab_firstDoc" action="showFirstTermDoc" />
-						<PushButton action="showNextTermDoc">
-							<buttonData>
-								<content:ButtonData icon="/img/next.png" />
-							</buttonData>
-						</PushButton>
-					</BoxPane>
-
-				</BoxPane>
-				<BoxPane orientation="vertical">
-					<PushButton buttonData="%documentsTab_showAllDocs"
-						action="showAllTermDoc" />
-					<PushButton buttonData="%documentsTab_deleteAllDocs"
-						action="deleteTermDoc">
-						<buttonData>
-							<content:ButtonData icon="/img/delete.gif" />
-						</buttonData>
-					</PushButton>
-				</BoxPane>
-				<Label text=" " />
-				<Label text="%documentsTab_termFreqInDoc" />
-
-				<Label bxml:id="tFreq" text="?" />
-				<PushButton bxml:id="bPos" buttonData="%documentsTab_showPositions"
-					action="showPositions" />
-			</FlowPane>
-		</TablePane.Row>
-		<TablePane.Row>
-			<TablePane styles="{verticalSpacing:1, horizontalSpacing:1}">
-				<columns>
-					<TablePane.Column width="1*" />
-					<TablePane.Column />
-				</columns>
-				<rows>
-					<TablePane.Row>
-						<FlowPane>
-							<Label text="Doc #:" />
-							<Label bxml:id="docNum2" text="?" />
-							<Label text=" " />
-						</FlowPane>
-						<FlowPane>
-							<TablePane styles="{verticalSpacing:1, horizontalSpacing:1}">
-								<columns>
-									<TablePane.Column />
-									<TablePane.Column />
-									<TablePane.Column />
-									<TablePane.Column />
-									<TablePane.Column />
-									<TablePane.Column />
-								</columns>
-								<rows>
-									<TablePane.Row>
-										<Label text="Flags: " />
-										<Label text=" I - Indexed " />
-										<Label text="  T - Tokenized " />
-										<Label text="  S - Stored " />
-										<Label text="  V - Term Vector " />
-										<Label text=" (o - offsets; p - positions) " />
-									</TablePane.Row>
-									<TablePane.Row>
-										<TablePane.Filler />
-
-										<Label text=" O - Omit Norms " />
-										<Label text="  f - Omit TF " />
-										<Label text="  L - Lazy " />
-										<Label text="  B - Binary " />
-									</TablePane.Row>
-								</rows>
-							</TablePane>
-						</FlowPane>
-					</TablePane.Row>
-				</rows>
-			</TablePane>
-		</TablePane.Row>
-		<TablePane.Row height="1*">
-			<ScrollPane horizontalScrollBarPolicy="fill_to_capacity" styles="{backgroundColor:11}">
-				<view>
-					<TableView bxml:id="docTable">
+	<bottom>
+		<TablePane styles="{verticalSpacing:5,horizontalSpacing:1,padding:5,backgroundColor:11}">
+			<columns>
+				<TablePane.Column width="1*" />
+			</columns>
+			<rows>
+				<TablePane.Row>
+					<TablePane>
 						<columns>
-							<TableView.Column name="field"
-								headerData="%documentsTab_docTable_col1" />
-							<TableView.Column name="itsvopfolb"
-								headerData="%documentsTab_docTable_col2" />
-							<TableView.Column name="norm"
-								headerData="%documentsTab_docTable_col3" />
-							<TableView.Column name="value"
-								headerData="%documentsTab_docTable_col4" width="1*" />
+							<TablePane.Column width="1*" />
+							<TablePane.Column />
 						</columns>
+						<rows>
+							<TablePane.Row>
+								<FlowPane>
+									<Label text="Doc #:" />
+									<Label bxml:id="docNum2" text="?" />
+									<Label text=" " />
+								</FlowPane>
+								<FlowPane>
+									<TablePane styles="{verticalSpacing:1, horizontalSpacing:1}">
+										<columns>
+											<TablePane.Column />
+											<TablePane.Column />
+											<TablePane.Column />
+											<TablePane.Column />
+											<TablePane.Column />
+											<TablePane.Column />
+										</columns>
+										<rows>
+											<TablePane.Row>
+												<Label text="Flags: " />
+												<Label text=" I - Indexed " />
+												<Label text=" T - Tokenized " />
+												<Label text=" S - Stored " />
+												<Label text=" V - Term Vector " />
+												<Label text=" (o - offsets; p - positions; a - payloads) " />
+											</TablePane.Row>
+											<TablePane.Row>
+												<TablePane.Filler />
 
-					</TableView>
-				</view>
-				<columnHeader>
-					<TableViewHeader tableView="$docTable" />
-				</columnHeader>
-			</ScrollPane>
-		</TablePane.Row>
-	</rows>
+												<Label text=" t - Index options" />
+												<Label text=" O - Omit Norms " />
+												<!--Label text="  f - Omit TF " /-->
+												<Label text=" L - Lazy " />
+												<Label text=" B - Binary " />
+											</TablePane.Row>
+										</rows>
+									</TablePane>
+								</FlowPane>
+							</TablePane.Row>
+						</rows>
+					</TablePane>
+				</TablePane.Row>
+				<TablePane.Row height="1*">
+					<Border styles="{padding:1}">
+						<content>
+							<!--ScrollPane horizontalScrollBarPolicy="fill_to_capacity" styles="{backgroundColor:11}"-->
+							<ScrollPane horizontalScrollBarPolicy="fill_to_capacity" styles="{backgroundColor:11}">
+								<view>
+									<TableView bxml:id="docTable">
+										<columns>
+											<TableView.Column name="field"
+																				headerData="%documentsTab_docTable_col1" />
+											<TableView.Column name="itsvopatolb"
+																				headerData="%documentsTab_docTable_col2" />
+											<TableView.Column name="docvaluestype"
+																				headerData="%documentsTab_docTable_col3" />
+											<TableView.Column name="norm"
+																				headerData="%documentsTab_docTable_col4" />
+											<TableView.Column name="value"
+																				headerData="%documentsTab_docTable_col5" width="1*" />
+										</columns>
+
+									</TableView>
+								</view>
+								<columnHeader>
+									<TableViewHeader tableView="$docTable" />
+								</columnHeader>
+							</ScrollPane>
+						</content>
+					</Border>
+				</TablePane.Row>
+				<TablePane.Row>
+					<BoxPane orientation="vertical">
+						<Label text="%documentsTab_indexOptionsNote1" styles="{wrapText:true}"/>
+						<Label text="%documentsTab_indexOptionsNote2" styles="{wrapText:true}"/>
+					</BoxPane>
+				</TablePane.Row>
+			</rows>
+		</TablePane>
+	</bottom>
 </luke:DocumentsTab>
Index: src/org/apache/lucene/luke/ui/DocumentsTab.java
===================================================================
--- src/org/apache/lucene/luke/ui/DocumentsTab.java	(revision 1655665)
+++ src/org/apache/lucene/luke/ui/DocumentsTab.java	(working copy)
@@ -55,17 +55,9 @@
 import org.apache.pivot.util.concurrent.Task;
 import org.apache.pivot.util.concurrent.TaskExecutionException;
 import org.apache.pivot.util.concurrent.TaskListener;
-import org.apache.pivot.wtk.Action;
-import org.apache.pivot.wtk.Component;
-import org.apache.pivot.wtk.Label;
-import org.apache.pivot.wtk.ListButton;
-import org.apache.pivot.wtk.TablePane;
-import org.apache.pivot.wtk.TableView;
-import org.apache.pivot.wtk.TaskAdapter;
-import org.apache.pivot.wtk.TextArea;
-import org.apache.pivot.wtk.TextInput;
+import org.apache.pivot.wtk.*;
 
-public class DocumentsTab extends TablePane implements Bindable {
+public class DocumentsTab extends SplitPane implements Bindable {
 
   private int iNum;
   @BXML
@@ -90,6 +82,8 @@
   private Label docNum2;
   @BXML
   private TextArea decText;
+  @BXML
+  private TextArea posAndOffsets;
 
   private java.util.List<String> fieldNames = null;
 
@@ -99,7 +93,8 @@
   private Resources resources;
 
   private TermsEnum te;
-  private DocsAndPositionsEnum td;
+  //private DocsAndPositionsEnum td;
+  private DocsEnum td;
 
   private String fld;
   private Term lastTerm;
@@ -326,10 +321,9 @@
 
     docNum2.setText(String.valueOf(docid));
     for (int i = 0; i < indexFields.size(); i++) {
-      Map<String,String> row = new HashMap<String,String>();
-
       IndexableField[] fields = doc.getFields(indexFields.get(i));
-      if (fields == null) {
+      if (fields == null || fields.length == 0) {
+        Map<String,String> row = new HashMap<String,String>();
         tableData.add(row);
         addFieldRow(row, indexFields.get(i), null, docid);
         continue;
@@ -339,6 +333,7 @@
         // System.out.println("f.len=" + fields[j].getBinaryLength() +
         // ", doc.len=" + doc.getBinaryValue(indexFields[i]).length);
         // }
+        Map<String,String> row = new HashMap<String,String>();
         tableData.add(row);
         addFieldRow(row, indexFields.get(i), fields[j], docid);
       }
@@ -354,19 +349,20 @@
     // putProperty(row, "fName", fName);
 
     row.put("field", fName);
-    row.put("itsvopfolb", Util.fieldFlags(f));
+    row.put("itsvopatolb", Util.fieldFlags(f, infos.fieldInfo(fName)));
+    row.put("docvaluestype", Util.docValuesType(infos.fieldInfo(fName)));
 
     // if (f == null) {
     // setBoolean(cell, "enabled", false);
     // }
 
-    if (f != null) {
+    if (fName != null) {
       try {
         FieldInfo info = infos.fieldInfo(fName);
         if (info.hasNorms()) {
           NumericDocValues norms = ar.getNormValues(fName);
-          String val = Long.toString(norms.get(docid));
-          row.put("norm", String.valueOf(norms.get(docid)));
+          String norm = String.valueOf(norms.get(docid)) + " (" + Util.normType(info) + ")";
+          row.put("norm", norm);
         } else {
           row.put("norm", "---");
         }
@@ -395,7 +391,8 @@
         if (f.fieldType().stored()) {
           text = dec.decodeStored(f.name(), f);
         } else {
-          text = dec.decodeTerm(f.name(), text);
+          //text = dec.decodeTerm(f.name(), text);
+          text = dec.decodeTerm(f.name(), f.binaryValue());
         }
       } catch (Throwable e) {
         // TODO:
@@ -428,7 +425,7 @@
         try {
 
           fld = (String) fieldsList.getSelectedItem();
-          System.out.println("fld:" + fld);
+          //System.out.println("fld:" + fld);
           Terms terms = MultiFields.getTerms(ir, fld);
           te = terms.iterator(null);
           BytesRef term = te.next();
@@ -472,7 +469,12 @@
       @Override
       public void taskExecuted(Task<Object> task) {
         try {
-          DocsAndPositionsEnum td = MultiFields.getTermPositionsEnum(ir, null, lastTerm.field(), lastTerm.bytes());
+          // try get DocsEnum with positions.
+          DocsEnum td = MultiFields.getTermPositionsEnum(ir, null, lastTerm.field(), lastTerm.bytes());
+          if (td == null) {
+            // positions were not indexed for this term.
+            td = MultiFields.getTermDocsEnum(ir, null, lastTerm.field(), lastTerm.bytes());
+          }
           td.nextDoc();
           tdNum.setText("1");
           DocumentsTab.this.td = td;
@@ -549,7 +551,7 @@
 
   }
 
-  private void showTerm(final Term t) {
+  protected void showTerm(final Term t) {
     if (t == null) {
       // TODO:
       // showStatus("No terms?!");
@@ -571,7 +573,8 @@
     String s = null;
     boolean decodeErr = false;
     try {
-      s = dec.decodeTerm(t.field(), t.text());
+      //s = dec.decodeTerm(t.field(), t.text());
+      s = dec.decodeTerm(t.field(), t.bytes());
     } catch (Throwable e) {
       s = e.getMessage();
       decodeErr = true;
@@ -580,7 +583,8 @@
     termText.setText(t.text());
 
     if (!s.equals(t.text())) {
-      decText.setText(s);
+      String decoded = s + " (by " + dec.toString() + ")";
+      decText.setText(decoded);
 
       if (decodeErr) {
         // setColor(rawText, "foreground", Color.RED);
@@ -598,6 +602,7 @@
     td = null;
     tdNum.setText("?");
     tFreq.setText("?");
+    posAndOffsets.setText("?");
 
     Task<Object> updateDfTdTask = new Task<Object>() {
 
@@ -613,14 +618,11 @@
 
         try {
           int freq = ir.docFreq(t);
-          dFreq.setText(String.valueOf(freq));
-
           tdMax.setText(String.valueOf(freq));
         } catch (Exception e) {
           e.printStackTrace();
           // TODO:
           // showStatus(e.getMessage());
-          dFreq.setText("?");
         }
         // ai.setActive(false);
       }
@@ -670,17 +672,20 @@
           String rawString = rawTerm != null ? rawTerm.utf8ToString() : null;
 
           if (te == null || !DocumentsTab.this.fld.equals(fld) || !text.equals(rawString)) {
+            // seek for requested term
             Terms terms = MultiFields.getTerms(ir, fld);
             te = terms.iterator(null);
 
             DocumentsTab.this.fld = fld;
             status = te.seekCeil(new BytesRef(text));
-            if (status.equals(SeekStatus.FOUND)) {
+            if (status.equals(SeekStatus.FOUND) || status.equals(SeekStatus.NOT_FOUND)) {
+              // precise term or different term after the requested term was found.
               rawTerm = te.term();
             } else {
               rawTerm = null;
             }
           } else {
+            // move to next term
             rawTerm = te.next();
           }
           if (rawTerm == null) { // proceed to next field
@@ -696,7 +701,7 @@
               te = terms.iterator(null);
               rawTerm = te.next();
               DocumentsTab.this.fld = fld;
-              break;
+              //break;
             }
           }
           if (rawTerm == null) {
@@ -747,6 +752,34 @@
 
           tFreq.setText(String.valueOf(td.freq()));
 
+          // if positions were indexed, positions (and offsets) information were also reterned.
+          if (td instanceof DocsAndPositionsEnum) {
+            DocsAndPositionsEnum pe = (DocsAndPositionsEnum) td;
+            PositionAndOffset[] posAndOffsetsAry = getTermPositionAndOffsets(pe);
+            StringBuilder sb = new StringBuilder();
+            sb.append("[");
+            for (PositionAndOffset posAndOffset : posAndOffsetsAry) {
+              //if (posAndOffset.pos > 0) {
+                sb.append(posAndOffset.pos);
+                if (posAndOffset.sOffset > 0 && posAndOffset.eOffset > 0) {
+                  sb.append("(");
+                  sb.append(posAndOffset.sOffset + ":" + posAndOffset.eOffset);
+                  sb.append(")");
+                  sb.append(",");
+                }
+              //}
+            }
+            if (sb.length() > 1) {
+              // remove last ',' char
+              sb.deleteCharAt(sb.length()-1);
+            }
+            sb.append("]");
+            //System.out.println(sb.toString());
+            posAndOffsets.setText(sb.toString());
+          } else {
+            posAndOffsets.setText("(position not indexed)");
+          }
+
           popTableWithDoc(td.docID(), doc);
         } catch (Exception e) {
           e.printStackTrace();
@@ -767,6 +800,25 @@
 
   }
 
+  class PositionAndOffset {
+    private int pos;
+    private int sOffset;
+    private int eOffset;
+  }
+
+  private PositionAndOffset[] getTermPositionAndOffsets(DocsAndPositionsEnum pe) throws IOException {
+    int freq = pe.freq();
+    PositionAndOffset[] res = new PositionAndOffset[freq];
+    for (int i = 0; i < freq; i++) {
+      PositionAndOffset po = new PositionAndOffset();
+      po.pos = pe.nextPosition();
+      po.sOffset = pe.startOffset();
+      po.eOffset = pe.endOffset();
+      res[i] = po;
+    }
+    return res;
+  }
+
   public void showAllTermDoc() {
     final IndexReader ir = lukeMediator.getIndexInfo().getReader();
     if (ir == null) {
Index: src/org/apache/lucene/luke/ui/LukeApplication_en.json
===================================================================
--- src/org/apache/lucene/luke/ui/LukeApplication_en.json	(revision 1655665)
+++ src/org/apache/lucene/luke/ui/LukeApplication_en.json	(working copy)
@@ -58,9 +58,10 @@
  overviewTab_userData: "Current commit user data:",
  
  overviewTab_fieldsAndTermCounts: "Available fields and term counts per field:",
- overviewTab_topRankingTerms: "Top Ranking Terms (Right click for more options)",
+ overviewTab_topRankingTerms: "Top Ranking Terms (Select a row and right click for more options)",
  overviewTab_decoderWarn: "Tokens marked in red indicate decoding errors, likely due to a mismatched decoder.",
  overviewTab_fieldSelect: "Select fields from the list below, and press button to view top terms in these fields. No selection means all fields.",
+ overviewTab_fieldsHintDecoder: "Hint: Double click 'Decoder' column, select decoder class, and press Enter to set the suitable decoder.",
  overviewTab_topTermsHint: "Hint: use Shift-Click to select ranges, or Ctrl-Click to select multiple fields (or unselect all).",
  overviewTab_showTopTerms: "Show top terms >>",
  
@@ -68,27 +69,36 @@
  overviewTab_topTermsTable_col2: "DF",
  overviewTab_topTermsTable_col3: "Field",
  overviewTab_topTermsTable_col4: "Text",
+
+ overviewTab_topTermTable_popup_menu1: "Browse term docs",
+ overviewTab_topTermTable_popup_menu2: "Show all term docs",
+ overviewTab_topTermTable_popup_menu3: "Copy to clipboard",
  
  documentsTab_noOrClosedIndex: "FAILED: No index, or index is closed. Reopen it.",
  documentsTab_docNumOutsideRange: "Document number outside valid range.",
  documentsTab_browseByDocNum: "Browse by document number:",
  documentsTab_browseByTerm: "Browse by term:",
+ documentsTab_selectField: "Select a field from the spinner below, press Next to browse terms.",
  documentsTab_enterTermHint: "(Hint: enter a substring and press Next to start at the nearest term).",
  documentsTab_firstTerm: "First Term",
  documentsTab_term: "Term:",
  documentsTab_decodedValue: "Decoded value:",
- documentsTab_browseDocsWithTerm: "Browse documents with this term",
+ documentsTab_browseDocsWithTerm: "Browse documents with this term:",
+ documentsTab_selectTerm: "After select term, press Next to browse docs with the term.",
  documentsTab_showAllDocs: "Show All Docs",
  documentsTab_deleteAllDocs: "Delete All Docs",
  documentsTab_document: "Document:",
  documentsTab_firstDoc: "First Doc",
  documentsTab_termFreqInDoc: "Term freq in this doc:",
- documentsTab_showPositions: "Show Positions",
- 
+ documentsTab_showPositions: "Show Positions and Offsets (optionally): ",
+ documentsTab_indexOptionsNote1: "Note: flag 't - Index options' means, 1: DOCS_ONLY; 2:DOCS_AND_FREQS; 3: DOCS_AND_FREQS_AND_POSITIONS; 4: DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS.",
+ documentsTab_indexOptionsNote2: "(See Javadocs about FieldInfo.IndexOptions for more info.)",
+
  documentsTab_docTable_col1: "Field",
- documentsTab_docTable_col2: "ITSVopfOLB",
- documentsTab_docTable_col3: "Norm",
- documentsTab_docTable_col4: "Value",
+ documentsTab_docTable_col2: "ITSVopatOLB",
+ documentsTab_docTable_col3: "DocValues Type",
+ documentsTab_docTable_col4: "Norm (Norm Type)",
+ documentsTab_docTable_col5: "Value",
  
  searchTab_searchPrompt: "Enter search expression here:",
  searchTab_update: "Update",
Index: src/org/apache/lucene/luke/ui/LukeWindow.bxml
===================================================================
--- src/org/apache/lucene/luke/ui/LukeWindow.bxml	(revision 1655665)
+++ src/org/apache/lucene/luke/ui/LukeWindow.bxml	(working copy)
@@ -103,7 +103,7 @@
 								</content>
 							</Border>
 
-							<Border>
+							<Border styles="{backgroundColor:11,thickness:0}">
 								<TabPane.tabData>
 									<content:ButtonData icon="/img/docs.gif"
 										text="%lukeWindow_documentsTabText" />
Index: src/org/apache/lucene/luke/ui/LukeWindow.java
===================================================================
--- src/org/apache/lucene/luke/ui/LukeWindow.java	(revision 1655665)
+++ src/org/apache/lucene/luke/ui/LukeWindow.java	(working copy)
@@ -23,7 +23,6 @@
 import java.lang.reflect.Constructor;
 import java.net.URL;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.HashSet;
 
 import org.apache.lucene.analysis.Analyzer;
@@ -99,6 +98,8 @@
   @BXML
   private LukeInitWindow lukeInitWindow;
   @BXML
+  private TabPane tabPane;
+  @BXML
   private FilesTab filesTab;
   @BXML
   private DocumentsTab documentsTab;
@@ -622,8 +623,13 @@
       setComponentColor(component, "scrollButtonBackgroundColor", theme[2]);
       setComponentColor(component, "borderColor", theme[3]);
     } else if (component instanceof PushButton || component instanceof ListButton) {
-      component.getComponentMouseButtonListeners().add(mouseButtonPressedListener);
-      component.getComponentMouseListeners().add(mouseMoveListener);
+      // Listeners are added at start-up time only.
+      if (component.getComponentMouseButtonListeners().isEmpty()) {
+        component.getComponentMouseButtonListeners().add(mouseButtonPressedListener);
+      }
+      if (component.getComponentMouseListeners().isEmpty()) {
+        component.getComponentMouseListeners().add(mouseMoveListener);
+      }
       setComponentColor(component, "color", theme[1]);
       setComponentColor(component, "backgroundColor", theme[0]);
       setComponentColor(component, "borderColor", theme[3]);
@@ -679,7 +685,7 @@
 
   private Directory directory;
 
-  class LukeMediator {
+  public class LukeMediator {
 
     // populated by LukeWindow#openIndex
     private IndexInfo indexInfo;
@@ -700,6 +706,14 @@
       return overviewTab;
     }
 
+    public DocumentsTab getDocumentsTab() {
+      return documentsTab;
+    }
+
+    public TabPane getTabPane() {
+      return tabPane;
+    }
+
     public LukeWindow getLukeWindow() {
       return LukeWindow.this;
     }
Index: src/org/apache/lucene/luke/ui/OverviewTab.bxml
===================================================================
--- src/org/apache/lucene/luke/ui/OverviewTab.bxml	(revision 1655665)
+++ src/org/apache/lucene/luke/ui/OverviewTab.bxml	(working copy)
@@ -148,9 +148,12 @@
 											</columns>
 											<rows>
 												<TablePane.Row height="-1">
-													<Label styles="{backgroundColor:11,padding:2}" text="%overviewTab_fieldSelect" />
+													<Label styles="{backgroundColor:11,padding:2,wrapText:true}" text="%overviewTab_fieldSelect" />
 												</TablePane.Row>
 												<TablePane.Row height="-1">
+													<Label styles="{backgroundColor:11,padding:2,wrapText:true}" text="%overviewTab_fieldsHintDecoder" />
+												</TablePane.Row>
+												<TablePane.Row height="-1">
 													<Label styles="{backgroundColor:11,font:{bold:true}}"
 														text="%overviewTab_fieldsAndTermCounts" />
 												</TablePane.Row>
Index: src/org/apache/lucene/luke/ui/OverviewTab.java
===================================================================
--- src/org/apache/lucene/luke/ui/OverviewTab.java	(revision 1655665)
+++ src/org/apache/lucene/luke/ui/OverviewTab.java	(working copy)
@@ -21,19 +21,16 @@
 import java.text.NumberFormat;
 import java.util.Collections;
 
-import org.apache.lucene.index.AtomicReaderContext;
-import org.apache.lucene.index.DirectoryReader;
-import org.apache.lucene.index.IndexCommit;
-import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.index.SegmentReader;
-import org.apache.lucene.luke.core.FieldTermCount;
+import org.apache.lucene.index.*;
+import org.apache.lucene.luke.core.*;
 import org.apache.lucene.luke.core.HighFreqTerms;
-import org.apache.lucene.luke.core.IndexInfo;
-import org.apache.lucene.luke.core.TableComparator;
 import org.apache.lucene.luke.core.TermStats;
-import org.apache.lucene.luke.core.decoders.Decoder;
+import org.apache.lucene.luke.core.decoders.*;
 import org.apache.lucene.luke.ui.LukeWindow.LukeMediator;
+import org.apache.lucene.luke.ui.util.FieldsTableRow;
+import org.apache.lucene.luke.ui.util.TableComparator;
 import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.BytesRef;
 import org.apache.pivot.beans.BXML;
 import org.apache.pivot.beans.Bindable;
 import org.apache.pivot.collections.*;
@@ -43,6 +40,7 @@
 import org.apache.pivot.util.concurrent.TaskExecutionException;
 import org.apache.pivot.util.concurrent.TaskListener;
 import org.apache.pivot.wtk.*;
+import org.apache.pivot.wtk.content.TableViewRowEditor;
 
 
 public class OverviewTab extends SplitPane implements Bindable {
@@ -230,7 +228,6 @@
 
             iTerms.setText(String.valueOf(numTerms));
             initFieldList(null, null);
-
           } catch (Exception e) {
             // showStatus("ERROR: can't count terms per field");
             numTerms = -1;
@@ -261,6 +258,7 @@
       };
 
       fListTask.execute(new TaskAdapter<String>(taskListener));
+      clearFieldsTableStatus();
 
       String sDel = ir.hasDeletions() ? "Yes (" + ir.numDeletedDocs() + ")" : "No";
       IndexCommit ic = ir instanceof DirectoryReader ? ((DirectoryReader) ir).getIndexCommit() : null;
@@ -347,16 +345,24 @@
 
     Sequence<?> fields = fieldsTable.getSelectedRows();
 
-    String[] flds = null;
+    final java.util.Map<String, Decoder> fldDecMap = new java.util.HashMap<String, Decoder>();
     if (fields == null || fields.getLength() == 0) {
-      flds = indexInfo.getFieldNames().toArray(new String[0]);
+      // no fields selected
+      for (String fld : indexInfo.getFieldNames()) {
+        Decoder dec = lukeMediator.getDecoders().get(fld);
+        if (dec == null) {
+          dec = lukeMediator.getDefDecoder();
+        }
+        fldDecMap.put(fld, dec);
+      }
     } else {
-      flds = new String[fields.getLength()];
+      // some fields selected
       for (int i = 0; i < fields.getLength(); i++) {
-        flds[i] = ((Map<String,String>) fields.get(i)).get("name");
+        String fld = ((FieldsTableRow)fields.get(i)).getName();
+        Decoder dec = ((FieldsTableRow)fields.get(i)).getDecoder();
+        fldDecMap.put(fld, dec);
       }
     }
-    final String[] fflds = flds;
 
     tTable.setTableData(new ArrayList(0));
 
@@ -387,6 +393,7 @@
       public void taskExecuted(Task<Object> task) {
         // this must happen here rather than in the task because it must happen in the UI dispatch thread
         try {
+          final String[] fflds = fldDecMap.keySet().toArray(new String[0]);
           TermStats[] topTerms = HighFreqTerms.getHighFreqTerms(ir, ndoc, fflds);
 
           List<Map<String,String>> tableData = new ArrayList<Map<String,String>>();
@@ -409,12 +416,11 @@
 
             row.put("field", topTerms[i].field);
 
-            Decoder dec = lukeMediator.getDecoders().get(topTerms[i].field);
-            if (dec == null)
-              dec = lukeMediator.getDefDecoder();
+            Decoder dec = fldDecMap.get(topTerms[i].field);
+
             String s;
             try {
-              s = dec.decodeTerm(topTerms[i].field, topTerms[i].termtext.utf8ToString());
+              s = dec.decodeTerm(topTerms[i].field, topTerms[i].termtext);
             } catch (Throwable e) {
               // e.printStackTrace();
               s = topTerms[i].termtext.utf8ToString();
@@ -422,6 +428,8 @@
               // setColor(cell, "foreground", Color.RED);
             }
             row.put("text", s);
+            // hidden field. would be used when the user select 'Browse term docs' menu at top terms table.
+            row.put("rawterm", topTerms[i].termtext.utf8ToString());
             tableData.add(row);
           }
           tTable.setTableData(tableData);
@@ -443,8 +451,74 @@
     };
 
     topTermsTask.execute(new TaskAdapter<Object>(taskListener));
+
+    addListenerToTopTermsTable();
   }
 
+  private void addListenerToTopTermsTable() {
+    // register mouse button listener for more options.
+    tTable.getComponentMouseButtonListeners().add(new ComponentMouseButtonListener.Adapter(){
+      @Override
+      public boolean mouseClick(Component component, Mouse.Button button, int x, int y, int count) {
+        final Map<String, String> row = (Map<String, String>) tTable.getSelectedRow();
+        if (row == null) {
+          System.out.println("No term selected.");
+          return false;
+        }
+        if (button.name().equals(Mouse.Button.RIGHT.name())) {
+          MenuPopup popup = new MenuPopup();
+          Menu menu = new Menu();
+          Menu.Section section1 = new Menu.Section();
+          Menu.Section section2 = new Menu.Section();
+          Menu.Item item1 = new Menu.Item(resources.get("overviewTab_topTermTable_popup_menu1"));
+          item1.setAction(new Action() {
+            @Override
+            public void perform(Component component) {
+              // 'Browse term docs' menu selected. switch to Documents tab.
+              Term term = new Term(row.get("field"), new BytesRef(row.get("rawterm")));
+              lukeMediator.getDocumentsTab().showTerm(term);
+              // TODO: index access isn't good...
+              lukeMediator.getTabPane().setSelectedIndex(1);
+            }
+          });
+          Menu.Item item2 = new Menu.Item(resources.get("overviewTab_topTermTable_popup_menu2"));
+          item2.setAction(new Action() {
+            @Override
+            public void perform(Component component) {
+              // 'Show all term docs' menu selected. switch to Search tab.
+              // TODO
+            }
+          });
+          Menu.Item item3 = new Menu.Item(resources.get("overviewTab_topTermTable_popup_menu3"));
+          item3.setAction(new Action() {
+            @Override
+            public void perform(Component component) {
+              // 'Copy to clipboard' menu selected.
+              StringBuilder sb = new StringBuilder();
+              sb.append(row.get("num") + "\t");
+              sb.append(row.get("df") + "\t");
+              sb.append(row.get("field") + "\t");
+              sb.append(row.get("text") + "\t");
+              LocalManifest content = new LocalManifest();
+              content.putText(sb.toString());
+              Clipboard.setContent(content);
+            }
+          });
+          section1.add(item1);
+          section1.add(item2);
+          section2.add(item3);
+          menu.getSections().add(section1);
+          menu.getSections().add(section2);
+          popup.setMenu(menu);
+
+          popup.open(getWindow(), getMouseLocation().x + 20, getMouseLocation().y);
+          return true;
+        }
+        return false;
+      }
+    });
+  }
+
   private void initFieldList(Object fCombo, Object defFld) {
     // removeAll(fieldsTable);
     // removeAll(defFld);
@@ -454,11 +528,12 @@
     NumberFormat percentFormat = NumberFormat.getNumberInstance();
     intCountFormat.setGroupingUsed(true);
     percentFormat.setMaximumFractionDigits(2);
+    // sort listener
     fieldsTable.getTableViewSortListeners().add(new TableViewSortListener.Adapter() {
       @Override
       public void sortChanged(TableView tableView) {
         @SuppressWarnings("unchecked")
-        List<Map<String, String>> tableData = (List<Map<String, String>>) tableView.getTableData();
+        List<FieldsTableRow> tableData = (List<FieldsTableRow>) tableView.getTableData();
         tableData.setComparator(new TableComparator(tableView));
       }
     });
@@ -465,34 +540,39 @@
     // default sort : sorted by name in ascending order
     fieldsTable.setSort("name", SortDirection.ASCENDING);
 
-    for (String s : indexInfo.getFieldNames()) {
-      Map<String,String> row = new HashMap<String,String>();
+    // row editor for decoders
+    List decoders = new ArrayList();
+    for (Decoder dec : Util.loadDecoders()) {
+      decoders.add(dec);
+    }
+    ListButton decodersButton = new ListButton(decoders);
+    decodersButton.setSelectedItemKey("decoder");
+    TableViewRowEditor rowEditor = new TableViewRowEditor();
+    rowEditor.getCellEditors().put("decoder", decodersButton);
+    fieldsTable.setRowEditor(rowEditor);
 
-      row.put("name", s);
 
-      FieldTermCount ftc = termCounts.get(s);
+    for (String fname : indexInfo.getFieldNames()) {
+      FieldsTableRow row = new FieldsTableRow(lukeMediator);
+      row.setName(fname);
+      FieldTermCount ftc = termCounts.get(fname);
       if (ftc != null) {
         long cnt = ftc.termCount;
-
-        row.put("termCount", intCountFormat.format(cnt));
-
+        row.setTermCount(intCountFormat.format(cnt));
         float pcent = (float) (cnt * 100) / (float) numTerms;
-
-        row.put("percent", percentFormat.format(pcent) + " %");
-
+        row.setPercent(percentFormat.format(pcent) + " %");
       } else {
-        row.put("termCount", "0");
-        row.put("percent", "0.00%");
+        row.setTermCount("0");
+        row.setPercent("0.00%");
       }
 
-      //tableData.add(row);
-      List<Map<String, String>> tableData = (List<Map<String, String>>)fieldsTable.getTableData();
+      List<FieldsTableRow> tableData = (List<FieldsTableRow>)fieldsTable.getTableData();
       tableData.add(row);
 
-      Decoder dec = lukeMediator.getDecoders().get(s);
+      Decoder dec = lukeMediator.getDecoders().get(fname);
       if (dec == null)
         dec = lukeMediator.getDefDecoder();
-      row.put("decoder", dec.toString());
+      row.setDecoder(dec);
 
       // populate combos
       // Object choice = create("choice");
@@ -504,9 +584,14 @@
       // setString(choice, "text", s);
       // putProperty(choice, "fName", s);
     }
-    //fieldsTable.setTableData(tableData);
+
   }
 
+  private void clearFieldsTableStatus() {
+    // clear the fields table view status
+    fieldsTable.clearSelection();
+  }
+
   private int getNTerms() {
     final int nTermsInt = nTerms.getSelectedIndex();
     return nTermsInt;
Index: src/org/apache/lucene/luke/ui/util/FieldsTableRow.java
===================================================================
--- src/org/apache/lucene/luke/ui/util/FieldsTableRow.java	(revision 0)
+++ src/org/apache/lucene/luke/ui/util/FieldsTableRow.java	(working copy)
@@ -0,0 +1,61 @@
+package org.apache.lucene.luke.ui.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.luke.core.decoders.Decoder;
+import org.apache.lucene.luke.ui.LukeWindow;
+
+public class FieldsTableRow {
+  private String name;
+  private String termCount;
+  private String percent;
+  private Decoder decoder;
+
+  private LukeWindow.LukeMediator lukeMediator;
+
+  public FieldsTableRow(LukeWindow.LukeMediator lukeMediator) {
+    this.lukeMediator = lukeMediator;
+  }
+
+  public String getName() {
+    return name;
+  }
+  public void setName(String name) {
+    this.name = name;
+  }
+  public String getTermCount() {
+    return termCount;
+  }
+  public void setTermCount(String termCount) {
+    this.termCount = termCount;
+  }
+  public String getPercent() {
+    return percent;
+  }
+  public void setPercent(String percent) {
+    this.percent = percent;
+  }
+  public Decoder getDecoder() {
+    return decoder;
+  }
+  public void setDecoder(Decoder decoder) {
+    this.decoder = decoder;
+    this.lukeMediator.getDecoders().put(name, decoder);
+  }
+
+}
Index: src/org/apache/lucene/luke/ui/util/TableComparator.java
===================================================================
--- src/org/apache/lucene/luke/ui/util/TableComparator.java	(revision 0)
+++ src/org/apache/lucene/luke/ui/util/TableComparator.java	(working copy)
@@ -0,0 +1,102 @@
+package org.apache.lucene.luke.ui.util;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+import java.util.Comparator;
+
+import org.apache.pivot.collections.Dictionary;
+import org.apache.pivot.wtk.SortDirection;
+import org.apache.pivot.wtk.TableView;
+
+public class TableComparator implements Comparator<FieldsTableRow> {
+  private TableView tableView;
+
+  public TableComparator(TableView fieldsTable) {
+    if (fieldsTable == null) {
+      throw new IllegalArgumentException();
+    }
+
+    this.tableView = fieldsTable;
+  }
+
+  @Override
+  public int compare(FieldsTableRow row1, FieldsTableRow row2) {
+    Dictionary.Pair<String, SortDirection> sort = tableView.getSort().get(0);
+
+    int result;
+    if (sort.key.equals("name")) {
+      // sort by name
+      result = row1.getName().compareTo(row2.getName());
+    } else if (sort.key.equals("termCount")) {
+      // sort by termCount
+      Integer c1 = Integer.parseInt(row1.getTermCount());
+      Integer c2 = Integer.parseInt(row2.getTermCount());
+      result = c1.compareTo(c2);
+    } else {
+      // other (ignored)
+      result = 0;
+    }
+    //int result = o1.get("name").compareTo(o2.get("name"));
+    //SortDirection sortDirection = tableView.getSort().get("name");
+    SortDirection sortDirection = sort.value;
+    result *= (sortDirection == SortDirection.DESCENDING ? 1 : -1);
+
+    return result * -1;
+  }
+}
+
+/*
+public class TableComparator implements Comparator<Map<String,String>> {
+  private TableView tableView;
+  
+  public TableComparator(TableView fieldsTable) {
+    if (fieldsTable == null) {
+      throw new IllegalArgumentException();
+    }
+    
+    this.tableView = fieldsTable;
+  }
+  
+  @Override
+  public int compare(Map<String,String> o1, Map<String,String> o2) {
+    Dictionary.Pair<String, SortDirection> sort = tableView.getSort().get(0);
+
+    int result;
+    if (sort.key.equals("name")) {
+      // sort by name
+      result = o1.get(sort.key).compareTo(o2.get(sort.key));
+    } else if (sort.key.equals("termCount")) {
+      // sort by termCount
+      Integer c1 = Integer.parseInt(o1.get(sort.key));
+      Integer c2 = Integer.parseInt(o2.get(sort.key));
+      result = c1.compareTo(c2);
+    } else {
+      // other (ignored)
+      result = 0;
+    }
+    //int result = o1.get("name").compareTo(o2.get("name"));
+    //SortDirection sortDirection = tableView.getSort().get("name");
+    SortDirection sortDirection = sort.value;
+    result *= (sortDirection == SortDirection.DESCENDING ? 1 : -1);
+
+    return result * -1;
+  }
+  
+}
+*/
