JDK-4652358 : Using value of "line.separator" for line separator in TextArea fails.
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2002-03-13
  • Updated: 2002-09-06
  • Resolved: 2002-09-06
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.2 mantisFixed
Related Reports
Relates :  
Relates :  
Description

Name: gm110360			Date: 03/13/2002


FULL PRODUCT VERSION :
java version "1.4.0-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-rc-b91)
Java HotSpot(TM) Client VM (build 1.4.0-rc-b91, mixed mode)


FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
Using the value of the "line.separator" system property to
separate lines when appending to a TextArea causes the lines
to get all jumbled with the Java 1.4 appletviewer and with
the Java 1.4 Plug-in.  The problem does not occur when using
the appletviewer of Java 1.0.2, Java 1.1.8_008, Java
1.2.2_010, nor Java 1.3.1_02-b02.


REGRESSION.  Last worked in version 1.3.1

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run the sample program below using the appletviewer.
2. Enter multiple lines of text into the text field, each
followed by the Enter key.
3. Look at the corresponding lines in the text area.


EXPECTED VERSUS ACTUAL BEHAVIOR :
If you typed:
  line1
  line2
  line3
you should see the following in the text area:
  line1
  line2
  line3

With Java 1.4, you instead see:
  lin
  lin
  line3e2e1

Note that the first line printed in the text area is the hex
value of the "line.separator" system property.


ERROR MESSAGES/STACK TRACES THAT OCCUR :
None.


This bug can be reproduced always.

---------- BEGIN SOURCE ----------
HTML for appletviewer:
----------------------
<html>
<head>
<title>TextArea Test</title>
</head>
<body>
<h1>TextArea Test</h1>
<applet code="Append.class" width="300" height="300">
</applet>
</body>
</html>

Java 1.0.2 source code:
-----------------------
import java.applet.*;
import java.awt.*;

