Workaround for feature request #1154254 (sticky browser URL) that solves bug #1827766...
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / text / LineBreakingReader.java
1 package net.sourceforge.phpdt.internal.ui.text;
2
3 /*
4  * (c) Copyright IBM Corp. 2000, 2001.
5  * All Rights Reserved.
6  */
7
8 import java.io.BufferedReader;
9 import java.io.IOException;
10 import java.io.Reader;
11 import java.text.BreakIterator;
12
13 import org.eclipse.swt.graphics.GC;
14
15 /*
16  * Not a real reader. Could change if requested
17  */
18 public class LineBreakingReader {
19
20         private BufferedReader fReader;
21
22         private GC fGC;
23
24         private int fMaxWidth;
25
26         private String fLine;
27
28         private int fOffset;
29
30         private BreakIterator fLineBreakIterator;
31
32         /**
33          * Creates a reader that breaks an input text to fit in a given width.
34          * 
35          * @param reader
36          *            Reader of the input text
37          * @param gc
38          *            The graphic context that defines the currently used font sizes
39          * @param maxLineWidth
40          *            The max width (pixes) where the text has to fit in
41          */
42         public LineBreakingReader(Reader reader, GC gc, int maxLineWidth) {
43                 fReader = new BufferedReader(reader);
44                 fGC = gc;
45                 fMaxWidth = maxLineWidth;
46                 fOffset = 0;
47                 fLine = null;
48                 fLineBreakIterator = BreakIterator.getLineInstance();
49         }
50
51         public boolean isFormattedLine() {
52                 return fLine != null;
53         }
54
55         /**
56          * Reads the next line. The lengths of the line will not exceed the gived
57          * maximum width.
58          */
59         public String readLine() throws IOException {
60                 if (fLine == null) {
61                         String line = fReader.readLine();
62                         if (line == null)
63                                 return null;
64
65                         int lineLen = fGC.textExtent(line).x;
66                         if (lineLen < fMaxWidth) {
67                                 return line;
68                         }
69                         fLine = line;
70                         fLineBreakIterator.setText(line);
71                         fOffset = 0;
72                 }
73                 int breakOffset = findNextBreakOffset(fOffset);
74                 String res;
75                 if (breakOffset != BreakIterator.DONE) {
76                         res = fLine.substring(fOffset, breakOffset);
77                         fOffset = findWordBegin(breakOffset);
78                         if (fOffset == fLine.length()) {
79                                 fLine = null;
80                         }
81                 } else {
82                         res = fLine.substring(fOffset);
83                         fLine = null;
84                 }
85                 return res;
86         }
87
88         private int findNextBreakOffset(int currOffset) {
89                 int currWidth = 0;
90                 int nextOffset = fLineBreakIterator.following(currOffset);
91                 while (nextOffset != BreakIterator.DONE) {
92                         String word = fLine.substring(currOffset, nextOffset);
93                         int wordWidth = fGC.textExtent(word).x;
94                         int nextWidth = wordWidth + currWidth;
95                         if (nextWidth > fMaxWidth) {
96                                 if (currWidth > 0) {
97                                         return currOffset;
98                                 } else {
99                                         return nextOffset;
100                                 }
101                         }
102                         currWidth = nextWidth;
103                         currOffset = nextOffset;
104                         nextOffset = fLineBreakIterator.next();
105                 }
106                 return nextOffset;
107         }
108
109         private int findWordBegin(int idx) {
110                 while (idx < fLine.length()
111                                 && Character.isWhitespace(fLine.charAt(idx))) {
112                         idx++;
113                 }
114                 return idx;
115         }
116 }