United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4652358 Using value of "line.separator" for line separator in TextArea fails.
JDK-4652358 : Using value of "line.separator" for line separator in TextArea fails.

Details
Type:
Bug
Submit Date:
2002-03-13
Status:
Resolved
Updated Date:
2002-09-06
Project Name:
JDK
Resolved Date:
2002-09-06
Component:
client-libs
OS:
windows_2000
Sub-Component:
java.awt
CPU:
x86
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.4.0
Fixed Versions:
1.4.2 (mantis)

Related Reports
Relates:
Relates:

Sub Tasks

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
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
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
mantis

FIXED IN:
mantis

INTEGRATED IN:
mantis


                                     
2004-06-14



Hardware and Software, Engineered to Work Together