Optimized Scanner
[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         private GC fGC;
22         private int fMaxWidth;
23         
24         private String fLine;
25         private int fOffset;
26         
27         private BreakIterator fLineBreakIterator;
28
29         /**
30          * Creates a reader that breaks an input text to fit in a given width.
31          * @param reader Reader of the input text
32          * @param gc The graphic context that defines the currently used font sizes
33          * @param maxLineWidth The max width (pixes) where the text has to fit in 
34          */
35         public LineBreakingReader(Reader reader, GC gc, int maxLineWidth) {
36                 fReader= new BufferedReader(reader);
37                 fGC= gc;
38                 fMaxWidth= maxLineWidth;
39                 fOffset= 0;
40                 fLine= null;
41                 fLineBreakIterator= BreakIterator.getLineInstance();
42         }
43         
44         public boolean isFormattedLine() {
45                 return fLine != null;
46         }
47         
48         /**
49          * Reads the next line. The lengths of the line will not exceed the gived maximum
50          * width.
51          */
52         public String readLine() throws IOException {
53                 if (fLine == null) {
54                         String line= fReader.readLine();
55                         if (line == null)
56                                 return null;
57                                                                 
58                         int lineLen= fGC.textExtent(line).x;
59                         if (lineLen < fMaxWidth) {
60                                 return line;
61                         }
62                         fLine= line;
63                         fLineBreakIterator.setText(line);
64                         fOffset= 0;
65                 }
66                 int breakOffset= findNextBreakOffset(fOffset);
67                 String res;
68                 if (breakOffset != BreakIterator.DONE) {
69                         res= fLine.substring(fOffset, breakOffset);
70                         fOffset= findWordBegin(breakOffset);
71                         if (fOffset == fLine.length()) {
72                                 fLine= null;
73                         }
74                 } else {
75                         res= fLine.substring(fOffset);
76                         fLine= null;
77                 }
78                 return res;
79         }
80         
81         private int findNextBreakOffset(int currOffset) {
82                 int currWidth= 0;
83                 int nextOffset= fLineBreakIterator.following(currOffset);
84                 while (nextOffset != BreakIterator.DONE) {
85                         String word= fLine.substring(currOffset, nextOffset);
86                         int wordWidth= fGC.textExtent(word).x;
87                         int nextWidth= wordWidth + currWidth;
88                         if (nextWidth > fMaxWidth) {
89                                 if (currWidth > 0) {
90                                         return currOffset;
91                                 } else {
92                                         return nextOffset;
93                                 }
94                         }
95                         currWidth= nextWidth;
96                         currOffset= nextOffset;
97                         nextOffset= fLineBreakIterator.next();
98                 }
99                 return nextOffset;
100         }
101         
102         private int findWordBegin(int idx) {
103                 while (idx < fLine.length() && Character.isWhitespace(fLine.charAt(idx))) {
104                         idx++;
105                 }
106                 return idx;
107         }       
108 }