public class Append extends Applet {
    private static final String LINE_SEPARATOR =
        System.getProperty("line.separator", "\n");
    private static final char[] DIGITS =
        {'0', '1', '2', '3', '4', '5', '6', '7',
         '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
    private static final Font FONT = new Font("Courier", Font.PLAIN, 13);

    private static final int NEW_LINE   = '\n';
    private static final int RETURN     = '\r';
    private static final int ESCAPE_KEY =   27;

    private TextArea  area;
    private TextField field;

    private static String hexEncode(byte[] bytes) {
        StringBuffer buffer = new StringBuffer(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            byte b = bytes[i];
            buffer.append(DIGITS[(b & 0xF0) >> 4]);
            buffer.append(DIGITS[b & 0x0F]);
        }
        return buffer.toString();
    }

    public void init() {
        area  = new TextArea();
        field = new TextField();
        area.setFont(FONT);
        field.setFont(FONT);
        setLayout(new BorderLayout());
        add("Center", area);
        add("South", field);
        byte[] bytes = new byte[LINE_SEPARATOR.length()];
        LINE_SEPARATOR.getBytes(0, bytes.length, bytes, 0);
        area.appendText(hexEncode(bytes));
    }

    public void start() {
        field.requestFocus();
    }

    public boolean keyDown(Event event, int key) {
        boolean handled = false;
        if (event.target == field) {
            String text = field.getText();
            switch (key) {
                case NEW_LINE: case RETURN:
                    // area.appendText("\n" + text);
                    area.appendText(LINE_SEPARATOR + text);
                    field.setText("");
                    handled = true;
                    break;
                case ESCAPE_KEY:
                    field.setText("");
                    handled = true;
                    break;
            }
        }
        return handled;
    }
}

---------- END SOURCE ----------

CUSTOMER WORKAROUND :
Use "\n" for the line separator character, regardless of the
platform.
(Review ID: 139621) 
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mantis FIXED IN: mantis INTEGRATED IN: mantis
2004-06-14

SUGGESTED FIX *** /cygdrive/n/TEMP\geta868 Wed Apr 17 19:32:33 2002 --- awt_TextComponent.cpp Wed Apr 17 19:32:32 2002 *************** *** 81,87 **** /* count newlines */ for (i=0; pStr[i] != 0; i++) { ! if (pStr[i] == L'\n') { nNewlines++; } } --- 81,87 ---- /* count newlines */ for (i=0; pStr[i] != 0; i++) { ! if (pStr[i] == L'\n' && (i == 0 || pStr[i-1] != L'\r')) { nNewlines++; } } *************** *** 95,101 **** nResultIx = nLen + nNewlines; for (i=nLen; i>=0; i--) { result[nResultIx--] = pStr[i]; ! if (pStr[i] == L'\n') { result[nResultIx--] = L'\r'; } } --- 95,101 ---- nResultIx = nLen + nNewlines; for (i=nLen; i>=0; i--) { result[nResultIx--] = pStr[i]; ! if (pStr[i] == L'\n' && (i == 0 || pStr[i-1] != L'\r')) { result[nResultIx--] = L'\r'; } } *************** *** 121,127 **** /* count newlines */ for (i=0; pStr[i] != 0; i++) { ! if (pStr[i] == '\n') { nNewlines++; } } --- 121,127 ---- /* count newlines */ for (i=0; pStr[i] != 0; i++) { ! if (pStr[i] == '\n' && (i == 0 || pStr[i-1] != '\r')) { nNewlines++; } } *************** *** 135,141 **** nResultIx = nLen + nNewlines; for (i=nLen; i>=0; i--) { result[nResultIx--] = pStr[i]; ! if (pStr[i] == '\n') { result[nResultIx--] = '\r'; } } --- 135,141 ---- nResultIx = nLen + nNewlines; for (i=nLen; i>=0; i--) { result[nResultIx--] = pStr[i]; ! if (pStr[i] == '\n' && (i == 0 || pStr[i-1] != '\r')) { result[nResultIx--] = '\r'; } } Name: dkR10074 Date: 08/01/2002 Please see a suggested fix for 4701398. ###@###.### 2002-08-01 ======================================================================
2002-08-01

EVALUATION I ran this with JDK1.4 FCS on Windows NT4 using appletviewer, and was not able to reproduce it. Here is the source code for /src/share/classes/java/awt/TextArea.appendText() It hasn't changed in almost four years. /** * @deprecated As of JDK version 1.1, * replaced by <code>append(String)</code>. */ public synchronized void appendText(String str) { if (peer != null) { insertText(str, getText().length()); } else { text = text + str; } } The peers of the textfield and textarea are not null according to some printlns I added to the test case. AWT TextArea widgets are just standard win32 Rich Edit controls. Note: the line.separator value printed is 0D0A = \r\n. I tried changing the value of LINE_SEPARATOR to "\r\n" and that worked fine as well. ###@###.### 2002-03-13 I tried this on Win2K, and reproduced the failure. Sigh. ###@###.### 2002-03-13 I added some printlns to the test case, and found that the length and caret position are different on win2k vs. winnt. These results are for typing line1 line2 line3 if (event.target == field) { String text = field.getText(); switch (key) { case NEW_LINE: case RETURN: // area.appendText("\n" + text); System.err.println("before length = " + area.getText().length()); System.err.println("before caret = " + area.getCaretPosition()); area.appendText(LINE_SEPARATOR + text); System.err.println("after length = " + area.getText().length()); System.err.println("after caret = " + area.getCaretPosition()); field.setText(""); handled = true; break; Windows_NT before length = 4 before caret = 4 after length = 11 after caret = 11 before length = 11 before caret = 11 after length = 18 after caret = 18 before length = 18 before caret = 18 after length = 25 after caret = 25 before length = 25 before caret = 25 Windows_2000 before length = 4 before caret = 4 after length = 10 after caret = 11 before length = 10 before caret = 11 after length = 16 after caret = 17 before length = 16 before caret = 17 after length = 22 after caret = 23 before length = 22 before caret = 23 I wonder if win2k handles the crlf like win9x does, rather than like winnt? I assume the problem is specific to the rich edit control we are using in 1.4, since it apparently doesn't happen with the common edit control we used in 1.3.1. ###@###.### 2002-03-13 Tested Windows XP with 1.4.1 build 5. It behaves the same as NT, not 2000. So the problem is on Win2K only. ###@###.### 2002-03-14 Name: dmR10075 Date: 04/17/2002 I think the problem is in the AwtTextCompoentn::AddCR method in awt_TextComponent.cpp. If we look at the buffer before AddCR and after AddCR we will see: let's say we add "\r\nline1" then we will see: \r \n l i n e 1 \0 0D 00 0A 00 6C 00 69 00 6E 00 65 00 31 00 00 00 after AddCR we see: \r \r \n l i n e 1 \0 0D 00 0D 00 0A 00 6C 00 69 00 6E 00 65 00 31 00 00 00 so, it adds one additional \r. The code in AddCR looks only for presense of \n when it decides whether or not it is line separator. But it doesn't ensure that it is already correctly (in Win32 terms) formatted line separator. From one side, it is ok - line separator for strings inside of java is unicode '\n' so we could expect that we will receive text only with '\n's. But it will be convenient to allow user to use '\r\n' as line separator as well. I suggest this as the fix for this bug, see Suggested fix section for diffs. ###@###.### 2002-04-17 ====================================================================== Name: dkR10074 Date: 08/01/2002 Please see an evaluation for 4701398. ###@###.### 2002-08-01 ======================================================================
2002-08-01