001package org.vishia.commander;
002
003import java.io.BufferedReader;
004import java.io.ByteArrayInputStream;
005import java.io.File;
006import java.io.IOException;
007import java.io.InputStream;
008import java.io.InputStreamReader;
009import java.nio.ByteBuffer;
010import java.nio.CharBuffer;
011import java.nio.channels.ReadableByteChannel;
012import java.nio.channels.WritableByteChannel;
013import java.nio.charset.Charset;
014
015import org.vishia.fileRemote.FileRemote;
016import org.vishia.gral.base.GralTextBox;
017import org.vishia.gral.base.GralWidget;
018import org.vishia.gral.base.GralWindow;
019import org.vishia.gral.ifc.GralColor;
020import org.vishia.gral.ifc.GralUserAction;
021import org.vishia.gral.ifc.GralWindow_ifc;
022import org.vishia.util.KeyCode;
023import org.vishia.util.StringFormatter;
024
025/**All functionality of view (F3-Key) and quick view.
026 * @deprecated. The {@link FcmdView} have more capabilities. It contains adequates. 
027 * @author Hartmut Schorrig
028 * */
029public class FcmdEdit
030{
031  protected final Fcmd main;
032
033  /**The window of this functionallity. */
034  private GralWindow_ifc windView;
035
036  /**The widget to show content. */
037  private GralTextBox widgContent;
038  
039  /**A buffer to get bytes from the file using the java.nio.Channel mechanism. 
040   * The channel mechanism is proper to work with remote file access especially.
041   * Note: The ByteBuffer may be a part of the channel mechanism itself, because it is placed JVM-internally,
042   * for example for socket communication. TODO check and change it.
043   */
044  private final ByteBuffer byteBuffer = ByteBuffer.allocate(1200);
045
046  /**Number of read bytes. */
047  private int nrofBytes;
048
049
050  /**The gotten bytes from bytebuffer. */
051  private byte[] buffer = new byte[1200];
052  
053  
054  //private byte[] outBuffer = new byte[20000];
055  
056  /**The current choiced view format.
057   * <ul>
058   * <li>a: us-ascii-text
059   * <li>w: iso (Windows)-text
060   * <li>u: UTF16-text
061   * <li>1: Hexa byte wise
062   * <li>2: Hexa 16-bit-words
063   * <li>4: Hexa 32-bit-words
064   * <li>F: contains, float values, shows it
065   * </ul>  
066   */
067  private final char format = 't';
068  
069  
070  private static Charset ascii7 = Charset.forName("US-ASCII");
071  
072  private static Charset utf8 = Charset.forName("UTF8");
073  
074  
075  /**Instance to prepare the text especially for hex view. */
076  private final StringFormatter formatterHex = new StringFormatter(120);
077  
078  public FcmdEdit(Fcmd main)
079  { this.main = main;
080  }
081  
082  
083  /**Builds the content of the confirm-delete window. The window is created static. It is shown
084   * whenever it is used.  */
085  void buildWindow()
086  {
087    main._gralMng.selectPanel("primaryWindow");
088    main._gralMng.setPosition(10, 0, 10, 0, 1, 'r'); //right buttom, about half less display width and hight.
089    int windProps = GralWindow.windConcurrently | GralWindow.windHasMenu;
090    GralWindow wind =  main._gralMng.createWindow("windView", "view - The.file.Commander", windProps);
091    wind.addMenuBarItemGThread("view-Search", "&Edit/&Search", actionOpenEdit);
092    wind.addMenuBarItemGThread("view-Search", "&Edit/set &Writeable", actionOpenEdit);
093    wind.addMenuBarItemGThread("view-Search", "&View/&Hex-Byte", actionOpenEdit);
094    wind.addMenuBarItemGThread("view-Search", "&View/text-&Windows", actionOpenEdit);
095    wind.addMenuBarItemGThread("view-Search", "&View/text-&UTF", actionOpenEdit);
096    wind.addMenuBarItemGThread("view-Search", "&View/text-&ASCII-7", actionOpenEdit);
097    wind.addMenuBarItemGThread("view-Search", "&View/text-&Encoding", actionOpenEdit);
098    wind.addMenuBarItemGThread(null, "&Save-as/UTF8-Unix-lf", actionConvertUTF8unix);
099    main._gralMng.setPosition(0, 0, 0, 0, 1, 'r');
100    widgContent = main._gralMng.addTextBox("view-content", false, null, '.');
101    widgContent.setTextStyle(GralColor.getColor("bk"), main._gralMng.propertiesGui.getTextFont(2.0f, 'm', 'n'));
102    windView = wind; 
103    windView.setWindowVisible(false);
104    //windView1.
105  }
106
107  
108  
109  
110  /**Opens the view window and fills its content.
111   * @param src The path which is selected as source. It may be a directory or a file.
112   */
113  void openEdit(FileRemote src)
114  {if(src !=null){
115      long len = src.length();
116      if(len > 1000000){ len = 1000000; } //nor more than 1MByte, 
117      buffer = new byte[(int)len];
118      int iBuffer = 0;
119      ReadableByteChannel reader = src.openRead(0);
120      try{
121        if(reader == null){
122          widgContent.setText("File is not able to read:\n");
123          widgContent.append(src.getAbsolutePath());
124        } else {
125          do{
126            byteBuffer.clear();
127            nrofBytes = reader.read(byteBuffer);
128            if(nrofBytes >0){
129              byteBuffer.rewind();
130              byteBuffer.get(buffer, iBuffer, nrofBytes);
131              iBuffer += nrofBytes;
132            }
133          } while(nrofBytes >0);
134          reader.close();
135          //byteBuffer.rewind();
136          presentContent();
137        }
138      } catch(IOException exc){
139        if(reader !=null) { try{ reader.close(); } catch(IOException exc1){}}        
140      }
141    }
142    windView.setFocus(); //WindowVisible(true);
143
144  }
145  
146
147  
148  
149  void presentContent() throws IOException
150  {
151    widgContent.setText("file ...\n");
152    presentContentHex();  
153  }
154  
155  
156  
157  void presentContentHex() throws IOException
158  {
159    try{
160      //byteBuffer.get(buffer);
161      for(int ii = 0; ii < 16 && ii < buffer.length /16; ++ii){
162        formatterHex.reset();
163        formatterHex.addHex(ii, 4).add(": ");
164        formatterHex.addHexLine(buffer, 16*ii, 16, StringFormatter.k1);
165        formatterHex.add("  ").addStringLine(buffer, 16*ii, 16, ascii7.name());
166        widgContent.append(formatterHex.getContent()).append('\n');
167      }
168    } catch(Exception exc){
169      widgContent.append(exc.getMessage());
170    }
171  }
172  
173  
174  
175  void presentContentText() throws IOException
176  {
177    
178    CharBuffer tContent = ascii7.decode(byteBuffer);
179    try{
180      do{
181        char cc = tContent.get();
182        widgContent.append(cc);
183      } while(true);
184    } catch(Exception exc){
185      widgContent.append('?');
186    }
187  }
188  
189  
190  /**Action for Key F3 for view command. Its like Norton Commander.
191   */
192  GralUserAction actionOpenEdit = new GralUserAction("actionOpenEdit")
193  {
194    @Override public boolean userActionGui(int key, GralWidget infos, Object... params)
195    { if(key == KeyCode.mouse1Up || key == KeyCode.menuEntered){
196        openEdit(main.currentFile());
197        return true;
198      } else return false; 
199      // /
200    }
201  };
202
203
204  GralUserAction actionConvertUTF8unix = new GralUserAction("actionConvertUTF8unix")
205  {
206    @Override public boolean userActionGui(int keyCode, GralWidget infos, Object... params)
207    { 
208      try{
209        InputStream inpBytes = new ByteArrayInputStream(buffer);
210        InputStreamReader inpText = new InputStreamReader(inpBytes);
211        BufferedReader inpLines = new BufferedReader(inpText);
212        FileRemote filedst = main.currentFile();
213        WritableByteChannel outchn =filedst.openWrite(0);
214        ByteBuffer outBuffer = ByteBuffer.allocate(1200);
215        //Writer out = new FileWriter();
216        String sLine;
217        do{
218          sLine = inpLines.readLine();
219          if(sLine !=null){
220            byte[] bytes = sLine.getBytes(utf8);
221            if(outBuffer.remaining() < bytes.length+1){
222              outBuffer.rewind();
223              outchn.write(outBuffer);
224              outBuffer.clear();  
225            }
226            int posBytes = 0;
227            int zOutBuffer;
228            while( (zOutBuffer = outBuffer.remaining()) < (bytes.length - posBytes +1)){
229              outBuffer.put(bytes, posBytes, zOutBuffer);
230              outBuffer.rewind();
231              outchn.write(outBuffer);
232              outBuffer.clear();
233              posBytes += zOutBuffer; 
234            }
235            outBuffer.put(bytes, posBytes, bytes.length - posBytes)
236                     .put((byte)0x0a);
237            //outText.append(sLine).append('\n');
238          }
239        } while(sLine !=null);
240        outBuffer.rewind();
241        outchn.write(outBuffer);
242        outBuffer.clear(); 
243        outchn.close();
244        
245      } catch(Exception exc){
246        main._gralMng.writeLog(0, exc);
247      }
248      return true;
249      // /
250    }
251  };
252
253
254  
255}