Lines 29-34
Link Here
|
29 |
import javax.swing.*; |
29 |
import javax.swing.*; |
30 |
import javax.accessibility.*; |
30 |
import javax.accessibility.*; |
31 |
|
31 |
|
|
|
32 |
import java.awt.font.*; |
33 |
import java.awt.geom.Point2D; |
34 |
|
32 |
import java.util.HashSet; |
35 |
import java.util.HashSet; |
33 |
import java.util.Date; |
36 |
import java.util.Date; |
34 |
import java.util.LinkedList; |
37 |
import java.util.LinkedList; |
Lines 48-83
Link Here
|
48 |
<li>History buffer. |
51 |
<li>History buffer. |
49 |
<li>Support for nested pickable regions in order to support hyperlinked |
52 |
<li>Support for nested pickable regions in order to support hyperlinked |
50 |
views or more complex active text utilities. |
53 |
views or more complex active text utilities. |
|
|
54 |
<li>Support for double-width Oriental characters. |
51 |
</ul> |
55 |
</ul> |
52 |
<p> |
56 |
<p> |
53 |
<h2>Coordinate systems</h2> |
57 |
<h2>Coordinate systems</h2> |
54 |
Two coordinate systems are used with Term. They are both cartesian and |
58 |
The following coordinate systems are used with Term. |
55 |
have their origin at the top left. But they differ in all other respects: |
59 |
They are all cartesian and have their origin at the top left. |
|
|
60 |
All but the first are 0-origin. |
61 |
But they differ in all other respects: |
56 |
<dl> |
62 |
<dl> |
57 |
<dt>Screen coordinates |
63 |
|
|
|
64 |
<dt>ANSI Screen coordinates |
58 |
<dd> |
65 |
<dd> |
59 |
Address only the visible portion of the screen. |
66 |
Address only the visible portion of the screen. |
60 |
They are 1-origin and extend thru the width and height of the visible |
67 |
They are 1-origin and extend thru the width and height of the visible |
61 |
portion of the screen per getColumns() and getRows(). |
68 |
portion of the screen per getColumns() and getRows(). |
62 |
<p> |
69 |
<p> |
63 |
This coordinate system is used mostly by the screen Interp classes and |
70 |
This is how an application (like 'vi' etc) views the screen. |
64 |
Ops. |
71 |
This coordinate system primarily comes into play in the cursor addressing |
|
|
72 |
directive, op_cm() and otherwise is not really used in the implementation. |
73 |
<p> |
74 |
|
75 |
<dt>Cell coordinates |
76 |
<dd> |
77 |
Each character usually takes one cell, and all placement on the screen |
78 |
is in terms of a grid of cells getColumns() wide This cellular nature |
79 |
is why fixed font is "required". In some locales some characters may |
80 |
be double-width. |
81 |
Japanese characters are like this, so they take up two cells. |
82 |
There are no double-height characters (that I know of). |
83 |
<p> |
84 |
Cursor motion is in cell coordinates, so to move past a Japanese character |
85 |
you need the cursor to move right twice. A cursor can also be placed on |
86 |
the second cell of a double-width character. |
87 |
<p> |
88 |
Note that this is strictly an internal coordinate system. For example |
89 |
Term.getCursorCol() and getCursorCoord() return buffer coordinates. |
90 |
<p> |
91 |
The main purpose of this coordinate system is to capture columns. |
92 |
In the vertical direction sometimes it extends only the height of the |
93 |
screen and sometimes the height of the buffer. |
65 |
<p> |
94 |
<p> |
66 |
<dt>Buffer coordinates |
95 |
|
|
|
96 |
<dt>Buffer coordinates ... |
67 |
<dd> |
97 |
<dd> |
68 |
Address the whole history buffer. |
98 |
... address the whole history character buffer. |
69 |
These are 0-origin and extend thru the width |
99 |
These are 0-origin and extend thru the width |
70 |
of the screen per getColumns() and the whole history (for which |
100 |
of the screen per getColumns(), or more if horizontal scrolling is |
71 |
there is no property yet. getHistorySize() isn't it). |
101 |
enabled, and the whole history (that's getHistorySize()+getRows()). |
72 |
<p> |
102 |
<p> |
73 |
The Coord class captures the value of such coordinates. |
103 |
The BCoord class captures the value of such coordinates. |
74 |
It is more akin to the 'int offset' used in the Java text package |
104 |
It is more akin to the 'int offset' used in the Java text package |
75 |
as opposed to javax.swing.text.Position. |
105 |
as opposed to javax.swing.text.Position. |
|
|
106 |
<p> |
107 |
If there are no double-width characters the buffer coords pretty much |
108 |
overlap with cell coords. If double-width characters are added then |
109 |
the buffer column and cell column will have a larger skew the more right |
110 |
you go. |
111 |
<p> |
112 |
<dt>Absolute coordinates ... |
113 |
<dd> |
114 |
... are like Buffer coordinates in the horizontal direction. |
115 |
In the vertical direction their origin is the first line that was |
116 |
sent to the terminal. This line might have scrolled out of history and |
117 |
might no longer be in the buffer. In effect each line ever printed by |
118 |
Term gets a unique Absolute row. |
76 |
<p> |
119 |
<p> |
77 |
Most, but not all, of the methods against Term and friends use the |
120 |
What good is this? The ActiveRegion mechanism maintains coordinates |
78 |
buffer coordinate system, but it hasn't all yet been regularized |
121 |
for its' boundaries. As text scrolls out of history buffer row coordinates |
79 |
so keep an eye out for unexpected use of screen coordinates. |
122 |
have to shift and all ActiveRegions' coords need to be relocated. This |
80 |
|
123 |
can get expensive because as soon as the history buffer becomes full |
|
|
124 |
each newline will require a relocation. This is the approach that |
125 |
javax.swing.text.Position implements and it's justified there because |
126 |
no Swing component has a "history buffer". |
127 |
However, if you use absolute coordinates you'll never have to |
128 |
relocate anything! Simple and effective. |
129 |
<p> |
130 |
Well almost. What happens when you reach Integer.MAX_VALUE? You wrap and |
131 |
that can confuse everything. What are the chances of this happening? |
132 |
Suppose term can process 4000 lines per second. A runaway process will |
133 |
produce Integer.MAX_VALUE lines in about 4 days. That's too close |
134 |
for comfort, so Term does detect the wrap and only then goes and |
135 |
relocates stuff. This, however, causes a secondary problem with |
136 |
testability since no-one wants to wait 4 days for a single wrap. |
137 |
So what I've done is periodically set Term.modulo to something |
138 |
smaller and tested stuff. |
139 |
<p> |
140 |
I'm indebted to Alan Kostinsky for this bit of lateral thinking. |
81 |
</dl> |
141 |
</dl> |
82 |
|
142 |
|
83 |
|
143 |
|
Lines 110-118
Link Here
|
110 |
This is the primary facility that XTerm and other derivatives provide. The |
170 |
This is the primary facility that XTerm and other derivatives provide. The |
111 |
screen has a history buffer in the vertical dimension. |
171 |
screen has a history buffer in the vertical dimension. |
112 |
<p> |
172 |
<p> |
113 |
Buffer coordinates play a role in this mode and it it crucial to |
173 |
Because of limited history active regions can scroll out of history and |
114 |
remember that as the contents of the buffer scrolls and old |
174 |
while the coordinate invalidation problem is not addressed by absolute |
115 |
lines wink out of history coordinates become invalidated. |
175 |
coordiantes sometimes we don't want stuff to wink out. |
116 |
<br> |
176 |
<br> |
117 |
Which is why we have ... |
177 |
Which is why we have ... |
118 |
|
178 |
|
Lines 120-129
Link Here
|
120 |
<dt>Page mode |
180 |
<dt>Page mode |
121 |
<dd> |
181 |
<dd> |
122 |
It is possible to "anchor" a location in the buffer and prevent it |
182 |
It is possible to "anchor" a location in the buffer and prevent it |
123 |
from going out of history. While this can be helpful in having the |
183 |
from going out of history. This can be helpful in having the |
124 |
client of Term make sure that crucial output doesn't get lost due to |
184 |
client of Term make sure that crucial output doesn't get lost due to |
125 |
short-sighted history settings on the part of the user, the main reason |
185 |
short-sighted history settings on the part of the user. |
126 |
is to allow for persistence of coordinate settings. |
|
|
127 |
<p> |
186 |
<p> |
128 |
To use Term |
187 |
To use Term |
129 |
in this mode you can use setText() or appendText() instead of |
188 |
in this mode you can use setText() or appendText() instead of |
Lines 146-154
Link Here
|
146 |
Term is not a document editing widget. |
205 |
Term is not a document editing widget. |
147 |
<p> |
206 |
<p> |
148 |
<li> |
207 |
<li> |
149 |
Term is also not a command line processor in the sense that a Windows |
208 |
Term is also not a command line processor in the sense that a MS Windows |
150 |
console is. Its shuttling of keyboard events to an output stream and |
209 |
console is. Its shuttling of keyboard events to an output stream and |
151 |
rendering of characters on the input stream unto the screen are completely |
210 |
rendering of characters from the input stream unto the screen are completely |
152 |
independent activities. |
211 |
independent activities. |
153 |
<p> |
212 |
<p> |
154 |
This is due to Terms unix heritage where shells (ksh, bash etc) do their own |
213 |
This is due to Terms unix heritage where shells (ksh, bash etc) do their own |
Lines 183-188
Link Here
|
183 |
// statistics |
242 |
// statistics |
184 |
private int n_putchar; |
243 |
private int n_putchar; |
185 |
private int n_putchars; |
244 |
private int n_putchars; |
|
|
245 |
private int n_linefeeds; |
186 |
private int n_repaint; |
246 |
private int n_repaint; |
187 |
private int n_paint; |
247 |
private int n_paint; |
188 |
|
248 |
|
Lines 352-357
Link Here
|
352 |
stream.setToDTE(dce_end); |
412 |
stream.setToDTE(dce_end); |
353 |
dce_end = stream; |
413 |
dce_end = stream; |
354 |
} |
414 |
} |
|
|
415 |
|
416 |
stream.setTerm(this); |
355 |
} |
417 |
} |
356 |
|
418 |
|
357 |
/* |
419 |
/* |
Lines 587-593
Link Here
|
587 |
public void clearHistoryNoRefresh() { |
649 |
public void clearHistoryNoRefresh() { |
588 |
sel.cancel(true); |
650 |
sel.cancel(true); |
589 |
|
651 |
|
590 |
int old_cols = buf.visible_cols; |
652 |
int old_cols = buf.visibleCols(); |
591 |
buf = new Buffer(old_cols); |
653 |
buf = new Buffer(old_cols); |
592 |
|
654 |
|
593 |
st.firstx = 0; |
655 |
st.firstx = 0; |
Lines 943-948
Link Here
|
943 |
|
1005 |
|
944 |
// vertical (row) dimension |
1006 |
// vertical (row) dimension |
945 |
if (st.cursor.row >= st.firstx && st.cursor.row < st.firstx + st.rows) { |
1007 |
if (st.cursor.row >= st.firstx && st.cursor.row < st.firstx + st.rows) { |
|
|
1008 |
; |
946 |
} else { |
1009 |
} else { |
947 |
st.firstx = buf.nlines - st.rows; |
1010 |
st.firstx = buf.nlines - st.rows; |
948 |
repaint(true); |
1011 |
repaint(true); |
Lines 998-1015
Link Here
|
998 |
} |
1061 |
} |
999 |
} |
1062 |
} |
1000 |
|
1063 |
|
1001 |
// System.out.println("Checking hscroll cursor.col " + st.cursor.col + |
1064 |
/* DEBUG |
1002 |
// " firsty " + st.firsty + " visible_cols " + buf.visible_cols); |
1065 |
System.out.println("Checking hscroll cursor.col " + st.cursor.col + // NOI18N |
|
|
1066 |
" firsty " + st.firsty // NOI18N |
1067 |
" visibleCols " + buf.visibleCols()); // NOI18N |
1068 |
*/ |
1003 |
|
1069 |
|
1004 |
// horizontal (col) dimension |
1070 |
// horizontal (col) dimension |
1005 |
if (st.cursor.col >= st.firsty + buf.visible_cols) { |
1071 |
if (st.cursor.col >= st.firsty + buf.visibleCols()) { |
1006 |
// System.out.println("Need to scroll right"); |
1072 |
/* DEBUG |
1007 |
st.firsty = st.cursor.col - buf.visible_cols + 1; |
1073 |
System.out.println("Need to scroll right"); // NOI18N |
|
|
1074 |
*/ |
1075 |
st.firsty = st.cursor.col - buf.visibleCols() + 1; |
1008 |
repaint(true); |
1076 |
repaint(true); |
1009 |
|
1077 |
|
1010 |
} else if (st.cursor.col - buf.visible_cols < st.firsty) { |
1078 |
} else if (st.cursor.col - buf.visibleCols() < st.firsty) { |
1011 |
// System.out.println("Need to scroll left"); |
1079 |
/* DEBUG |
1012 |
st.firsty = st.cursor.col - buf.visible_cols + 1; |
1080 |
System.out.println("Need to scroll left"); // NOI18N |
|
|
1081 |
*/ |
1082 |
st.firsty = st.cursor.col - buf.visibleCols() + 1; |
1013 |
if (st.firsty < 0) |
1083 |
if (st.firsty < 0) |
1014 |
st.firsty = 0; |
1084 |
st.firsty = 0; |
1015 |
else |
1085 |
else |
Lines 1097-1103
Link Here
|
1097 |
// Really weird I seem to get the same results regardless of |
1167 |
// Really weird I seem to get the same results regardless of |
1098 |
// whether I use orows or buf.nlines. SHOULD investigate more. |
1168 |
// whether I use orows or buf.nlines. SHOULD investigate more. |
1099 |
|
1169 |
|
1100 |
// int allowed = orows - st.cursor.row - 1; |
|
|
1101 |
int allowed = buf.nlines - st.cursor.row - 1; |
1170 |
int allowed = buf.nlines - st.cursor.row - 1; |
1102 |
|
1171 |
|
1103 |
if (allowed < 0) |
1172 |
if (allowed < 0) |
Lines 1173-1179
Link Here
|
1173 |
|
1242 |
|
1174 |
// cull any regions that are no longer in history |
1243 |
// cull any regions that are no longer in history |
1175 |
if (++cull_count % cull_frequency == 0) { |
1244 |
if (++cull_count % cull_frequency == 0) { |
1176 |
// System.out.println("Culling regions ..."); // NOI18N |
1245 |
/* DEBUG |
|
|
1246 |
System.out.println("Culling regions ..."); // NOI18N |
1247 |
*/ |
1177 |
region_manager.cull(firsta); |
1248 |
region_manager.cull(firsta); |
1178 |
} |
1249 |
} |
1179 |
|
1250 |
|
Lines 1244-1255
Link Here
|
1244 |
c = 0; |
1315 |
c = 0; |
1245 |
} else if ((direction & RIGHT) == RIGHT) { |
1316 |
} else if ((direction & RIGHT) == RIGHT) { |
1246 |
st.firsty ++; |
1317 |
st.firsty ++; |
1247 |
int limit = buf.totalCols() - buf.visible_cols; |
1318 |
int limit = buf.totalCols() - buf.visibleCols(); |
1248 |
if (limit < 0) |
1319 |
if (limit < 0) |
1249 |
limit = 0; |
1320 |
limit = 0; |
1250 |
if (st.firsty > limit) |
1321 |
if (st.firsty > limit) |
1251 |
st.firsty = limit; |
1322 |
st.firsty = limit; |
1252 |
c = st.firsty + buf.visible_cols; |
1323 |
c = st.firsty + buf.visibleCols(); |
1253 |
} |
1324 |
} |
1254 |
|
1325 |
|
1255 |
BCoord vc = new BCoord(r, c); |
1326 |
BCoord vc = new BCoord(r, c); |
Lines 1263-1278
Link Here
|
1263 |
public void run() { |
1334 |
public void run() { |
1264 |
while (true) { |
1335 |
while (true) { |
1265 |
|
1336 |
|
1266 |
// System.out.print("Scrolling "); |
1337 |
/* DEBUG |
1267 |
// if ((direction & UP) == UP) |
1338 |
System.out.print("Scrolling "); // NOI18N |
1268 |
// System.out.print("UP "); |
1339 |
if ((direction & UP) == UP) |
1269 |
// if ((direction & DOWN) == DOWN) |
1340 |
System.out.print("UP "); // NOI18N |
1270 |
// System.out.print("DOWN "); |
1341 |
if ((direction & DOWN) == DOWN) |
1271 |
// if ((direction & LEFT) == LEFT) |
1342 |
System.out.print("DOWN "); // NOI18N |
1272 |
// System.out.print("LEFT "); |
1343 |
if ((direction & LEFT) == LEFT) |
1273 |
// if ((direction & RIGHT) == RIGHT) |
1344 |
System.out.print("LEFT "); // NOI18N |
1274 |
// System.out.print("RIGHT "); |
1345 |
if ((direction & RIGHT) == RIGHT) |
1275 |
// System.out.println(); |
1346 |
System.out.print("RIGHT "); // NOI18N |
|
|
1347 |
System.out.println(); |
1348 |
*/ |
1276 |
|
1349 |
|
1277 |
extend(); |
1350 |
extend(); |
1278 |
|
1351 |
|
Lines 1282-1288
Link Here
|
1282 |
break; |
1355 |
break; |
1283 |
} |
1356 |
} |
1284 |
} |
1357 |
} |
1285 |
// System.out.println("Done with Scrolling"); |
1358 |
/* DEBUG |
|
|
1359 |
System.out.println("Done with Scrolling"); // NOI18N |
1360 |
*/ |
1286 |
} |
1361 |
} |
1287 |
} |
1362 |
} |
1288 |
|
1363 |
|
Lines 1354-1360
Link Here
|
1354 |
BorderLayout layout = new BorderLayout(); |
1429 |
BorderLayout layout = new BorderLayout(); |
1355 |
setLayout(layout); |
1430 |
setLayout(layout); |
1356 |
screen = new Screen(this, |
1431 |
screen = new Screen(this, |
1357 |
(buf.visible_cols * metrics.width + |
1432 |
(buf.visibleCols() * metrics.width + |
1358 |
glyph_gutter_width + |
1433 |
glyph_gutter_width + |
1359 |
debug_gutter_width), |
1434 |
debug_gutter_width), |
1360 |
st.rows * metrics.height); |
1435 |
st.rows * metrics.height); |
Lines 1389-1399
Link Here
|
1389 |
|
1464 |
|
1390 |
// deal with the user moving the thumb |
1465 |
// deal with the user moving the thumb |
1391 |
st.firstx = pos; |
1466 |
st.firstx = pos; |
|
|
1467 |
/* DEBUG |
1468 |
if (st.firstx + st.rows > buf.nlines) { |
1469 |
Thread.dumpStack(); |
1470 |
printStats("bad scroll value"); // NOI18N |
1471 |
} |
1472 |
*/ |
1392 |
repaint(false); |
1473 |
repaint(false); |
1393 |
break; |
1474 |
break; |
1394 |
|
1475 |
|
1395 |
default: |
1476 |
default: |
1396 |
// System.out.println("adjustmentValueChanged: " + e); // NOI18N |
1477 |
/* DEBUG |
|
|
1478 |
System.out.println("adjustmentValueChanged: " + e); // NOI18N |
1479 |
*/ |
1397 |
break; |
1480 |
break; |
1398 |
} |
1481 |
} |
1399 |
} |
1482 |
} |
Lines 1429-1435
Link Here
|
1429 |
break; |
1512 |
break; |
1430 |
|
1513 |
|
1431 |
default: |
1514 |
default: |
1432 |
// System.out.println("adjustmentValueChanged: " + e); // NOI18N |
1515 |
/* DEBUG |
|
|
1516 |
System.out.println("adjustmentValueChanged: " + e); // NOI18N |
1517 |
*/ |
1433 |
break; |
1518 |
break; |
1434 |
} |
1519 |
} |
1435 |
} |
1520 |
} |
Lines 1483-1489
Link Here
|
1483 |
} |
1568 |
} |
1484 |
|
1569 |
|
1485 |
public void keyPressed(KeyEvent e) { |
1570 |
public void keyPressed(KeyEvent e) { |
1486 |
// System.out.println("keyPressed " + e); // NOI18N |
1571 |
/* DEBUG |
|
|
1572 |
System.out.println("keyPressed " + e); // NOI18N |
1573 |
*/ |
1487 |
|
1574 |
|
1488 |
switch (e.getKeyCode()) { |
1575 |
switch (e.getKeyCode()) { |
1489 |
case KeyEvent.VK_COPY: |
1576 |
case KeyEvent.VK_COPY: |
Lines 1508-1516
Link Here
|
1508 |
} |
1595 |
} |
1509 |
|
1596 |
|
1510 |
public void keyReleased(KeyEvent e) { |
1597 |
public void keyReleased(KeyEvent e) { |
1511 |
// System.out.println("keyReleased"); // NOI18N |
1598 |
/* DEBUG |
|
|
1599 |
System.out.println("keyReleased"); // NOI18N |
1600 |
*/ |
1601 |
|
1512 |
if (e.getKeyCode() == KeyEvent.VK_ENTER) { |
1602 |
if (e.getKeyCode() == KeyEvent.VK_ENTER) { |
1513 |
// System.out.println("keyReleased VK_ENTER"); // NOI18N |
1603 |
/* DEBUG |
|
|
1604 |
System.out.println("keyReleased VK_ENTER"); // NOI18N |
1605 |
*/ |
1514 |
saw_return = false; |
1606 |
saw_return = false; |
1515 |
} |
1607 |
} |
1516 |
maybeConsume(e); |
1608 |
maybeConsume(e); |
Lines 1520-1533
Link Here
|
1520 |
screen.addMouseMotionListener(new MouseMotionListener() { |
1612 |
screen.addMouseMotionListener(new MouseMotionListener() { |
1521 |
|
1613 |
|
1522 |
public void mouseDragged(MouseEvent e) { |
1614 |
public void mouseDragged(MouseEvent e) { |
1523 |
// System.out.println("mouseDragged"); // NOI18N |
1615 |
/* DEBUG |
|
|
1616 |
System.out.println("mouseDragged"); // NOI18N |
1617 |
*/ |
1524 |
if (left_down_point != null) { |
1618 |
if (left_down_point != null) { |
1525 |
BCoord bc = toBufCoords(toViewCoord(left_down_point)); |
1619 |
BCoord bc = toBufCoords(toViewCoord(left_down_point)); |
1526 |
sel.track(new Coord(bc, firsta)); |
1620 |
sel.track(new Coord(bc, firsta)); |
1527 |
left_down_point = null; |
1621 |
left_down_point = null; |
1528 |
} |
1622 |
} |
1529 |
drag_point = e.getPoint(); |
1623 |
drag_point = e.getPoint(); |
1530 |
// System.out.println("mouseDrag: " + drag_point); // NOI18N |
1624 |
/* DEBUG |
|
|
1625 |
System.out.println("mouseDrag: " + drag_point); // NOI18N |
1626 |
*/ |
1531 |
|
1627 |
|
1532 |
int scroll_direction = 0; |
1628 |
int scroll_direction = 0; |
1533 |
|
1629 |
|
Lines 1547-1561
Link Here
|
1547 |
} |
1643 |
} |
1548 |
|
1644 |
|
1549 |
public void mouseMoved(MouseEvent e) { |
1645 |
public void mouseMoved(MouseEvent e) { |
1550 |
/* |
1646 |
/* DEBUG |
1551 |
Point p = (Point) e.getPoint().clone(); |
1647 |
Point p = (Point) e.getPoint().clone(); |
1552 |
BCoord bc = toBufCoords(toViewCoord(p)); |
1648 |
BCoord bc = toBufCoords(toViewCoord(p)); |
1553 |
Coord c = new Coord(bc, firsta); |
1649 |
Coord c = new Coord(bc, firsta); |
1554 |
Extent x = sel.getExtent(); |
1650 |
Extent x = sel.getExtent(); |
1555 |
if (x == null) { |
1651 |
if (x == null) { |
1556 |
// System.out.println("sel intersect: no extent"); |
1652 |
System.out.println("sel intersect: no extent"); // NOI18N |
1557 |
} else { |
1653 |
} else { |
1558 |
// System.out.println("sel intersect: " + (x.intersects(c.row, c.col)? "intersects": "doesn't intersect")); |
1654 |
System.out.println("sel intersect: " + // NOI18N |
|
|
1655 |
(x.intersects(c.row, c.col)? "intersects" // NOI18N |
1656 |
"doesn't intersect")); // NOI18N |
1559 |
} |
1657 |
} |
1560 |
*/ |
1658 |
*/ |
1561 |
} |
1659 |
} |
Lines 1564-1570
Link Here
|
1564 |
screen.addMouseListener(new MouseListener() { |
1662 |
screen.addMouseListener(new MouseListener() { |
1565 |
|
1663 |
|
1566 |
public void mouseClicked(MouseEvent e) { |
1664 |
public void mouseClicked(MouseEvent e) { |
1567 |
// System.out.println("mouseClicked"); // NOI18N |
1665 |
/* DEBUG |
|
|
1666 |
System.out.println("mouseClicked"); // NOI18N |
1667 |
*/ |
1568 |
BCoord bcoord = toBufCoords(toViewCoord(e.getPoint())); |
1668 |
BCoord bcoord = toBufCoords(toViewCoord(e.getPoint())); |
1569 |
|
1669 |
|
1570 |
if (SwingUtilities.isLeftMouseButton(e)) { |
1670 |
if (SwingUtilities.isLeftMouseButton(e)) { |
Lines 1573-1580
Link Here
|
1573 |
screen.requestFocus(); |
1673 |
screen.requestFocus(); |
1574 |
|
1674 |
|
1575 |
} else if ( SwingUtilities.isMiddleMouseButton(e)) { |
1675 |
} else if ( SwingUtilities.isMiddleMouseButton(e)) { |
1576 |
// System.out.println("MIDDLE click"); // NOI18N |
1676 |
/* DEBUG |
1577 |
// System.out.println("Selection: '" + sel.sel_get() + "'"); // NOI18N |
1677 |
System.out.println("MIDDLE click"); // NOI18N |
|
|
1678 |
System.out.println("Selection: '" + sel.sel_get() + "'"); // NOI18N |
1679 |
*/ |
1578 |
paste(); |
1680 |
paste(); |
1579 |
|
1681 |
|
1580 |
} else if (SwingUtilities.isRightMouseButton(e)) { |
1682 |
} else if (SwingUtilities.isRightMouseButton(e)) { |
Lines 1703-1710
Link Here
|
1703 |
|
1805 |
|
1704 |
if (message != null) |
1806 |
if (message != null) |
1705 |
System.out.print("\t"); // NOI18N |
1807 |
System.out.print("\t"); // NOI18N |
1706 |
System.out.println("rows " + st.rows + |
1808 |
System.out.println("rows " + st.rows + // NOI18N |
1707 |
" v cols " + buf.visible_cols + // NOI18N |
1809 |
" v cols " + buf.visibleCols() + // NOI18N |
1708 |
" t cols " + buf.totalCols() + // NOI18N |
1810 |
" t cols " + buf.totalCols() + // NOI18N |
1709 |
" history " + history_size + // NOI18N |
1811 |
" history " + history_size + // NOI18N |
1710 |
" firstx " + st.firstx + // NOI18N |
1812 |
" firstx " + st.firstx + // NOI18N |
Lines 1722-1727
Link Here
|
1722 |
System.out.print("\t"); // NOI18N |
1824 |
System.out.print("\t"); // NOI18N |
1723 |
System.out.println("putChar " + n_putchar + // NOI18N |
1825 |
System.out.println("putChar " + n_putchar + // NOI18N |
1724 |
" putChars " + n_putchars + // NOI18N |
1826 |
" putChars " + n_putchars + // NOI18N |
|
|
1827 |
" linefeeds " + n_linefeeds + // NOI18N |
1725 |
" repaint " + n_repaint + // NOI18N |
1828 |
" repaint " + n_repaint + // NOI18N |
1726 |
" paint " + n_paint); // NOI18N |
1829 |
" paint " + n_paint); // NOI18N |
1727 |
} |
1830 |
} |
Lines 1813-1822
Link Here
|
1813 |
} |
1916 |
} |
1814 |
|
1917 |
|
1815 |
/** |
1918 |
/** |
|
|
1919 |
* Trampoline from Line.ensureCapacity() to Buffer.noteColumn() |
1920 |
*/ |
1921 |
void noteColumn(Line l, int capacity) { |
1922 |
int vcapacity = l.bufToCell(metrics, capacity); |
1923 |
buf.noteColumn(vcapacity); |
1924 |
} |
1925 |
|
1926 |
/** |
1927 |
* Trampoline from Line to MyFontMetrics.checkForMultiCell() |
1928 |
*/ |
1929 |
void checkForMultiCell(char c) { |
1930 |
metrics.checkForMultiCell(c); |
1931 |
} |
1932 |
|
1933 |
/** |
1816 |
* Get the number of character columns in the screen |
1934 |
* Get the number of character columns in the screen |
1817 |
*/ |
1935 |
*/ |
1818 |
public int getColumns() { |
1936 |
public int getColumns() { |
1819 |
return buf.visible_cols; |
1937 |
return buf.visibleCols(); |
1820 |
} |
1938 |
} |
1821 |
|
1939 |
|
1822 |
/** |
1940 |
/** |
Lines 1892-1898
Link Here
|
1892 |
*/ |
2010 |
*/ |
1893 |
public void fillSizeInfo(Dimension cells, Dimension pixels) { |
2011 |
public void fillSizeInfo(Dimension cells, Dimension pixels) { |
1894 |
cells.height = st.rows; |
2012 |
cells.height = st.rows; |
1895 |
cells.width = buf.visible_cols; |
2013 |
cells.width = buf.visibleCols(); |
1896 |
Dimension cpixels = screen.getSize(); |
2014 |
Dimension cpixels = screen.getSize(); |
1897 |
pixels.width = cpixels.width - glyph_gutter_width - debug_gutter_width; |
2015 |
pixels.width = cpixels.width - glyph_gutter_width - debug_gutter_width; |
1898 |
pixels.height = cpixels.height; |
2016 |
pixels.height = cpixels.height; |
Lines 1904-1910
Link Here
|
1904 |
*/ |
2022 |
*/ |
1905 |
protected void updateTtySize() { |
2023 |
protected void updateTtySize() { |
1906 |
if (screen != null) { |
2024 |
if (screen != null) { |
1907 |
Dimension cells = new Dimension(buf.visible_cols, st.rows); |
2025 |
Dimension cells = new Dimension(buf.visibleCols(), st.rows); |
1908 |
Dimension pixels = screen.getSize(); |
2026 |
Dimension pixels = screen.getSize(); |
1909 |
fireSizeChanged(cells, pixels); |
2027 |
fireSizeChanged(cells, pixels); |
1910 |
} |
2028 |
} |
Lines 1918-1924
Link Here
|
1918 |
/* |
2036 |
/* |
1919 |
* Convert from buffer coords to view coords |
2037 |
* Convert from buffer coords to view coords |
1920 |
*/ |
2038 |
*/ |
1921 |
BCoord v = new BCoord(b.row - st.firstx, b.col - st.firsty); |
2039 |
int vc = buf.lineAt(b.row).bufToCell(metrics, b.col); |
|
|
2040 |
BCoord v = new BCoord(b.row - st.firstx, vc - st.firsty); |
1922 |
return v; |
2041 |
return v; |
1923 |
} |
2042 |
} |
1924 |
|
2043 |
|
Lines 1949-1955
Link Here
|
1949 |
private BCoord toViewCoord(Point p) { |
2068 |
private BCoord toViewCoord(Point p) { |
1950 |
BCoord v = new BCoord(p.y / metrics.height, |
2069 |
BCoord v = new BCoord(p.y / metrics.height, |
1951 |
(p.x - glyph_gutter_width - debug_gutter_width) / metrics.width); |
2070 |
(p.x - glyph_gutter_width - debug_gutter_width) / metrics.width); |
1952 |
v.clip(st.rows, buf.visible_cols); |
2071 |
v.clip(st.rows, buf.visibleCols()); |
1953 |
// System.out.println("toViewCoord() -> " + v); // NOI18N |
2072 |
// System.out.println("toViewCoord() -> " + v); // NOI18N |
1954 |
return v; |
2073 |
return v; |
1955 |
} |
2074 |
} |
Lines 1962-1969
Link Here
|
1962 |
int brow = st.firstx + v.row; |
2081 |
int brow = st.firstx + v.row; |
1963 |
if (brow >= buf.nlines) |
2082 |
if (brow >= buf.nlines) |
1964 |
brow = buf.nlines-1; |
2083 |
brow = buf.nlines-1; |
1965 |
BCoord b = new BCoord(brow, st.firsty + v.col); |
2084 |
int bc = buf.lineAt(brow).cellToBuf(metrics, st.firsty + v.col); |
1966 |
// System.out.println("toBufCoords() -> " + b); // NOI18N |
2085 |
BCoord b = new BCoord(brow, bc); |
|
|
2086 |
// System.out.println("toBufCoords(" + v + ") -> " + b); // NOI18N |
1967 |
return b; |
2087 |
return b; |
1968 |
} |
2088 |
} |
1969 |
|
2089 |
|
Lines 2013-2036
Link Here
|
2013 |
} |
2133 |
} |
2014 |
} |
2134 |
} |
2015 |
|
2135 |
|
|
|
2136 |
|
2016 |
private Color actual_foreground; |
2137 |
private Color actual_foreground; |
2017 |
private Color actual_background; |
2138 |
private Color actual_background; |
2018 |
private boolean check_selection; |
2139 |
private boolean check_selection; |
2019 |
private int totcols; |
2140 |
private int totcols; |
2020 |
|
2141 |
|
2021 |
private void do_run(Graphics g, int yoff, int xoff, int baseline, |
2142 |
private void do_run(Graphics g, int yoff, int xoff, int baseline, |
2022 |
int brow, char buf[], |
2143 |
int brow, char buf[], Line l, |
2023 |
int attr, int rbegin, int rend) { |
2144 |
int attr, int rbegin, int rend) { |
2024 |
|
2145 |
|
2025 |
// System.out.println("do_run(" + rbegin + ", " + rend + ")"); |
2146 |
// System.out.println("do_run(" + rbegin + ", " + rend + ")"); // NOI18N |
2026 |
|
2147 |
|
2027 |
int x = xoff + (rbegin - st.firsty) * metrics.width; |
2148 |
int x; |
2028 |
int rlength = rend - rbegin + 1; |
2149 |
int rlength; |
2029 |
if (rlength <= 0) { |
2150 |
int xlength; |
2030 |
System.out.println("do_run(" + rbegin + ", " + rend + ")"); |
2151 |
|
2031 |
return; |
2152 |
if (metrics.isMultiCell()) { |
|
|
2153 |
int vbegin = l.bufToCell(metrics, rbegin); |
2154 |
int vend = l.bufToCell(metrics, rend+1)-1; |
2155 |
x = xoff + (vbegin - st.firsty) * metrics.width; |
2156 |
int vlength = vend - vbegin + 1; |
2157 |
if (vlength <= 0) { |
2158 |
/* DEBUG |
2159 |
System.out.println("do_run(" + rbegin + ", " + rend + ")"); // NOI18N |
2160 |
*/ |
2161 |
return; |
2162 |
} |
2163 |
rlength = rend - rbegin + 1; |
2164 |
xlength = vlength * metrics.width; |
2165 |
|
2166 |
} else { |
2167 |
x = xoff + (rbegin - st.firsty) * metrics.width; |
2168 |
rlength = rend - rbegin + 1; |
2169 |
if (rlength <= 0) { |
2170 |
/* DEBUG |
2171 |
System.out.println("do_run(" + rbegin + ", " + rend + ")"); // NOI18N |
2172 |
*/ |
2173 |
return; |
2174 |
} |
2175 |
xlength = rlength * metrics.width; |
2032 |
} |
2176 |
} |
2033 |
int xlength = rlength * metrics.width; |
|
|
2034 |
|
2177 |
|
2035 |
boolean reverse = ((attr & Attr.REVERSE) == Attr.REVERSE); |
2178 |
boolean reverse = ((attr & Attr.REVERSE) == Attr.REVERSE); |
2036 |
boolean active = ((attr & Attr.ACTIVE) == Attr.ACTIVE); |
2179 |
boolean active = ((attr & Attr.ACTIVE) == Attr.ACTIVE); |
Lines 2097-2126
Link Here
|
2097 |
} |
2240 |
} |
2098 |
|
2241 |
|
2099 |
// Draw the foreground character glyphs |
2242 |
// Draw the foreground character glyphs |
2100 |
g.drawChars(buf, rbegin, rlength, x, baseline); |
2243 |
myDrawChars(g, buf, l, rbegin, rlength, x, baseline); |
2101 |
|
2244 |
|
2102 |
// Draw fake bold characters by redrawing one pixel to the right |
2245 |
// Draw fake bold characters by redrawing one pixel to the right |
2103 |
if ( (attr & Attr.BRIGHT) == Attr.BRIGHT) { |
2246 |
if ( (attr & Attr.BRIGHT) == Attr.BRIGHT) { |
2104 |
g.drawChars(buf, rbegin, rlength, x+1, baseline); |
2247 |
myDrawChars(g, buf, l, rbegin, rlength, x+1, baseline); |
|
|
2248 |
} |
2249 |
} |
2250 |
|
2251 |
|
2252 |
|
2253 |
private final Point newp = new Point(); |
2254 |
|
2255 |
/* |
2256 |
* Tweak glyph X positions so they fall on cell/grid/column boundries. |
2257 |
*/ |
2258 |
private void massage_glyphs(GlyphVector gv, int start, int n, Line l) { |
2259 |
Point2D pos0 = gv.getGlyphPosition(0); |
2260 |
|
2261 |
// There's one big assumption here that in a monospaced font all the |
2262 |
// Y placements are identical. So we use the placement for the first |
2263 |
// glyph only. |
2264 |
newp.y = (int) pos0.getY(); |
2265 |
|
2266 |
int col = (int) pos0.getX(); |
2267 |
for (int gx = 0; gx < n; gx++) { |
2268 |
newp.x = col; |
2269 |
gv.setGlyphPosition(gx, newp); |
2270 |
col += l.width(metrics, start + gx) * metrics.width; |
2271 |
} |
2272 |
} |
2273 |
|
2274 |
/** |
2275 |
* Draw characters in cells. |
2276 |
* |
2277 |
* Fixed width or monospaced fonts implies that the glyphs of all characters |
2278 |
* have the same width. Some non-latin characters (japanese) might have |
2279 |
* glyph widths that are an _integer multiple_ of the latin glyphs. Thus |
2280 |
* cellular (grid based) text widget like this termulator can still place |
2281 |
* all characters nicely. There is a 'C' function wcwidth() which |
2282 |
* ... determines the number of _column_ positions ... and CDE's DtTrem |
2283 |
* ultimately depends on it to place things. (See also Tuthill & Smallberg, |
2284 |
* "Creating worldwide software" PrenticeHall 2nd ed. p98) |
2285 |
* |
2286 |
* Unfortunately the fonts used by Java, even the "monospaced" fonts, do |
2287 |
* not abide by the above convention. I measured a 10pt ja locale latin |
2288 |
* character at 7 pixels wide and a japanese character at 12 pixels wide, |
2289 |
* instead of 14. A similar problem existed with respect to the "unprintbale" |
2290 |
* placeholder square. Until Java 1.4 it used to be 9 or 10 pixels wide! |
2291 |
* The square is fixed, but I"m not sure the above will be anytime soon. |
2292 |
* |
2293 |
* What this means is that Graphics.drawString() when given a mix and match |
2294 |
* of latin and japanese characters will not place them right. Selection |
2295 |
* doesn't work etc. |
2296 |
* |
2297 |
* Nor does Java provide anything resembling wcwidth() so we're rolling |
2298 |
* our own here. That's done in Line.width(). |
2299 |
* |
2300 |
* So one approach would be to place each character individually, but it's |
2301 |
* rather slow. Fortunately Java provides a GlyphVector class that allows |
2302 |
* us to tweak the positions of the glyphs. The timing I"ve gotten are |
2303 |
* 50 for one drawChars() per charactr. (SLOWER below) |
2304 |
* 15 using the GlyphVector technique |
2305 |
* 8 using plain drawChars |
2306 |
* Unfortunately GlyphVector's interface leaves a bit to be desired. |
2307 |
* - It does not take a (char [], offset, length) triple and depends |
2308 |
* on the length of the char array passed in. Since our Line char arrays |
2309 |
* have some slop in them we can't pass them directly. Hence the |
2310 |
* "new char[]" and the "System.arraycopy". |
2311 |
* - The interface for getting and setting positions is also a bit |
2312 |
* awkward as you may notice from massage_glyphs(). |
2313 |
* |
2314 |
* We SHOULD fall back on plain drawChars() if the host charset is an |
2315 |
* 8 bit encoding like ASCII or ISO 8859. This encoding is available |
2316 |
* via System.getProperty("file.encoding") but there are so many aliases |
2317 |
* for each that I"m wary of hardcoding tests. See |
2318 |
* http://www.iana.org/assignments/character-sets |
2319 |
* Java 1.4 has class Charset that helps with the aliases but we can't |
2320 |
* yet lock into 1.4. |
2321 |
*/ |
2322 |
|
2323 |
private void myDrawChars(Graphics g, char buf[], Line l, |
2324 |
int start, int howmany, int xoff, int baseline) { |
2325 |
if (metrics.isMultiCell()) { |
2326 |
// slow way |
2327 |
// This looks expensive but it is in fact a whole lot faster |
2328 |
// than issuing a g.drawChars() _per_ character |
2329 |
|
2330 |
Graphics2D g2 = (Graphics2D) g; |
2331 |
FontRenderContext frc = g2.getFontRenderContext(); |
2332 |
// Gaaah, why doesn't createGlyphVector() take a (char[],offset,len) |
2333 |
// triple? |
2334 |
char[] tmp = new char[howmany]; |
2335 |
System.arraycopy(buf, start, tmp, 0, howmany); |
2336 |
GlyphVector gv = getFont().createGlyphVector(frc, tmp); |
2337 |
massage_glyphs(gv, start, howmany, l); |
2338 |
g2.drawGlyphVector(gv, xoff, baseline); |
2339 |
} else { |
2340 |
// fast way |
2341 |
g.drawChars(buf, start, howmany, xoff, baseline); |
2105 |
} |
2342 |
} |
2106 |
} |
2343 |
} |
2107 |
|
2344 |
|
2108 |
/* |
2345 |
/* |
2109 |
* Render one line |
2346 |
* Render one line |
|
|
2347 |
* Draw the line on this brow (buffer row 0-origin) |
2110 |
*/ |
2348 |
*/ |
2111 |
|
2349 |
|
2112 |
private void paint_line_new(Graphics g, Line l, int brow, |
2350 |
private void paint_line_new(Graphics g, Line l, int brow, |
2113 |
int xoff, int yoff, int baseline, |
2351 |
int xoff, int yoff, int baseline, |
2114 |
Extent selx) { |
2352 |
Extent selx) { |
2115 |
// draw the line on this brow (buffer row 0-origin) |
|
|
2116 |
|
2353 |
|
2117 |
int length = l.length(); |
2354 |
int length = l.length(); |
2118 |
if (length == 0) |
2355 |
if (length == 0) |
2119 |
return; |
2356 |
return; |
2120 |
|
2357 |
|
2121 |
int howmany = length-st.firsty; |
2358 |
int lastcol; |
2122 |
if (howmany <= 0) |
2359 |
int firstcol; |
|
|
2360 |
|
2361 |
if (metrics.isMultiCell()) { |
2362 |
|
2363 |
// Figure what buffer column is the first visible one (moral |
2364 |
// equivalent of st.firsty) |
2365 |
|
2366 |
// SHOULD replace with something that does cellToBuf/bufToCell |
2367 |
// all at once. There are a couple of other occurances of this |
2368 |
// pattern. |
2369 |
|
2370 |
firstcol = l.cellToBuf(metrics, st.firsty); |
2371 |
int inverse_firstcol = l.bufToCell(metrics, firstcol); |
2372 |
int delta = st.firsty - inverse_firstcol; |
2373 |
if (delta > 0) { |
2374 |
/* This is what to do if we want to draw the right half of the |
2375 |
* glyph. However the left half of it will end up in the glyph |
2376 |
* gutter and to compensate for thet we'll need to tweak the |
2377 |
* clip region. For now taking the easy way out> |
2378 |
|
2379 |
int pdelta = delta * metrics.width; // pixel delta |
2380 |
xoff -= pdelta; |
2381 |
|
2382 |
*/ |
2383 |
|
2384 |
firstcol++; |
2385 |
int pdelta = delta * metrics.width; // pixel delta |
2386 |
xoff += pdelta; |
2387 |
} |
2388 |
|
2389 |
lastcol = l.cellToBuf(metrics, st.firsty + buf.visibleCols() - 1); |
2390 |
|
2391 |
/* DEBUG |
2392 |
System.out.print |
2393 |
("firstcol = " + firstcol + " for firsty " + st.firsty); // NOI18N |
2394 |
System.out.print |
2395 |
(" delta = " + delta); // NOI18N |
2396 |
System.out.println |
2397 |
(" lastcol = " + lastcol + // NOI18N |
2398 |
" for visibleCols " + buf.visibleCols()); // NOI18N |
2399 |
*/ |
2400 |
|
2401 |
} else { |
2402 |
lastcol = st.firsty + buf.visibleCols() - 1; |
2403 |
firstcol = st.firsty; |
2404 |
} |
2405 |
|
2406 |
|
2407 |
lastcol = Math.min(lastcol, length-1); |
2408 |
if (firstcol > lastcol) |
2123 |
return; |
2409 |
return; |
|
|
2410 |
int howmany = lastcol - firstcol + 1; |
2411 |
|
2412 |
|
2413 |
// 'length' is not used from here on down |
2124 |
|
2414 |
|
2125 |
char buf[] = l.charArray(); |
2415 |
char buf[] = l.charArray(); |
2126 |
|
2416 |
|
Lines 2130-2141
Link Here
|
2130 |
if (l.isWrapped() && l.isAboutToWrap()) |
2420 |
if (l.isWrapped() && l.isAboutToWrap()) |
2131 |
g.setColor(Color.red); // not a good state to be in |
2421 |
g.setColor(Color.red); // not a good state to be in |
2132 |
else if (l.isAboutToWrap()) |
2422 |
else if (l.isAboutToWrap()) |
2133 |
g.setColor(Color.pink); |
2423 |
g.setColor(Color.orange); |
2134 |
else if (l.isWrapped()) |
2424 |
else if (l.isWrapped()) |
2135 |
g.setColor(Color.magenta); |
2425 |
g.setColor(Color.magenta); |
2136 |
} |
2426 |
} |
2137 |
|
2427 |
|
2138 |
g.drawChars(buf, st.firsty, howmany, xoff, baseline); |
2428 |
myDrawChars(g, buf, l, firstcol, howmany, xoff, baseline); |
|
|
2429 |
|
2430 |
|
2139 |
return; |
2431 |
return; |
2140 |
} |
2432 |
} |
2141 |
|
2433 |
|
Lines 2166-2174
Link Here
|
2166 |
} |
2458 |
} |
2167 |
|
2459 |
|
2168 |
// iterate through runs |
2460 |
// iterate through runs |
2169 |
int lastcol = st.firsty + howmany; |
|
|
2170 |
|
2461 |
|
2171 |
int rbegin = st.firsty; |
2462 |
int rbegin = firstcol; |
2172 |
int rend = rbegin; |
2463 |
int rend = rbegin; |
2173 |
|
2464 |
|
2174 |
while (true) { |
2465 |
while (true) { |
Lines 2179-2185
Link Here
|
2179 |
|
2470 |
|
2180 |
int attr = attrs[rbegin]; |
2471 |
int attr = attrs[rbegin]; |
2181 |
rend = rbegin+1; |
2472 |
rend = rbegin+1; |
2182 |
while (rend < lastcol) { |
2473 |
while (rend <= lastcol) { |
2183 |
if (attrs[rend] != attr) |
2474 |
if (attrs[rend] != attr) |
2184 |
break; |
2475 |
break; |
2185 |
rend++; |
2476 |
rend++; |
Lines 2195-2239
Link Here
|
2195 |
if (sbegin == -1 || send < rbegin || sbegin > rend) { |
2486 |
if (sbegin == -1 || send < rbegin || sbegin > rend) { |
2196 |
// run is not in selection |
2487 |
// run is not in selection |
2197 |
do_run(g, yoff, xoff, |
2488 |
do_run(g, yoff, xoff, |
2198 |
baseline, brow, buf, attr, rbegin, rend); |
2489 |
baseline, brow, buf, l, attr, rbegin, rend); |
2199 |
|
2490 |
|
2200 |
} else if (sbegin <= rbegin && send >= rend) { |
2491 |
} else if (sbegin <= rbegin && send >= rend) { |
2201 |
// run entirely in selection |
2492 |
// run entirely in selection |
2202 |
// System.out.println("run entirely in selection"); |
2493 |
/* DEBUG |
|
|
2494 |
System.out.println("run entirely in selection"); // NOI18N |
2495 |
*/ |
2203 |
do_run(g, yoff, xoff, |
2496 |
do_run(g, yoff, xoff, |
2204 |
baseline, brow, buf, alt_attr, rbegin, rend); |
2497 |
baseline, brow, buf, l, alt_attr, rbegin, rend); |
2205 |
|
2498 |
|
2206 |
} else if (sbegin > rbegin && send < rend) { |
2499 |
} else if (sbegin > rbegin && send < rend) { |
2207 |
// selection fully within run |
2500 |
// selection fully within run |
2208 |
// split into three parts |
2501 |
// split into three parts |
2209 |
// System.out.println("run selection fully within run"); |
2502 |
/* DEBUG |
|
|
2503 |
System.out.println("run selection fully within run"); // NOI18N |
2504 |
*/ |
2210 |
do_run(g, yoff, xoff, |
2505 |
do_run(g, yoff, xoff, |
2211 |
baseline, brow, buf, attr, rbegin, sbegin-1); |
2506 |
baseline, brow, buf, l, attr, rbegin, sbegin-1); |
2212 |
do_run(g, yoff, xoff, |
2507 |
do_run(g, yoff, xoff, |
2213 |
baseline, brow, buf, alt_attr, sbegin, send); |
2508 |
baseline, brow, buf, l, alt_attr, sbegin, send); |
2214 |
do_run(g, yoff, xoff, |
2509 |
do_run(g, yoff, xoff, |
2215 |
baseline, brow, buf, attr, send+1, rend); |
2510 |
baseline, brow, buf, l, attr, send+1, rend); |
2216 |
|
2511 |
|
2217 |
} else if (sbegin <= rbegin) { |
2512 |
} else if (sbegin <= rbegin) { |
2218 |
// selection covers left portion of run |
2513 |
// selection covers left portion of run |
2219 |
// System.out.println("selection covers left portion of run"); |
2514 |
/* DEBUG |
|
|
2515 |
System.out.println("selection covers left portion of run"); // NOI18N |
2516 |
*/ |
2220 |
// split into two parts |
2517 |
// split into two parts |
2221 |
do_run(g, yoff, xoff, |
2518 |
do_run(g, yoff, xoff, |
2222 |
baseline, brow, buf, alt_attr, rbegin, send); |
2519 |
baseline, brow, buf, l, alt_attr, rbegin, send); |
2223 |
do_run(g, yoff, xoff, |
2520 |
do_run(g, yoff, xoff, |
2224 |
baseline, brow, buf, attr, send+1, rend); |
2521 |
baseline, brow, buf, l, attr, send+1, rend); |
2225 |
|
2522 |
|
2226 |
} else if (send >= rend) { |
2523 |
} else if (send >= rend) { |
2227 |
// selection covers right portion of run |
2524 |
// selection covers right portion of run |
2228 |
// split into two parts |
2525 |
// split into two parts |
2229 |
// System.out.println("selection covers right portion of run"); |
2526 |
/* DEBUG |
|
|
2527 |
System.out.println("selection covers right portion of run"); // NOI18N |
2528 |
*/ |
2230 |
do_run(g, yoff, xoff, |
2529 |
do_run(g, yoff, xoff, |
2231 |
baseline, brow, buf, attr, rbegin, sbegin-1); |
2530 |
baseline, brow, buf, l, attr, rbegin, sbegin-1); |
2232 |
do_run(g, yoff, xoff, |
2531 |
do_run(g, yoff, xoff, |
2233 |
baseline, brow, buf, alt_attr, sbegin, rend); |
2532 |
baseline, brow, buf, l, alt_attr, sbegin, rend); |
2234 |
|
2533 |
|
2235 |
} else { |
2534 |
} else { |
2236 |
// System.out.println("Odd run/selection overlap"); |
2535 |
// System.out.println("Odd run/selection overlap"); // NOI18N |
2237 |
} |
2536 |
} |
2238 |
|
2537 |
|
2239 |
if (rend+1 >= lastcol) |
2538 |
if (rend+1 >= lastcol) |
Lines 2244-2381
Link Here
|
2244 |
} |
2543 |
} |
2245 |
} |
2544 |
} |
2246 |
|
2545 |
|
2247 |
private void paint_line_old(Graphics g, Line l, int brow, |
|
|
2248 |
int xoff, int yoff, int baseline, |
2249 |
Extent selx) { |
2250 |
// draw the line on this brow (buffer row 0-origin) |
2251 |
|
2252 |
int length = l.length(); |
2253 |
if (length == 0) |
2254 |
return; |
2255 |
|
2256 |
int howmany = length-st.firsty; |
2257 |
if (howmany <= 0) |
2258 |
return; |
2259 |
|
2260 |
char buf[] = l.charArray(); |
2261 |
|
2262 |
if (! l.hasAttributes()) { |
2263 |
|
2264 |
if (debugWrap()) { |
2265 |
if (l.isWrapped() && l.isAboutToWrap()) |
2266 |
g.setColor(Color.red); // not a good state to be in |
2267 |
else if (l.isAboutToWrap()) |
2268 |
g.setColor(Color.pink); |
2269 |
else if (l.isWrapped()) |
2270 |
g.setColor(Color.magenta); |
2271 |
} |
2272 |
|
2273 |
g.drawChars(buf, st.firsty, howmany, xoff, baseline); |
2274 |
return; |
2275 |
} |
2276 |
|
2277 |
int attrs[] = l.attrArray(); |
2278 |
|
2279 |
int lastcol = st.firsty + howmany; |
2280 |
int x = xoff; |
2281 |
|
2282 |
for (int col = st.firsty; col < lastcol; col++) { |
2283 |
int attr = attrs[col]; |
2284 |
boolean reverse = ((attr & Attr.REVERSE) == Attr.REVERSE); |
2285 |
boolean active = ((attr & Attr.ACTIVE) == Attr.ACTIVE); |
2286 |
boolean need_rect = reverse || active; |
2287 |
boolean override_fg = false; |
2288 |
|
2289 |
// choose background color |
2290 |
// If we're doing 'reverse' video then we use FG colors for BG. |
2291 |
Color bg; |
2292 |
if (reverse) { |
2293 |
int fcx = Attr.foregroundColor(attr); |
2294 |
if (fcx != 0 && fcx <= 8) { |
2295 |
bg = standard_color[fcx-1]; |
2296 |
need_rect = true; |
2297 |
} else if (fcx != 0 && fcx > 8) { |
2298 |
bg = custom_color[fcx-9]; |
2299 |
need_rect = true; |
2300 |
} else { |
2301 |
bg = actual_foreground; |
2302 |
} |
2303 |
|
2304 |
} else { |
2305 |
int bcx = Attr.backgroundColor(attr); |
2306 |
if (bcx != 0 && bcx <= 8) { |
2307 |
bg = standard_color[bcx-1]; |
2308 |
need_rect = true; |
2309 |
} else if (bcx > 8) { |
2310 |
bg = custom_color[bcx-9]; |
2311 |
need_rect = true; |
2312 |
} else { |
2313 |
bg = actual_background; |
2314 |
} |
2315 |
} |
2316 |
|
2317 |
if (check_selection && |
2318 |
selx.intersects(firsta + brow, col)) { |
2319 |
|
2320 |
need_rect = false; |
2321 |
override_fg = true; |
2322 |
} |
2323 |
|
2324 |
if (need_rect) { |
2325 |
// Draw any background |
2326 |
if (active) { |
2327 |
g.setColor(active_color); |
2328 |
} else { |
2329 |
g.setColor(bg); |
2330 |
} |
2331 |
g.fillRect(x, yoff, |
2332 |
metrics.width, metrics.height - metrics.leading); |
2333 |
} |
2334 |
|
2335 |
// Set foreground color |
2336 |
Color fg; |
2337 |
if (override_fg) { |
2338 |
fg = actual_foreground; |
2339 |
} else if (reverse) { |
2340 |
int bcx = Attr.backgroundColor(attr); |
2341 |
if (bcx != 0 && bcx <= 8) { |
2342 |
fg = standard_color[bcx-1]; |
2343 |
} else if (bcx > 8) { |
2344 |
fg = custom_color[bcx-9]; |
2345 |
} else { |
2346 |
fg = actual_background; |
2347 |
} |
2348 |
|
2349 |
} else { |
2350 |
int fcx = Attr.foregroundColor(attr); |
2351 |
if (fcx != 0 && fcx <= 8) { |
2352 |
fg = standard_color[fcx-1]; |
2353 |
} else if (fcx != 0 && fcx > 8) { |
2354 |
fg = custom_color[fcx-9]; |
2355 |
} else { |
2356 |
fg = actual_foreground; |
2357 |
} |
2358 |
} |
2359 |
g.setColor(fg); |
2360 |
|
2361 |
// draw any underscores |
2362 |
if ( (attr & Attr.UNDERSCORE) == Attr.UNDERSCORE) { |
2363 |
int h = metrics.height - metrics.leading - 1; |
2364 |
g.drawLine(x, yoff+h, x + metrics.width, yoff+h); |
2365 |
} |
2366 |
|
2367 |
// Draw the foreground character glyphs |
2368 |
g.drawChars(buf, col, 1, x, baseline); |
2369 |
|
2370 |
// Draw fake bold characters by redrawing one pixel to the right |
2371 |
if ( (attr & Attr.BRIGHT) == Attr.BRIGHT) { |
2372 |
g.drawChars(buf, col, 1, x+1, baseline); |
2373 |
} |
2374 |
|
2375 |
x += metrics.width; |
2376 |
} |
2377 |
} |
2378 |
|
2379 |
synchronized void do_paint(Graphics g) { |
2546 |
synchronized void do_paint(Graphics g) { |
2380 |
|
2547 |
|
2381 |
/* |
2548 |
/* |
Lines 2391-2397
Link Here
|
2391 |
return; |
2558 |
return; |
2392 |
} |
2559 |
} |
2393 |
|
2560 |
|
2394 |
// long paint_start_time = System.currentTimeMillis(); |
2561 |
/* DEBUG |
|
|
2562 |
long paint_start_time = System.currentTimeMillis(); |
2563 |
*/ |
2564 |
|
2565 |
// If Screen is opaque it seems that there is a bug in Swing where |
2566 |
// the Graphics that we get here ends up with fonts other than what |
2567 |
// we assigned to Term. So we make doubly sure here. |
2568 |
g.setFont(getFont()); |
2395 |
|
2569 |
|
2396 |
n_paint++; |
2570 |
n_paint++; |
2397 |
|
2571 |
|
Lines 2456-2462
Link Here
|
2456 |
for (int vrow = 0; vrow < st.rows; vrow++) { |
2630 |
for (int vrow = 0; vrow < st.rows; vrow++) { |
2457 |
Line l = buf.lineAt(lx); |
2631 |
Line l = buf.lineAt(lx); |
2458 |
if (l == null) { |
2632 |
if (l == null) { |
|
|
2633 |
/* DEBUG |
2459 |
System.out.println("vrow " + vrow + " lx " + lx); // NOI18N |
2634 |
System.out.println("vrow " + vrow + " lx " + lx); // NOI18N |
|
|
2635 |
*/ |
2460 |
printStats(null); |
2636 |
printStats(null); |
2461 |
break; |
2637 |
break; |
2462 |
} |
2638 |
} |
Lines 2498-2506
Link Here
|
2498 |
if (debugMargins()) |
2674 |
if (debugMargins()) |
2499 |
paint_margins(g); |
2675 |
paint_margins(g); |
2500 |
|
2676 |
|
2501 |
// long paint_stop_time = System.currentTimeMillis(); |
2677 |
/* DEBUG |
2502 |
// long paint_time = paint_stop_time - paint_start_time; |
2678 |
long paint_stop_time = System.currentTimeMillis(); |
2503 |
// System.out.println("paint_time = " + paint_time); |
2679 |
long paint_time = paint_stop_time - paint_start_time; |
|
|
2680 |
System.out.println("paint_time = " + paint_time); // NOI18N |
2681 |
*/ |
2504 |
} |
2682 |
} |
2505 |
|
2683 |
|
2506 |
private void paint_margins(Graphics g) { |
2684 |
private void paint_margins(Graphics g) { |
Lines 2523-2529
Link Here
|
2523 |
} |
2701 |
} |
2524 |
|
2702 |
|
2525 |
int cursor_col = st.cursor.col - st.firsty; |
2703 |
int cursor_col = st.cursor.col - st.firsty; |
2526 |
if (cursor_col >= buf.visible_cols) { |
2704 |
if (cursor_col >= buf.visibleCols()) { |
|
|
2705 |
return; // cursor not visible |
2706 |
} else if (cursor_col < 0) { |
2527 |
return; // cursor not visible |
2707 |
return; // cursor not visible |
2528 |
} |
2708 |
} |
2529 |
|
2709 |
|
Lines 2532-2537
Link Here
|
2532 |
glyph_gutter_width + |
2712 |
glyph_gutter_width + |
2533 |
debug_gutter_width; |
2713 |
debug_gutter_width; |
2534 |
int rect_y = cursor_row * metrics.height; |
2714 |
int rect_y = cursor_row * metrics.height; |
|
|
2715 |
// we _don't_ make cursor as wide as underlying character |
2535 |
int rect_width = metrics.width; |
2716 |
int rect_width = metrics.width; |
2536 |
int rect_height = metrics.height - metrics.leading; |
2717 |
int rect_height = metrics.height - metrics.leading; |
2537 |
if (has_focus) |
2718 |
if (has_focus) |
Lines 2545-2551
Link Here
|
2545 |
private boolean possiblyScrollDown() { |
2726 |
private boolean possiblyScrollDown() { |
2546 |
/* |
2727 |
/* |
2547 |
* If cursor has moved below the scrollable region scroll down. |
2728 |
* If cursor has moved below the scrollable region scroll down. |
2548 |
* Buffer manipulation is party done here or at the callsite if |
2729 |
* Buffer manipulation is partly done here or at the callsite if |
2549 |
* 'true' is returned. |
2730 |
* 'true' is returned. |
2550 |
*/ |
2731 |
*/ |
2551 |
|
2732 |
|
Lines 2619-2625
Link Here
|
2619 |
* Perhaps SHOULD lock out sendChar() so user input doesn't interfere. |
2800 |
* Perhaps SHOULD lock out sendChar() so user input doesn't interfere. |
2620 |
*/ |
2801 |
*/ |
2621 |
private void reply(String str) { |
2802 |
private void reply(String str) { |
2622 |
// System.out.println("replying " + str); |
2803 |
// System.out.println("replying " + str); // NOI18N |
2623 |
for (int sx = 0; sx < str.length(); sx++) |
2804 |
for (int sx = 0; sx < str.length(); sx++) |
2624 |
sendChar(str.charAt(sx)); |
2805 |
sendChar(str.charAt(sx)); |
2625 |
} |
2806 |
} |
Lines 2653-2667
Link Here
|
2653 |
|
2834 |
|
2654 |
public void op_char(char c) { |
2835 |
public void op_char(char c) { |
2655 |
if (debugOps()) |
2836 |
if (debugOps()) |
2656 |
System.out.println("op_char('" + c + "')"); // NOI18N |
2837 |
System.out.println("op_char('" + c + "') = " + (int) c); // NOI18N |
2657 |
|
2838 |
|
2658 |
// generic character printing |
2839 |
// generic character printing |
2659 |
Line l = cursor_line(); |
2840 |
Line l = cursor_line(); |
2660 |
|
2841 |
|
2661 |
if (!st.overstrike) |
2842 |
int insertion_col = l.cellToBuf(metrics, st.cursor.col); |
2662 |
l.insertCharAt(buf, ' ', st.cursor.col, st.attr); |
2843 |
if (debugOps()) { |
|
|
2844 |
System.out.println("op_char(): st.cursor.col " + st.cursor.col + // NOI18N |
2845 |
" insertion_col " + insertion_col); // NOI18N |
2846 |
} |
2847 |
if (!st.overstrike) { |
2848 |
// This just shifts stuff the actual character gets put in below. |
2849 |
l.insertCharAt(Term.this, ' ', insertion_col, st.attr); |
2850 |
} |
2851 |
|
2852 |
int cwidth = metrics.wcwidth(c); |
2853 |
if (l.isAboutToWrap() || |
2854 |
(cwidth > 1 && |
2855 |
st.cursor.col + cwidth > buf.visibleCols() && |
2856 |
!horizontally_scrollable)) { |
2663 |
|
2857 |
|
2664 |
if (l.isAboutToWrap()) { |
|
|
2665 |
// 'wrap' the line |
2858 |
// 'wrap' the line |
2666 |
if (debugOps()) |
2859 |
if (debugOps()) |
2667 |
System.out.println("\twrapping it"); // NOI18N |
2860 |
System.out.println("\twrapping it"); // NOI18N |
Lines 2670-2686
Link Here
|
2670 |
op_line_feed(); |
2863 |
op_line_feed(); |
2671 |
op_carriage_return(); |
2864 |
op_carriage_return(); |
2672 |
l = cursor_line(); |
2865 |
l = cursor_line(); |
|
|
2866 |
insertion_col = 0; |
2673 |
// Fall thru |
2867 |
// Fall thru |
2674 |
} |
2868 |
} |
2675 |
|
2869 |
|
2676 |
l.setCharAt(buf, c, st.cursor.col, st.attr); // overstrike |
2870 |
l.setCharAt(Term.this, c, insertion_col, st.attr); // overstrike |
2677 |
st.cursor.col++; |
2871 |
st.cursor.col += cwidth; |
2678 |
|
2872 |
|
2679 |
if (st.cursor.col >= buf.visible_cols && !horizontally_scrollable) { |
2873 |
if (st.cursor.col >= buf.visibleCols() && !horizontally_scrollable) { |
2680 |
if (debugOps()) |
2874 |
if (debugOps()) |
2681 |
System.out.println("\tabout to wrap"); // NOI18N |
2875 |
System.out.println("\tabout to wrap"); // NOI18N |
2682 |
l.setAboutToWrap(true); |
2876 |
l.setAboutToWrap(true); |
2683 |
st.cursor.col--; |
2877 |
st.cursor.col -= cwidth; |
2684 |
} |
2878 |
} |
2685 |
} |
2879 |
} |
2686 |
|
2880 |
|
Lines 2701-2712
Link Here
|
2701 |
System.out.println("op_back_space"); // NOI18N |
2895 |
System.out.println("op_back_space"); // NOI18N |
2702 |
|
2896 |
|
2703 |
if (st.cursor.col > 0) { |
2897 |
if (st.cursor.col > 0) { |
2704 |
if (! cursor_line().isAboutToWrap()) |
2898 |
if (! cursor_line().isAboutToWrap()) { |
2705 |
st.cursor.col--; |
2899 |
st.cursor.col--; |
|
|
2900 |
} |
2706 |
cursor_line().setAboutToWrap(false); |
2901 |
cursor_line().setAboutToWrap(false); |
2707 |
|
2902 |
|
2708 |
// If we' backed up to column 0, maybe we need to consider |
2903 |
// If we' backed up to column 0, maybe we need to consider |
2709 |
// whether the previous line was wrapped. Oldr xterms aren't |
2904 |
// whether the previous line was wrapped. Older xterms aren't |
2710 |
// this clever, newer ones (Solaris 8+?) are. |
2905 |
// this clever, newer ones (Solaris 8+?) are. |
2711 |
|
2906 |
|
2712 |
if (st.cursor.col == 0) { |
2907 |
if (st.cursor.col == 0) { |
Lines 2719-2726
Link Here
|
2719 |
if (debugOps()) |
2914 |
if (debugOps()) |
2720 |
System.out.println("\tit is"); // NOI18N |
2915 |
System.out.println("\tit is"); // NOI18N |
2721 |
st.cursor.row--; |
2916 |
st.cursor.row--; |
2722 |
st.cursor.col = prev.length()-1; |
2917 |
|
|
|
2918 |
// The below is done in a roundabout way because BS doesn't |
2919 |
// really reduce length. So, suppose we went to the end with |
2920 |
// latin chars that makes the line 80 long. Then we backspace |
2921 |
// to column 78 and enter one 2-cell japanese character. Now |
2922 |
// the line is conceptually 79 long, but it still remembers |
2923 |
// the 80. So we don't use 'prev.length()' directly. |
2924 |
|
2925 |
// st.cursor.col = prev.bufToCell(metrics, prev.length()-1); |
2926 |
|
2927 |
int last_col = prev.cellToBuf(metrics, buf.visibleCols()-1); |
2928 |
st.cursor.col = prev.bufToCell(metrics, last_col); |
2929 |
|
2723 |
prev.setWrapped(false); |
2930 |
prev.setWrapped(false); |
|
|
2931 |
|
2932 |
// The following isn't entirely correct when we backspaced |
2933 |
// over a multi-celled character. SHOULD either note |
2934 |
// what we BS'ed over or note the slop at the end of the line. |
2724 |
prev.setAboutToWrap(true); |
2935 |
prev.setAboutToWrap(true); |
2725 |
} |
2936 |
} |
2726 |
} |
2937 |
} |
Lines 2735-2740
Link Here
|
2735 |
if (debugOps()) |
2946 |
if (debugOps()) |
2736 |
System.out.println("op_line_feed"); // NOI18N |
2947 |
System.out.println("op_line_feed"); // NOI18N |
2737 |
Line last_line = cursor_line(); |
2948 |
Line last_line = cursor_line(); |
|
|
2949 |
/* DEBUG |
2950 |
if (last_line == null) { |
2951 |
Thread.dumpStack(); |
2952 |
printStats("last_line == null in op_line_feed()");// NOI18N |
2953 |
} |
2954 |
*/ |
2738 |
st.cursor.row++; |
2955 |
st.cursor.row++; |
2739 |
if (possiblyScrollDown()) { |
2956 |
if (possiblyScrollDown()) { |
2740 |
buf.addLineAt(st.cursor.row); |
2957 |
buf.addLineAt(st.cursor.row); |
Lines 2743-2750
Link Here
|
2743 |
System.out.println("op_line_feed ADJUSTED"); // NOI18N |
2960 |
System.out.println("op_line_feed ADJUSTED"); // NOI18N |
2744 |
} |
2961 |
} |
2745 |
// have new line inherit cursorAtEnd |
2962 |
// have new line inherit cursorAtEnd |
2746 |
cursor_line().setAboutToWrap(last_line.isAboutToWrap()); |
2963 |
boolean atw = last_line.isAboutToWrap(); |
|
|
2964 |
cursor_line().setAboutToWrap(atw); |
2747 |
last_line.setAboutToWrap(false); |
2965 |
last_line.setAboutToWrap(false); |
|
|
2966 |
|
2967 |
n_linefeeds++; |
2968 |
|
2969 |
// See repaint() for an explanation of this. |
2970 |
// repaint(false); |
2748 |
} |
2971 |
} |
2749 |
|
2972 |
|
2750 |
public void op_tab() { |
2973 |
public void op_tab() { |
Lines 2756-2770
Link Here
|
2756 |
if (debugOps()) |
2979 |
if (debugOps()) |
2757 |
System.out.println("op_tab"); // NOI18N |
2980 |
System.out.println("op_tab"); // NOI18N |
2758 |
|
2981 |
|
2759 |
if (st.cursor.col == buf.visible_cols-1 && !horizontally_scrollable) |
2982 |
if (st.cursor.col == buf.visibleCols()-1 && !horizontally_scrollable) |
2760 |
return; |
2983 |
return; |
2761 |
|
2984 |
|
2762 |
cursor_line().setCharAt(buf, ' ', st.cursor.col, st.attr); |
2985 |
Line l = cursor_line(); |
|
|
2986 |
int insert_col = l.cellToBuf(metrics, st.cursor.col); |
2987 |
l.setCharAt(Term.this, ' ', insert_col, st.attr); |
2763 |
st.cursor.col++; |
2988 |
st.cursor.col++; |
2764 |
while ((st.cursor.col < buf.visible_cols-1 || horizontally_scrollable) && |
2989 |
insert_col++; |
|
|
2990 |
// no need to re-apply cellToBuf to cursor since we're only adding 1-wide ' ' |
2991 |
while ((st.cursor.col < buf.visibleCols()-1 || horizontally_scrollable) && |
2765 |
(st.cursor.col % tab_size) != 0) { |
2992 |
(st.cursor.col % tab_size) != 0) { |
2766 |
cursor_line().setCharAt(buf, ' ', st.cursor.col, st.attr); |
2993 |
cursor_line().setCharAt(Term.this, ' ', insert_col, st.attr); |
2767 |
st.cursor.col++; |
2994 |
st.cursor.col++; |
|
|
2995 |
insert_col++; |
2768 |
} |
2996 |
} |
2769 |
} |
2997 |
} |
2770 |
|
2998 |
|
Lines 2782-2800
Link Here
|
2782 |
|
3010 |
|
2783 |
Line l; |
3011 |
Line l; |
2784 |
while (count-- > 0) { |
3012 |
while (count-- > 0) { |
2785 |
boolean old_cae = cursor_line().setAboutToWrap(false); |
3013 |
boolean old_atw = cursor_line().setAboutToWrap(false); |
2786 |
|
3014 |
|
2787 |
// reverse of op_dl() |
3015 |
// reverse of op_dl() |
2788 |
// Rotate a line from bottom to top |
3016 |
// Rotate a line from bottom to top |
2789 |
if (!do_margins) { |
3017 |
if (!do_margins) { |
2790 |
l = buf.moveLineFromTo(buf.nlines-1, st.cursor.row); |
3018 |
l = buf.moveLineFromTo(buf.nlines-1, st.cursor.row); |
2791 |
} else { |
3019 |
} else { |
2792 |
l = buf.moveLineFromTo(st.firstx + botMargin(), |
3020 |
l = buf.moveLineFromTo(st.firstx + botMargin(), st.cursor.row); |
2793 |
st.cursor.row); |
|
|
2794 |
} |
3021 |
} |
2795 |
l.reset(); |
3022 |
l.reset(); |
2796 |
|
3023 |
|
2797 |
cursor_line().setAboutToWrap(old_cae); |
3024 |
cursor_line().setAboutToWrap(old_atw); |
2798 |
} |
3025 |
} |
2799 |
|
3026 |
|
2800 |
switch(sel.intersection(st.cursor.row - 1)) { |
3027 |
switch(sel.intersection(st.cursor.row - 1)) { |
Lines 2817-2823
Link Here
|
2817 |
if (debugOps()) |
3044 |
if (debugOps()) |
2818 |
System.out.println("op_bc(" + count + ")"); // NOI18N |
3045 |
System.out.println("op_bc(" + count + ")"); // NOI18N |
2819 |
|
3046 |
|
2820 |
while(count-- > 0) { |
3047 |
while (count-- > 0) { |
2821 |
if (st.cursor.col <= 0) |
3048 |
if (st.cursor.col <= 0) |
2822 |
return; |
3049 |
return; |
2823 |
st.cursor.col--; |
3050 |
st.cursor.col--; |
Lines 2841-2848
Link Here
|
2841 |
// deal with overflow |
3068 |
// deal with overflow |
2842 |
if (row > st.rows) |
3069 |
if (row > st.rows) |
2843 |
row = st.rows; |
3070 |
row = st.rows; |
2844 |
if (col > buf.visible_cols) |
3071 |
if (col > buf.visibleCols()) |
2845 |
col = buf.visible_cols; |
3072 |
col = buf.visibleCols(); |
2846 |
|
3073 |
|
2847 |
cursor_line().setAboutToWrap(false); |
3074 |
cursor_line().setAboutToWrap(false); |
2848 |
st.cursor.row = beginx() + row - 1; |
3075 |
st.cursor.row = beginx() + row - 1; |
Lines 2865-2872
Link Here
|
2865 |
if (debugOps()) |
3092 |
if (debugOps()) |
2866 |
System.out.println("op_ce"); // NOI18N |
3093 |
System.out.println("op_ce"); // NOI18N |
2867 |
|
3094 |
|
2868 |
Line l = buf.lineAt(st.cursor.row); |
3095 |
Line l = cursor_line(); |
2869 |
l.clearToEndFrom(buf, st.cursor.col); |
3096 |
l.clearToEndFrom(Term.this, l.cellToBuf(metrics, st.cursor.col)); |
2870 |
|
3097 |
|
2871 |
switch(sel.intersection(st.cursor.row)) { |
3098 |
switch(sel.intersection(st.cursor.row)) { |
2872 |
case Sel.INT_NONE: |
3099 |
case Sel.INT_NONE: |
Lines 2912-2918
Link Here
|
2912 |
count = 1; |
3139 |
count = 1; |
2913 |
Line l = cursor_line(); |
3140 |
Line l = cursor_line(); |
2914 |
while (count-- > 0) |
3141 |
while (count-- > 0) |
2915 |
cursor_line().deleteCharAt(st.cursor.col); |
3142 |
l.deleteCharAt(l.cellToBuf(metrics, st.cursor.col)); |
2916 |
} |
3143 |
} |
2917 |
|
3144 |
|
2918 |
public void op_dl(int count) { |
3145 |
public void op_dl(int count) { |
Lines 2923-2929
Link Here
|
2923 |
|
3150 |
|
2924 |
Line l; |
3151 |
Line l; |
2925 |
while (count-- > 0) { |
3152 |
while (count-- > 0) { |
2926 |
boolean old_cae = cursor_line().setAboutToWrap(false); |
3153 |
boolean old_atw = cursor_line().setAboutToWrap(false); |
2927 |
|
3154 |
|
2928 |
// reverse of op_al() |
3155 |
// reverse of op_al() |
2929 |
// Rotate a line from top to bottom |
3156 |
// Rotate a line from top to bottom |
Lines 2936-2942
Link Here
|
2936 |
} |
3163 |
} |
2937 |
l.reset(); |
3164 |
l.reset(); |
2938 |
|
3165 |
|
2939 |
cursor_line().setAboutToWrap(old_cae); |
3166 |
cursor_line().setAboutToWrap(old_atw); |
2940 |
} |
3167 |
} |
2941 |
|
3168 |
|
2942 |
switch(sel.intersection(st.cursor.row)) { |
3169 |
switch(sel.intersection(st.cursor.row)) { |
Lines 2955-2973
Link Here
|
2955 |
} |
3182 |
} |
2956 |
|
3183 |
|
2957 |
public void op_do(int count) { |
3184 |
public void op_do(int count) { |
|
|
3185 |
// down count lines |
2958 |
// SHOULD add a mode: {scroll, warp, stay} for cases where |
3186 |
// SHOULD add a mode: {scroll, warp, stay} for cases where |
2959 |
// cursor is on the bottom line. |
3187 |
// cursor is on the bottom line. |
2960 |
|
3188 |
|
2961 |
// down count lines |
|
|
2962 |
if (debugOps()) |
3189 |
if (debugOps()) |
2963 |
System.out.println("op_do(" + count + ") -- down"); // NOI18N |
3190 |
System.out.println("op_do(" + count + ") -- down"); // NOI18N |
2964 |
|
3191 |
|
2965 |
boolean old_cae = cursor_line().setAboutToWrap(false); |
3192 |
boolean old_atw = cursor_line().setAboutToWrap(false); |
2966 |
|
3193 |
|
2967 |
while (count-- > 0) { |
3194 |
while (count-- > 0) { |
2968 |
st.cursor.row++; |
3195 |
st.cursor.row++; |
2969 |
if (st.cursor.row >= buf.nlines) { |
3196 |
if (st.cursor.row >= buf.nlines) { |
2970 |
// st.cursor.row--; // don't go beyond bottomline |
|
|
2971 |
|
3197 |
|
2972 |
// equivalent of op_newline: |
3198 |
// equivalent of op_newline: |
2973 |
if (possiblyScrollDown()) { |
3199 |
if (possiblyScrollDown()) { |
Lines 2978-2984
Link Here
|
2978 |
} |
3204 |
} |
2979 |
} |
3205 |
} |
2980 |
} |
3206 |
} |
2981 |
cursor_line().setAboutToWrap(old_cae); |
3207 |
cursor_line().setAboutToWrap(old_atw); |
2982 |
} |
3208 |
} |
2983 |
|
3209 |
|
2984 |
public void op_ho() { |
3210 |
public void op_ho() { |
Lines 2995-3002
Link Here
|
2995 |
if (debugOps()) |
3221 |
if (debugOps()) |
2996 |
System.out.println("op_ic(" + count + ")"); // NOI18N |
3222 |
System.out.println("op_ic(" + count + ")"); // NOI18N |
2997 |
|
3223 |
|
2998 |
while (count-- > 0) |
3224 |
Line l = cursor_line(); |
2999 |
cursor_line().insertCharAt(buf, ' ', st.cursor.col, st.attr); |
3225 |
int insertion_col = l.cellToBuf(metrics, st.cursor.col); |
|
|
3226 |
while (count-- > 0) { |
3227 |
l.insertCharAt(Term.this, ' ', insertion_col, st.attr); |
3228 |
} |
3229 |
// SHOULD worry about line wrapping |
3000 |
} |
3230 |
} |
3001 |
|
3231 |
|
3002 |
public void op_nd(int count) { |
3232 |
public void op_nd(int count) { |
Lines 3004-3018
Link Here
|
3004 |
if (debugOps()) |
3234 |
if (debugOps()) |
3005 |
System.out.println("op_nd(" + count + ")"); // NOI18N |
3235 |
System.out.println("op_nd(" + count + ")"); // NOI18N |
3006 |
|
3236 |
|
|
|
3237 |
int vc = st.cursor.col; |
3007 |
while (count-- > 0) { |
3238 |
while (count-- > 0) { |
3008 |
st.cursor.col++; |
3239 |
vc++; |
3009 |
if (st.cursor.col >= buf.visible_cols) { |
3240 |
if (vc >= buf.visibleCols()) { |
3010 |
if (debugOps()) |
3241 |
if (debugOps()) |
3011 |
System.out.println("\tbailing out at count " + count); // NOI18N |
3242 |
System.out.println("\tbailing out at count " + count); // NOI18N |
3012 |
st.cursor.col--; |
3243 |
vc--; |
3013 |
return; |
3244 |
break; |
3014 |
} |
3245 |
} |
3015 |
} |
3246 |
} |
|
|
3247 |
st.cursor.col = vc; |
3016 |
} |
3248 |
} |
3017 |
|
3249 |
|
3018 |
public void op_up(int count) { |
3250 |
public void op_up(int count) { |
Lines 3020-3026
Link Here
|
3020 |
if (debugOps()) |
3252 |
if (debugOps()) |
3021 |
System.out.println("op_up(" + count + ")"); // NOI18N |
3253 |
System.out.println("op_up(" + count + ")"); // NOI18N |
3022 |
|
3254 |
|
3023 |
boolean old_cae = cursor_line().setAboutToWrap(false); |
3255 |
boolean old_atw = cursor_line().setAboutToWrap(false); |
3024 |
Line l; |
3256 |
Line l; |
3025 |
while (count-- > 0) { |
3257 |
while (count-- > 0) { |
3026 |
st.cursor.row--; |
3258 |
st.cursor.row--; |
Lines 3030-3043
Link Here
|
3030 |
if (!do_margins) { |
3262 |
if (!do_margins) { |
3031 |
l = buf.moveLineFromTo(buf.nlines-1, st.cursor.row); |
3263 |
l = buf.moveLineFromTo(buf.nlines-1, st.cursor.row); |
3032 |
} else { |
3264 |
} else { |
3033 |
l = buf.moveLineFromTo(st.firstx + botMargin(), |
3265 |
l = buf.moveLineFromTo(st.firstx + botMargin(), st.cursor.row); |
3034 |
st.cursor.row); |
|
|
3035 |
} |
3266 |
} |
3036 |
l.reset(); |
3267 |
l.reset(); |
3037 |
// SHOULD note and do something about the selection? |
3268 |
// SHOULD note and do something about the selection? |
3038 |
} |
3269 |
} |
3039 |
} |
3270 |
} |
3040 |
cursor_line().setAboutToWrap(old_cae); |
3271 |
cursor_line().setAboutToWrap(old_atw); |
3041 |
} |
3272 |
} |
3042 |
|
3273 |
|
3043 |
public void op_sc() { |
3274 |
public void op_sc() { |
Lines 3072-3078
Link Here
|
3072 |
} |
3303 |
} |
3073 |
|
3304 |
|
3074 |
public void op_margin(int from, int to) { |
3305 |
public void op_margin(int from, int to) { |
3075 |
// System.out.println("op_margin(" + from + ", " + to + ")"); // NOI18N |
3306 |
if (debugOps()) { |
|
|
3307 |
System.out.println("op_margin(" + from + ", " + // NOI18N |
3308 |
to + ")"); // NOI18N |
3309 |
} |
3076 |
|
3310 |
|
3077 |
if (from < 0) |
3311 |
if (from < 0) |
3078 |
top_margin = 0; |
3312 |
top_margin = 0; |
Lines 3106-3111
Link Here
|
3106 |
String output1 = date_str + " Elapsed (sec): " + elapsed_str;// NOI18N |
3340 |
String output1 = date_str + " Elapsed (sec): " + elapsed_str;// NOI18N |
3107 |
String output2 = "putChar " + n_putchar + // NOI18N |
3341 |
String output2 = "putChar " + n_putchar + // NOI18N |
3108 |
" putChars " + n_putchars + // NOI18N |
3342 |
" putChars " + n_putchars + // NOI18N |
|
|
3343 |
" linefeeds " + n_linefeeds + // NOI18N |
3109 |
" repaint " + n_repaint + // NOI18N |
3344 |
" repaint " + n_repaint + // NOI18N |
3110 |
" paint " + n_paint; // NOI18N |
3345 |
" paint " + n_paint; // NOI18N |
3111 |
|
3346 |
|
Lines 3125-3130
Link Here
|
3125 |
last_time = time; |
3360 |
last_time = time; |
3126 |
n_putchar = 0; |
3361 |
n_putchar = 0; |
3127 |
n_putchars = 0; |
3362 |
n_putchars = 0; |
|
|
3363 |
n_linefeeds = 0; |
3128 |
n_paint = 0; |
3364 |
n_paint = 0; |
3129 |
n_repaint = 0; |
3365 |
n_repaint = 0; |
3130 |
|
3366 |
|
Lines 3133-3139
Link Here
|
3133 |
} |
3369 |
} |
3134 |
|
3370 |
|
3135 |
public int op_get_width() { |
3371 |
public int op_get_width() { |
3136 |
return horizontally_scrollable? buf.totalCols(): buf.visible_cols; |
3372 |
return horizontally_scrollable? buf.totalCols(): buf.visibleCols(); |
3137 |
} |
3373 |
} |
3138 |
|
3374 |
|
3139 |
public int op_get_column() { |
3375 |
public int op_get_column() { |
Lines 3228-3236
Link Here
|
3228 |
// So extent has to be set to visible-range - 1: |
3464 |
// So extent has to be set to visible-range - 1: |
3229 |
|
3465 |
|
3230 |
// It's important that we do this from within the AWT event thread. |
3466 |
// It's important that we do this from within the AWT event thread. |
3231 |
// This is primarily ensured by the use of Swing.invokeAndWait() |
|
|
3232 |
// in StreamTerm. |
3233 |
|
3467 |
|
|
|
3468 |
if (SwingUtilities.isEventDispatchThread()) { |
3469 |
adjust_scrollbar_impl(); |
3470 |
} |
3471 |
else { |
3472 |
SwingUtilities.invokeLater(new Runnable() { |
3473 |
public void run() { |
3474 |
adjust_scrollbar_impl(); |
3475 |
} |
3476 |
}); |
3477 |
} |
3478 |
} |
3479 |
|
3480 |
private void adjust_scrollbar_impl() { |
3234 |
if (vscroll_bar != null) { |
3481 |
if (vscroll_bar != null) { |
3235 |
int value = st.firstx; |
3482 |
int value = st.firstx; |
3236 |
int extent = st.rows-1; |
3483 |
int extent = st.rows-1; |
Lines 3245-3255
Link Here
|
3245 |
|
3492 |
|
3246 |
if (hscroll_bar != null && horizontally_scrollable) { |
3493 |
if (hscroll_bar != null && horizontally_scrollable) { |
3247 |
int value = st.firsty; |
3494 |
int value = st.firsty; |
3248 |
int extent = buf.visible_cols-1; |
3495 |
int extent = buf.visibleCols()-1; |
3249 |
int min = 0; |
3496 |
int min = 0; |
3250 |
int max; |
3497 |
int max; |
3251 |
if (buf.totalCols() <= buf.visible_cols) |
3498 |
if (buf.totalCols() <= buf.visibleCols()) |
3252 |
max = buf.visible_cols - 1; |
3499 |
max = buf.visibleCols() - 1; |
3253 |
else |
3500 |
else |
3254 |
max = buf.totalCols() - 1; |
3501 |
max = buf.totalCols() - 1; |
3255 |
hscroll_bar.setValues(value, extent, min, max); |
3502 |
hscroll_bar.setValues(value, extent, min, max); |
Lines 3260-3266
Link Here
|
3260 |
* Figure the pixel size of the screen based on various properties. |
3507 |
* Figure the pixel size of the screen based on various properties. |
3261 |
*/ |
3508 |
*/ |
3262 |
private Dimension calculateSize() { |
3509 |
private Dimension calculateSize() { |
3263 |
int dx = buf.visible_cols * metrics.width + |
3510 |
int dx = buf.visibleCols() * metrics.width + |
3264 |
glyph_gutter_width + |
3511 |
glyph_gutter_width + |
3265 |
debug_gutter_width; |
3512 |
debug_gutter_width; |
3266 |
int dy = st.rows * metrics.height; |
3513 |
int dy = st.rows * metrics.height; |
Lines 3306-3312
Link Here
|
3306 |
*/ |
3553 |
*/ |
3307 |
|
3554 |
|
3308 |
void sizeChanged(int newWidth, int newHeight) { |
3555 |
void sizeChanged(int newWidth, int newHeight) { |
3309 |
/* |
3556 |
/* DEBUG |
3310 |
System.out.println("sizeChanged(newheight " + newHeight + // NOI18N |
3557 |
System.out.println("sizeChanged(newheight " + newHeight + // NOI18N |
3311 |
", newWidth " + newWidth + ")"); |
3558 |
", newWidth " + newWidth + ")"); |
3312 |
*/ |
3559 |
*/ |
Lines 3379-3388
Link Here
|
3379 |
repaint(adjust_scrollbar); |
3626 |
repaint(adjust_scrollbar); |
3380 |
} |
3627 |
} |
3381 |
|
3628 |
|
|
|
3629 |
/** |
3630 |
* Model and or view settings have changed, redraw everything. |
3631 |
*/ |
3382 |
protected void repaint(boolean adjust_scrollbar) { |
3632 |
protected void repaint(boolean adjust_scrollbar) { |
3383 |
|
3633 |
|
3384 |
/* |
3634 |
/* |
3385 |
* Model and or view settings have changed, redraw everything. |
3635 |
* A long discussion on performance and smooth vs jump vs jerky |
|
|
3636 |
* scrolling ... (note: a lot of this is based on experiments with |
3637 |
* Term as a unix terminal emulator application as opposed to |
3638 |
* within the context of NetBeans). |
3639 |
* |
3640 |
* Term spends it's time between collecting and deciphering input |
3641 |
* and repainting the screen. Input processing always goes on, but |
3642 |
* screen repainitng can be done more or less often to trade off |
3643 |
* smoothness of scrolling vs speed. |
3644 |
* |
3645 |
* At one end is so-called smooth scrolling. This is where the |
3646 |
* screen is redrawn on every linefeed. That's a lot of painting. |
3647 |
* To get into that mode use the paintImmediately() below and |
3648 |
* uncomment the call to us in op_line_feed(). Also |
3649 |
* paintImmediately() doesn't really work unless the Screen is |
3650 |
* opaque. I think that is because the paint request comes |
3651 |
* to us and we don't forward it to screen; but it could be a |
3652 |
* Swing bug too. Term is very slow in this. For example I"ve |
3653 |
* time xterm and DtTerm dealing with "cat /etc/termcap" in 2-3 |
3654 |
* seconds while Term takes 20-25 seconds. Part of this is |
3655 |
* attributed to the fact that Term doesn't take advantage of |
3656 |
* bitBlitting when it's adding one line at a time and still |
3657 |
* redraws everything. However I'll make a case below that this |
3658 |
* isn't that important. |
3659 |
* |
3660 |
* Then there is so-called jump scrolling. In this regime terminal |
3661 |
* emulators redraw the screen "as time permits". This is in effect |
3662 |
* what the swing repaint manager helps with. Multiple repaint() |
3663 |
* requests translate to one actual paint(). With todays computers |
3664 |
* it's very hard to tell visually that you're jump scrolling |
3665 |
* things go by so fast (yes, even under Swing), so this is the |
3666 |
* preferred setup. |
3667 |
* Here term does a bit better. To deal with a cat'ed 100,000 |
3668 |
* line file DtTerm takes 8 seconds, while Term takes 22 seconds. |
3669 |
* (That's 3 times slower vs 8 times). From some measurements |
3670 |
* I've made the number of linefeeds per actual paints has |
3671 |
* ranged from > 100 to upper 30's. These numbers are sufficiently |
3672 |
* high that the whole screen has to be repained everytime. |
3673 |
* I.e. blitting to scroll and drawing only what's new isn't |
3674 |
* going to help here. To get reasonable jump-scrolling, you need |
3675 |
* to make sure that the Screen is opaque because if you don't |
3676 |
* you will get ... |
3677 |
* |
3678 |
* Jerky scrolling. If Term is not opaque, the number of actual |
3679 |
* paints per repaint() requests diminishes drastically. 'cat' of |
3680 |
* etc/termcap (once the code has been warmed up) sometimes causes |
3681 |
* a single refresh at the end in contrast to ~100 when Screen |
3682 |
* is opaque. Naturally Term in this mode can eat up input at |
3683 |
* a rate comparable to dtterm etc, but the jerkiness is very |
3684 |
* ugly. |
3685 |
* Opacity isn't the only criterion. Term, when embeded inside a |
3686 |
* tabbed pane (like it is in NetBeans) will also act as if it's |
3687 |
* opaque and you get more frequent refreshes, as in the |
3688 |
* jump-scrolling regime. But that was way too slow for the |
3689 |
* taste of NB users which is why OutputTab window calls us on a |
3690 |
* timer. That brings it's own jerkiness of a different sort. |
3691 |
* |
3692 |
* There is a third factor that contributes to slowness. If you |
3693 |
* just 'cat' a file you get the numbers I presneted above. But |
3694 |
* if you run an app that actually puts out the 100,000 lines |
3695 |
* some sort of timing interaction forces Term into near smooth |
3696 |
* scrolling and as a result things slow down a lot! For example, |
3697 |
* $ generate_100K_lines > /tmp/bag 00:08 sec |
3698 |
* $ cat /tmp/bag 00:20 sec |
3699 |
* $ generate_100K_lines 03:42 sec (opaque) |
3700 |
* $ generate_100K_lines 01:58 sec (!opaque) |
3701 |
* This happens even if the generating program is a lightweight |
3702 |
* native application. In fact I believe it is this effect that |
3703 |
* forced NB's OutputTab to adopt the timer. I believe there are two |
3704 |
* factors that contrinute to this. |
3705 |
* a) Running applications are line buffered so putChars(), with |
3706 |
* it's attendant repaint(), gets called once per line pushing |
3707 |
* us into the smooth scrolling regime. (But why then doesn't |
3708 |
* DtTerm suffer from this?) |
3709 |
* b) timeslicing gives enough time to the repaint manager such |
3710 |
* that it converts evey repaint() to a paint. |
3711 |
* I know (b) is a factor since if I "simulate" (a) by issueing |
3712 |
* repaints() from op_line_feed() while keeping this function from |
3713 |
* using paintImmediately() I don't get that many paints. |
3714 |
* The combined case has 44 paints per repaint as does simulated (a). |
3715 |
* So ain increased number of paints per repaint doesn't |
3716 |
* explain this. |
3717 |
* |
3718 |
* In the end, currently since jump scrolling is still not very |
3719 |
* fast and since NB has the timer anyway, Screen is not opaque. |
3720 |
* |
3721 |
* A useful quantitative measure is the number of linefeeds vs |
3722 |
* the number of repaint requests vs the number of actual paints. |
3723 |
* All these are collected and can be dumped via op_time() or |
3724 |
* printStats(). |
3386 |
*/ |
3725 |
*/ |
3387 |
|
3726 |
|
3388 |
n_repaint++; |
3727 |
n_repaint++; |
Lines 3394-3399
Link Here
|
3394 |
// The following causes Screen.paint() to get called by the Swing |
3733 |
// The following causes Screen.paint() to get called by the Swing |
3395 |
// repaint manager which in turn calls back to term.paint(Graphics). |
3734 |
// repaint manager which in turn calls back to term.paint(Graphics). |
3396 |
screen.repaint(); |
3735 |
screen.repaint(); |
|
|
3736 |
|
3737 |
|
3738 |
// The following should cause an immediate paint. It doesn't |
3739 |
// always though! |
3740 |
// I've found that for it to be effective Screen needs to be opaque. |
3741 |
|
3742 |
/* |
3743 |
NOTE: paintImmediately() is probably not the best thing to use. |
3744 |
// RepaintManager.currentManager(screen).paintDirtyRegions(); |
3745 |
screen.paintImmediately(0, 0, screen.getWidth(), screen.getHeight()); |
3746 |
*/ |
3397 |
} |
3747 |
} |
3398 |
|
3748 |
|
3399 |
/* |
3749 |
/* |
Lines 3560-3566
Link Here
|
3560 |
return interp; |
3910 |
return interp; |
3561 |
} |
3911 |
} |
3562 |
|
3912 |
|
3563 |
private Interp interp = new InterpANSI(ops); |
3913 |
private Interp interp = new InterpDumb(ops); // used to InterpANSI |
3564 |
|
3914 |
|
3565 |
|
3915 |
|
3566 |
/** |
3916 |
/** |
Lines 3644-3672
Link Here
|
3644 |
} |
3994 |
} |
3645 |
|
3995 |
|
3646 |
/** |
3996 |
/** |
3647 |
* Get cursor column (0-origin) |
3997 |
* Get cursor column in buffer coordinates (0-origin) |
3648 |
*/ |
3998 |
*/ |
3649 |
public int getCursorCol() { |
3999 |
public int getCursorCol() { |
3650 |
return st.cursor.col; |
4000 |
return cursor_line().cellToBuf(metrics, st.cursor.col); |
3651 |
} |
4001 |
} |
3652 |
|
4002 |
|
3653 |
/** |
4003 |
/** |
3654 |
* Get (view) cursor coordinates. |
4004 |
* Get (absolute) cursor coordinates. |
3655 |
* <p> |
4005 |
* <p> |
3656 |
* The returned Coord is newly allocated and need not be cloned. |
4006 |
* The returned Coord is newly allocated and need not be cloned. |
3657 |
*/ |
4007 |
*/ |
3658 |
public Coord getCursorCoord() { |
4008 |
public Coord getCursorCoord() { |
3659 |
return new Coord(new BCoord(st.cursor.row, st.cursor.col), firsta); |
4009 |
Line l = buf.lineAt(st.cursor.row); |
|
|
4010 |
return new Coord(new BCoord(st.cursor.row, |
4011 |
l.cellToBuf(metrics, st.cursor.col)), |
4012 |
firsta); |
4013 |
} |
4014 |
|
4015 |
/* |
4016 |
* |
4017 |
* Move the cursor to the given (absolute) coordinates |
4018 |
* |
4019 |
* @deprecated, replaced by{@link #setCursorCoord(Coord)} |
4020 |
*/ |
4021 |
public void goTo(Coord coord) { |
4022 |
setCursorCoord(coord); |
3660 |
} |
4023 |
} |
3661 |
|
4024 |
|
3662 |
/** |
4025 |
/** |
3663 |
* Move the cursor to the given (view) coordinates |
4026 |
* Move the cursor to the given (absolute) coordinates |
3664 |
* SHOULD be setCursorCoord! |
4027 |
* SHOULD be setCursorCoord! |
3665 |
*/ |
4028 |
*/ |
3666 |
public void goTo(Coord coord) { |
4029 |
public void setCursorCoord(Coord coord) { |
3667 |
Coord c = (Coord) coord.clone(); |
4030 |
Coord c = (Coord) coord.clone(); |
3668 |
c.clip(st.rows, buf.visible_cols, firsta); |
4031 |
c.clip(st.rows, buf.visibleCols(), firsta); |
3669 |
st.cursor = c.toBCoord(firsta); |
4032 |
st.cursor = c.toBCoord(firsta); |
|
|
4033 |
st.cursor.col = cursor_line().bufToCell(metrics, st.cursor.col); |
3670 |
repaint(true); |
4034 |
repaint(true); |
3671 |
} |
4035 |
} |
3672 |
|
4036 |
|
Lines 4012-4019
Link Here
|
4012 |
public void columnRight(int n) { |
4376 |
public void columnRight(int n) { |
4013 |
synchronized(this) { |
4377 |
synchronized(this) { |
4014 |
st.firsty += n; |
4378 |
st.firsty += n; |
4015 |
if (st.firsty + buf.visible_cols > buf.totalCols()) |
4379 |
if (st.firsty + buf.visibleCols() > buf.totalCols()) |
4016 |
st.firsty = buf.totalCols() - buf.visible_cols; |
4380 |
st.firsty = buf.totalCols() - buf.visibleCols(); |
4017 |
} |
4381 |
} |
4018 |
repaint(true); |
4382 |
repaint(true); |
4019 |
} |
4383 |
} |
Lines 4030-4035
Link Here
|
4030 |
repaint(true); |
4394 |
repaint(true); |
4031 |
} |
4395 |
} |
4032 |
|
4396 |
|
|
|
4397 |
/** |
4398 |
* Return the cell width of the given character. |
4399 |
*/ |
4400 |
public int charWidth(char c) { |
4401 |
return metrics.wcwidth(c); |
4402 |
} |
4403 |
|
4033 |
/* |
4404 |
/* |
4034 |
* The following are overrides of JComponent/Component |
4405 |
* The following are overrides of JComponent/Component |
4035 |
*/ |
4406 |
*/ |
Lines 4050-4056
Link Here
|
4050 |
super.setFont(font); // This should invalidate us, which |
4421 |
super.setFont(font); // This should invalidate us, which |
4051 |
// ultimately will cause a repaint |
4422 |
// ultimately will cause a repaint |
4052 |
|
4423 |
|
4053 |
/* |
4424 |
/* DEBUG |
4054 |
System.out.println("Font info:"); // NOI18N |
4425 |
System.out.println("Font info:"); // NOI18N |
4055 |
System.out.println("\tlogical name: " + font.getName()); // NOI18N |
4426 |
System.out.println("\tlogical name: " + font.getName()); // NOI18N |
4056 |
System.out.println("\tfamily name: " + font.getFamily()); // NOI18N |
4427 |
System.out.println("\tfamily name: " + font.getFamily()); // NOI18N |
Lines 4062-4067
Link Here
|
4062 |
|
4433 |
|
4063 |
updateScreenSize(); |
4434 |
updateScreenSize(); |
4064 |
} |
4435 |
} |
|
|
4436 |
|
4065 |
|
4437 |
|
4066 |
/** |
4438 |
/** |
4067 |
* Override of JComponent |
4439 |
* Override of JComponent |