import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; class Edit extends JComponent { Datei file; int pos, subpos, modus; int ueberschreiben=1; int breite, hoehe, proZeile, luecke, anzahl; String searchString=""; int searchPos = -1; BMPHexEditor parent; class myKeyListener implements KeyListener { public void keyPressed( KeyEvent k ) { int iHeight = getSize().height; if (k.getKeyCode()==8) delete(-1); if (k.getKeyCode()==127) delete(0); if (k.getKeyCode()==37) movePos(-1); if (k.getKeyCode()==39) movePos(1); if (k.getKeyCode()==38) movePos(-proZeile); if (k.getKeyCode()==40) movePos(proZeile); if (k.getKeyCode()==33) movePos(-proZeile*(iHeight/hoehe)); if (k.getKeyCode()==34) movePos(proZeile*(iHeight/hoehe)); } public void keyReleased(KeyEvent k){} public void keyTyped(KeyEvent k){ // System.out.println( "Typed:"+k.getKeyCode()+"|"+k.getKeyChar() ); switch(modus) { case 1: { if (k.getKeyChar()>='0' && k.getKeyChar()<='1') modifyByte(k.getKeyChar()); break; } case 2: { if (k.getKeyChar()>='0' && k.getKeyChar()<='9') modifyByte(k.getKeyChar()); if (k.getKeyChar()>='a' && k.getKeyChar()<='f') modifyByte(k.getKeyChar()); if (k.getKeyChar()>='A' && k.getKeyChar()<='F') modifyByte(k.getKeyChar()); break; } default: { if (k.getKeyCode()!= 127) modifyByte(k.getKeyChar()); } } } } class myMouseListener implements MouseListener { public void mouseClicked( MouseEvent m ) { moveToMousePos(m.getX(),m.getY() ); } public void mouseExited(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mousePressed(MouseEvent e) { // System.out.println("Test"); } public void mouseReleased(MouseEvent e) { } } public Edit(BMPHexEditor p){ super(); parent = p; file = null; pos = 0; subpos = 0; addKeyListener(new myKeyListener()); addMouseListener(new myMouseListener()); modus = 1; } public void adjustTextMetrics() { int iWidth = getSize().width; int iHeight = getSize().height; Graphics g = getGraphics(); g.setFont(new Font("Monospaced",Font.PLAIN,12)); FontMetrics fm = g.getFontMetrics( g.getFont() ); hoehe = fm.getHeight(); switch (modus) { case 1: breite = fm.stringWidth("01010101")+4; luecke = 4; anzahl = 8; break; case 2: breite = fm.stringWidth("FF")+4; luecke = 4; anzahl = 2; break; default : breite = fm.stringWidth("F"); luecke = 0; anzahl = 1; } proZeile = iWidth / breite; } public void paint(Graphics g){ String s; int iWidth = getSize().width; int iHeight = getSize().height; Rectangle r = getVisibleRect(); adjustTextMetrics(); g.setFont(new Font("Monospaced",Font.PLAIN,12)); g.setColor( Color.black ); int zeile, spalte; if (file != null) { // BMP-Bild interpretieren String info; int bilddaten = file.getDWORD(10); int bbreite = file.getDWORD(18); int bhoehe = file.getDWORD(22); int farbtiefe = file.getWORD(28); int compression = 0; int min = 0; int max = -1; int xx = -1; int yy = -1; switch (pos) { case 0: case 1: info = "Byte 1+2 immer 'BM' zur Kennzeichnung eines BMP-Bildes"; min = 0; max = 1; break; case 2: case 3: case 4: case 5: int i = file.getDWORD(2); info = "Byte 3-6 Dateigröße: "+i+" Bytes (unsicher)"; min = 2; max = 5; break; case 6: case 7: case 8: case 9: info = "Byte 7-10 reservierte Bytes (keine Bedeutung)"; min = 6; max = 9; break; case 10: case 11: case 12: case 13: info = "Byte 11-14 Bilddaten beginnen bei Byte Nr. "+bilddaten; min = 10; max = 13; break; case 14: case 15: case 16: case 17: i = file.getDWORD(14); info = "Byte 15-18 Größe des Headers: "+i+" Byte"; min = 14; max = 17; break; case 18: case 19: case 20: case 21: info = "Byte 19-22 Breite des Bildes: "+bbreite+" Pixel"; min = 18; max = 21; break; case 22: case 23: case 24: case 25: if (bhoehe<0) { info = "Byte 23-26 Höhe des Bildes: "+(-bhoehe)+" Pixel und Top-Down-Bitmap"; } else { info = "Byte 23-26 Höhe des Bildes: "+bhoehe+" Pixel und Bottum-Up-Bitmap"; } min = 22; max = 25; break; case 28: case 29: if (farbtiefe<=8) { info = "Byte 29+30: Farbtiefe "+farbtiefe+" Bit pro Pixel mit Farbpalette"; } else { info = "Byte 29+30: Farbtiefe "+farbtiefe+" Bit pro Pixel ohne Farbpalette"; } min = 28; max = 29; break; case 30: case 31: case 32: case 33: compression = file.getDWORD(30); if (compression == 0) { info = "Byte 31-34: Komprimierung: Die Bilddaten sind unkomprimiert"; } else { info = "Byte 31-34: Komprimierung: Die Bilddaten sind RunLength komprimiert"; } min = 30; max = 33; break; case 34: case 35: case 36: case 37: i = file.getDWORD(34); info = "Byte 35-38 Größe der Bilddaten: "+i+" Byte (kann auch 0 sein)"; min = 34; max = 37; break; case 38: case 39: case 40: case 41: i = file.getDWORD(38); info = "Byte 39-42 Horizontale Auflösung "+i+" Pixel pro Meter (meist 0 gesetzt)"; min = 38; max = 41; break; case 42: case 43: case 44: case 45: i = file.getDWORD(42); info = "Byte 43-46 Vertikale Auflösung "+i+" Pixel pro Meter (meist 0 gesetzt)"; min = 42; max = 45; break; case 46: case 47: case 48: case 49: i = file.getDWORD(38); info = "Byte 47-50 Anzahl der Farben in der Palette "+i+" (0 = maximale Anzahl)"; min = 46; max = 49; break; case 50: case 51: case 52: case 53: i = file.getDWORD(38); info = "Byte 51-54 Anzahl der benutzten Farben im Bild "+i+" (0 = alle Farben)"; min = 50; max = 53; break; default: info = "sonstige Daten"; if (pos >= 54 && pos < bilddaten) { min = max = pos; min = min -(pos-54) % 4; max = max + 3-(pos-54) % 4; info = "Byte "+(pos+1)+" Farbe Nr. "+(pos-54)/4+" der Palette "; if ((pos-54) % 4==0) { info = info + " (Blauanteil)"; } if ((pos-54) % 4==1) { info = info + " (Grünanteil)"; } if ((pos-54) % 4==2) { info = info + " (Rotanteil)"; } if ((pos-54) % 4==3) { info = info + " (immer 0)"; } } if (pos >= bilddaten) { min = max = pos; // immer auf 4 Byte mit Nullen aufgefüllt int bbreite_angepasst = bbreite*farbtiefe/8+3; bbreite_angepasst = bbreite_angepasst - bbreite_angepasst % 4; yy = (pos-bilddaten) / bbreite_angepasst +1; int pos_in_zeile = ((pos-bilddaten) - (yy-1)*bbreite_angepasst); xx = pos_in_zeile*8 / farbtiefe +1; if (bhoehe > 0) { yy = bhoehe - yy +1; } if (farbtiefe == 1) { info = "Byte "+(pos+1)+" Farbenummer des Pixels an Pos ("+xx+"/"+yy+") und der nächsten 7 Pixel"; } if (farbtiefe == 2) { info = "Byte "+(pos+1)+" Farbenummer des Pixels an Pos ("+xx+"/"+yy+") und der nächsten 3 Pixel"; } if (farbtiefe == 4) { info = "Byte "+(pos+1)+" Farbnummer des Pixels an Pos ("+xx+"/"+yy+") und des nächsten Pixels"; } if (farbtiefe == 8) { info = "Byte "+(pos+1)+" Farbnummer des Pixels an Pos ("+xx+"/"+yy+")"; } if (farbtiefe > 8) { info = "Byte "+(pos+1)+" Farbe des Pixels an Pos ("+xx+"/"+yy+")"; if ((pos_in_zeile) % 3==0) { info = info + " (Blauanteil)"; } if ((pos_in_zeile) % 3==1) { info = info + " (Grünanteil)"; } if ((pos_in_zeile) % 3==2) { info = info + " (Rotanteil)"; } min = min -(pos_in_zeile) % 3; max = max + 2-(pos_in_zeile) % 3; } if (xx > bbreite) { // Dummybytes info = "Byte "+(pos+1)+" keine Bedeutung"; min = max = pos; } parent.posChanged(xx,yy); } } int laenge = file.getLength(); zeile = 0; spalte = 0; int start = (int)(r.getY() / hoehe) * proZeile; int ende = ((int) ((r.getY()+r.getHeight()) / hoehe)+1)*proZeile; zeile = (int) (r.getY() / hoehe); spalte = 0; for (int i=start; i=min && i<=max) { g.setColor( Color.lightGray); g.fillRect((spalte)*breite+luecke/2,4+(zeile)*hoehe,breite-luecke/2-1,hoehe); g.setColor( Color.black); } if (i==pos) { g.setColor( Color.yellow); g.fillRect((spalte)*breite+luecke/2,4+(zeile)*hoehe,breite-luecke/2-1,hoehe); if (subpos != 0) { g.setColor( Color.red); g.fillRect((spalte)*breite+subpos*(breite-luecke)/anzahl+luecke/2,4+(zeile)*hoehe,(breite-luecke/2)/anzahl-1,hoehe); } g.setColor( Color.black); } switch (modus) { case 1: s = file.getByteBinary(i); break; case 2: s = file.getByteHex(i); break; default : s = file.getByteChar(i); } g.drawString(s,(spalte)*breite+luecke/2,hoehe+(zeile)*hoehe); spalte++; if (spalte >= proZeile) { zeile++; spalte = 0; } } if (pos leeres Rechteck zeichnen g.setColor( Color.lightGray); g.fillRect((spalte)*breite+luecke/2,4+(zeile)*hoehe,breite-luecke/2-1,hoehe); g.setColor( Color.black); } parent.showLabels(file.getByteBinary(pos), file.getByteHex(pos), file.getByteChar(pos),info); } } public void setDatei(Datei file) { this.file = file; pos = 0; subpos = 0; } public Datei getDatei(){ return file; } public Dimension getPreferredSize() { adjustTextMetrics(); if (file == null) { return new Dimension( 300, 200 ); } else { int laenge = file.getLength(); int komponentenhoehe = hoehe+(laenge/proZeile)*hoehe+5; if (komponentenhoehe < 200) { komponentenhoehe = 200; } return new Dimension( 300, komponentenhoehe); } } public Dimension getMinimumSize() { return getPreferredSize(); } public void setMode( int i) { modus = i; subpos = 0; repaint(); } public void setUeberschreiben(int i) { ueberschreiben = i; } public int getUeberschreiben() { return ueberschreiben; } public void movePos ( int i ){ if (file!=null) { subpos = 0; pos += i; if (pos < 0) pos = 0; if (pos > file.getLength()) pos = file.getLength(); repaint(); } } public void moveToMousePos(int x, int y) { if (file!=null) { pos = (y / hoehe)*proZeile + (x / breite); subpos = 0; if (pos < 0) pos = 0; if (pos > file.getLength()) pos = file.getLength(); repaint(); } } public void moveToPos(int x, int y) { int bilddaten = file.getDWORD(10); int bbreite = file.getDWORD(18); int bhoehe = file.getDWORD(22); int farbtiefe = file.getWORD(28); if (bhoehe > 0) { pos = (bhoehe - y)*bbreite +x-1; } else { pos = (y-1)*bbreite + x-1; } pos = pos * farbtiefe / 8; pos += bilddaten; parent.scrollTo(0, pos / proZeile * hoehe - 100); repaint(); } public int compare(File vergleichDatei) { int gefunden = -1; if (file!=null) { gefunden = file.compare(vergleichDatei); } repaint(); return gefunden; } public int search(String s) { int gefunden = -1; if (file!=null) { String s2=""; char b; for (int i = 0; i < s.length(); i++) { b = s.charAt(i); if (modus==1 && (b == '0' || b == '1')) s2 = s2 + b; if (modus==2 && ((b >= '0' && b <= '9')|| (b>='A' && b <='F') || (b>='a' && b<='f'))) s2 = s2+b; if (modus==3) s2 = s2+b; } if (modus==2) s2 = s2.toUpperCase(); if (s2.length()>0) gefunden = file.search(s2,modus); } repaint(); return gefunden; } public void delete( int i) { if (file != null && pos+i>0 && pos+i file.getLength()) pos--; } repaint(); } public void modifyByte( char c ) { String s; if (file != null) { if (pos == file.getLength() || (subpos == 0 && !(ueberschreiben==1))) file.insertByte(pos); switch (modus) { case 1: s = file.getByteBinary(pos); break; case 2: s = file.getByteHex(pos); break; default : s = file.getByteChar(pos); } s = s.substring(0,subpos)+c+s.substring(subpos+1); subpos++; int maxSubpos; switch (modus) { case 1: maxSubpos = 7; file.setByteBinary(pos,s); break; case 2: maxSubpos = 1; file.setByteHex(pos,s); break; default : maxSubpos = 0; file.setByteChar(pos,c); } if (subpos > maxSubpos) { subpos = 0; movePos(1); } repaint(); parent.fileChanged(); } } public void keyPressed ( KeyEvent e){ } public void keyReleased ( KeyEvent e ){ } public boolean isFocusable() { return true; } }