Mercurial > hg > octave-nkf
comparison libqterminal/unix/TerminalView.cpp @ 15671:14da85a0d1c3
Set terminal to fixed width, renamed some variables.
author | Jacob Dawid <jacob.dawid@googlemail.com> |
---|---|
date | Fri, 08 Jun 2012 18:12:41 +0200 |
parents | a8ff19a82906 |
children | 76452c97add8 |
comparison
equal
deleted
inserted
replaced
15670:d79d1a3130c8 | 15671:14da85a0d1c3 |
---|---|
54 #endif | 54 #endif |
55 | 55 |
56 #define yMouseScroll 1 | 56 #define yMouseScroll 1 |
57 | 57 |
58 #define REPCHAR "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ | 58 #define REPCHAR "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ |
59 "abcdefgjijklmnopqrstuvwxyz" \ | 59 "abcdefgjijklmnopqrstuvwxyz" \ |
60 "0123456789./+@" | 60 "0123456789./+@" |
61 | 61 |
62 // scroll increment used when dragging selection at top/bottom of window. | 62 // scroll increment used when dragging selection at top/bottom of window. |
63 | 63 |
64 // static | 64 // static |
65 bool TerminalView::_antialiasText = true; | 65 bool TerminalView::_antialiasText = true; |
79 IBMPC (rgb) Black Blue Green Cyan Red Magenta Yellow White | 79 IBMPC (rgb) Black Blue Green Cyan Red Magenta Yellow White |
80 */ | 80 */ |
81 | 81 |
82 ScreenWindow* TerminalView::screenWindow() const | 82 ScreenWindow* TerminalView::screenWindow() const |
83 { | 83 { |
84 return _screenWindow; | 84 return _screenWindow; |
85 } | 85 } |
86 void TerminalView::setScreenWindow(ScreenWindow* window) | 86 void TerminalView::setScreenWindow(ScreenWindow* window) |
87 { | 87 { |
88 // disconnect existing screen window if any | 88 // disconnect existing screen window if any |
89 if ( _screenWindow ) | 89 if ( _screenWindow ) |
90 { | 90 { |
91 disconnect( _screenWindow , 0 , this , 0 ); | 91 disconnect( _screenWindow , 0 , this , 0 ); |
92 } | 92 } |
93 | 93 |
94 _screenWindow = window; | 94 _screenWindow = window; |
95 | 95 |
96 if ( window ) | 96 if ( window ) |
97 { | 97 { |
98 //#warning "The order here is not specified - does it matter whether updateImage or updateLineProperties comes first?" | 98 //#warning "The order here is not specified - does it matter whether updateImage or updateLineProperties comes first?" |
99 connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateLineProperties()) ); | 99 connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateLineProperties()) ); |
100 connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateImage()) ); | 100 connect( _screenWindow , SIGNAL(outputChanged()) , this , SLOT(updateImage()) ); |
101 window->setWindowLines(_lines); | 101 window->setWindowLines(_lines); |
102 } | 102 } |
103 } | 103 } |
104 | 104 |
105 const ColorEntry* TerminalView::colorTable() const | 105 const ColorEntry* TerminalView::colorTable() const |
106 { | 106 { |
108 } | 108 } |
109 | 109 |
110 void TerminalView::setColorTable(const ColorEntry table[]) | 110 void TerminalView::setColorTable(const ColorEntry table[]) |
111 { | 111 { |
112 for (int i = 0; i < TABLE_COLORS; i++) | 112 for (int i = 0; i < TABLE_COLORS; i++) |
113 _colorTable[i] = table[i]; | 113 _colorTable[i] = table[i]; |
114 | 114 |
115 QPalette p = palette(); | 115 QPalette p = palette(); |
116 p.setColor( backgroundRole(), _colorTable[DEFAULT_BACK_COLOR].color ); | 116 p.setColor( backgroundRole(), _colorTable[DEFAULT_BACK_COLOR].color ); |
117 setPalette( p ); | 117 setPalette( p ); |
118 | 118 |
141 */ | 141 */ |
142 | 142 |
143 static inline bool isLineChar(quint16 c) { return ((c & 0xFF80) == 0x2500);} | 143 static inline bool isLineChar(quint16 c) { return ((c & 0xFF80) == 0x2500);} |
144 static inline bool isLineCharString(const QString& string) | 144 static inline bool isLineCharString(const QString& string) |
145 { | 145 { |
146 return (string.length() > 0) && (isLineChar(string.at(0).unicode())); | 146 return (string.length() > 0) && (isLineChar(string.at(0).unicode())); |
147 } | 147 } |
148 | 148 |
149 | 149 |
150 // assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i. | 150 // assert for i in [0..31] : vt100extended(vt100_graphics[i]) == i. |
151 | 151 |
171 | 171 |
172 _fixedFont = true; | 172 _fixedFont = true; |
173 | 173 |
174 int fw = fm.width(REPCHAR[0]); | 174 int fw = fm.width(REPCHAR[0]); |
175 for(unsigned int i=1; i< strlen(REPCHAR); i++) | 175 for(unsigned int i=1; i< strlen(REPCHAR); i++) |
176 { | 176 { |
177 if (fw != fm.width(REPCHAR[i])) | 177 if (fw != fm.width(REPCHAR[i])) |
178 { | 178 { |
179 _fixedFont = false; | 179 _fixedFont = false; |
180 break; | 180 break; |
181 } | 181 } |
182 } | 182 } |
183 | |
183 | 184 |
184 if (_fontWidth < 1) | 185 if (_fontWidth < 1) |
185 _fontWidth=1; | 186 _fontWidth=1; |
186 | 187 |
187 _fontAscent = fm.ascent(); | 188 _fontAscent = fm.ascent(); |
188 | 189 |
189 emit changedFontMetricSignal( _fontHeight, _fontWidth ); | 190 emit changedFontMetricSignal( _fontHeight, _fontWidth ); |
191 parentWidget()->setFixedWidth(_fontWidth * 80 + _leftMargin); | |
190 propagateSize(); | 192 propagateSize(); |
191 update(); | 193 update(); |
192 } | 194 } |
193 | 195 |
194 void TerminalView::setVTFont(const QFont& f) | 196 void TerminalView::setVTFont(const QFont& f) |
196 QFont font = f; | 198 QFont font = f; |
197 | 199 |
198 QFontMetrics metrics(font); | 200 QFontMetrics metrics(font); |
199 | 201 |
200 if ( metrics.height() < height() && metrics.maxWidth() < width() ) | 202 if ( metrics.height() < height() && metrics.maxWidth() < width() ) |
201 { | 203 { |
202 // hint that text should be drawn without anti-aliasing. | 204 // hint that text should be drawn without anti-aliasing. |
203 // depending on the user's font configuration, this may not be respected | 205 // depending on the user's font configuration, this may not be respected |
204 if (!_antialiasText) | 206 if (!_antialiasText) |
205 font.setStyleStrategy( QFont::NoAntialias ); | 207 font.setStyleStrategy( QFont::NoAntialias ); |
206 | 208 |
207 // experimental optimization. Konsole assumes that the terminal is using a | 209 // experimental optimization. Konsole assumes that the terminal is using a |
208 // mono-spaced font, in which case kerning information should have an effect. | 210 // mono-spaced font, in which case kerning information should have an effect. |
209 // Disabling kerning saves some computation when rendering text. | 211 // Disabling kerning saves some computation when rendering text. |
210 font.setKerning(false); | 212 // font.setKerning(false); |
211 | 213 |
212 QWidget::setFont(font); | 214 QWidget::setFont(font); |
213 fontChange(font); | 215 fontChange(font); |
214 } | 216 } |
215 } | 217 } |
216 | 218 |
217 void TerminalView::setFont(const QFont &) | 219 void TerminalView::setFont(const QFont &) |
218 { | 220 { |
219 // ignore font change request if not coming from konsole itself | 221 // ignore font change request if not coming from konsole itself |
224 /* Constructor / Destructor */ | 226 /* Constructor / Destructor */ |
225 /* */ | 227 /* */ |
226 /* ------------------------------------------------------------------------- */ | 228 /* ------------------------------------------------------------------------- */ |
227 | 229 |
228 TerminalView::TerminalView(QWidget *parent) | 230 TerminalView::TerminalView(QWidget *parent) |
229 :QWidget(parent) | 231 :QWidget(parent) |
230 ,_screenWindow(0) | 232 ,_screenWindow(0) |
231 ,_allowBell(true) | 233 ,_allowBell(true) |
232 ,_gridLayout(0) | 234 ,_gridLayout(0) |
233 ,_fontHeight(1) | 235 ,_fontHeight(1) |
234 ,_fontWidth(1) | 236 ,_fontWidth(1) |
235 ,_fontAscent(1) | 237 ,_fontAscent(1) |
236 ,_lines(1) | 238 ,_lines(1) |
237 ,_columns(1) | 239 ,_columns(1) |
238 ,_usedLines(1) | 240 ,_usedLines(1) |
239 ,_usedColumns(1) | 241 ,_usedColumns(1) |
240 ,_contentHeight(1) | 242 ,_contentHeight(1) |
241 ,_contentWidth(1) | 243 ,_contentWidth(1) |
242 ,_image(0) | 244 ,_image(0) |
243 ,_randomSeed(0) | 245 ,_randomSeed(0) |
244 ,_resizing(false) | 246 ,_resizing(false) |
245 ,_terminalSizeHint(false) | 247 ,_terminalSizeHint(false) |
246 ,_terminalSizeStartup(true) | 248 ,_terminalSizeStartup(true) |
247 ,_bidiEnabled(false) | 249 ,_bidiEnabled(false) |
248 ,_actSel(0) | 250 ,_actSel(0) |
249 ,_wordSelectionMode(false) | 251 ,_wordSelectionMode(false) |
250 ,_lineSelectionMode(false) | 252 ,_lineSelectionMode(false) |
251 ,_preserveLineBreaks(false) | 253 ,_preserveLineBreaks(false) |
252 ,_columnSelectionMode(false) | 254 ,_columnSelectionMode(false) |
253 ,_scrollbarLocation(NoScrollBar) | 255 ,_scrollbarLocation(NoScrollBar) |
254 ,_wordCharacters(":@-./_~") | 256 ,_wordCharacters(":@-./_~") |
255 ,_bellMode(SystemBeepBell) | 257 ,_bellMode(SystemBeepBell) |
256 ,_blinking(false) | 258 ,_blinking(false) |
257 ,_cursorBlinking(false) | 259 ,_cursorBlinking(false) |
258 ,_hasBlinkingCursor(false) | 260 ,_hasBlinkingCursor(false) |
259 ,_ctrlDrag(false) | 261 ,_ctrlDrag(false) |
260 ,_tripleClickMode(SelectWholeLine) | 262 ,_tripleClickMode(SelectWholeLine) |
261 ,_isFixedSize(false) | 263 ,_isFixedSize(false) |
262 ,_possibleTripleClick(false) | 264 ,_possibleTripleClick(false) |
263 ,_resizeWidget(0) | 265 ,_resizeWidget(0) |
264 ,_resizeTimer(0) | 266 ,_resizeTimer(0) |
265 ,_outputSuspendedLabel(0) | 267 ,_outputSuspendedLabel(0) |
266 ,_lineSpacing(0) | 268 ,_lineSpacing(0) |
267 ,_colorsInverted(false) | 269 ,_colorsInverted(false) |
268 ,_blendColor(qRgba(0,0,0,0xff)) | 270 ,_blendColor(qRgba(0,0,0,0xff)) |
269 ,_filterChain(new TerminalImageFilterChain()) | 271 ,_filterChain(new TerminalImageFilterChain()) |
270 ,_cursorShape(BlockCursor) | 272 ,_cursorShape(BlockCursor) |
271 ,_readonly(false) | 273 ,_readonly(false) |
272 { | 274 { |
273 // terminal applications are not designed with Right-To-Left in mind, | 275 // terminal applications are not designed with Right-To-Left in mind, |
274 // so the layout is forced to Left-To-Right | 276 // so the layout is forced to Left-To-Right |
275 setLayoutDirection(Qt::LeftToRight); | 277 setLayoutDirection(Qt::LeftToRight); |
276 | 278 |
284 // set the scroll bar's slider to occupy the whole area of the scroll bar initially | 286 // set the scroll bar's slider to occupy the whole area of the scroll bar initially |
285 _scrollBar = new QScrollBar(this); | 287 _scrollBar = new QScrollBar(this); |
286 setScroll(0,0); | 288 setScroll(0,0); |
287 _scrollBar->setCursor( Qt::ArrowCursor ); | 289 _scrollBar->setCursor( Qt::ArrowCursor ); |
288 connect(_scrollBar, SIGNAL(valueChanged(int)), this, | 290 connect(_scrollBar, SIGNAL(valueChanged(int)), this, |
289 SLOT(scrollBarPositionChanged(int))); | 291 SLOT(scrollBarPositionChanged(int))); |
290 | 292 |
291 // setup timers for blinking cursor and text | 293 // setup timers for blinking cursor and text |
292 _blinkTimer = new QTimer(this); | 294 _blinkTimer = new QTimer(this); |
293 connect(_blinkTimer, SIGNAL(timeout()), this, SLOT(blinkEvent())); | 295 connect(_blinkTimer, SIGNAL(timeout()), this, SLOT(blinkEvent())); |
294 _blinkCursorTimer = new QTimer(this); | 296 _blinkCursorTimer = new QTimer(this); |
295 connect(_blinkCursorTimer, SIGNAL(timeout()), this, SLOT(blinkCursorEvent())); | 297 connect(_blinkCursorTimer, SIGNAL(timeout()), this, SLOT(blinkCursorEvent())); |
296 | 298 |
297 // QCursor::setAutoHideCursor( this, true ); | 299 // QCursor::setAutoHideCursor( this, true ); |
298 | 300 |
299 setUsesMouse(true); | 301 setUsesMouse(true); |
300 setColorTable(base_color_table); | 302 setColorTable(base_color_table); |
301 setMouseTracking(true); | 303 setMouseTracking(true); |
302 | 304 |
355 */ | 357 */ |
356 | 358 |
357 | 359 |
358 enum LineEncode | 360 enum LineEncode |
359 { | 361 { |
360 TopL = (1<<1), | 362 TopL = (1<<1), |
361 TopC = (1<<2), | 363 TopC = (1<<2), |
362 TopR = (1<<3), | 364 TopR = (1<<3), |
363 | 365 |
364 LeftT = (1<<5), | 366 LeftT = (1<<5), |
365 Int11 = (1<<6), | 367 Int11 = (1<<6), |
366 Int12 = (1<<7), | 368 Int12 = (1<<7), |
367 Int13 = (1<<8), | 369 Int13 = (1<<8), |
368 RightT = (1<<9), | 370 RightT = (1<<9), |
369 | 371 |
370 LeftC = (1<<10), | 372 LeftC = (1<<10), |
371 Int21 = (1<<11), | 373 Int21 = (1<<11), |
372 Int22 = (1<<12), | 374 Int22 = (1<<12), |
373 Int23 = (1<<13), | 375 Int23 = (1<<13), |
374 RightC = (1<<14), | 376 RightC = (1<<14), |
375 | 377 |
376 LeftB = (1<<15), | 378 LeftB = (1<<15), |
377 Int31 = (1<<16), | 379 Int31 = (1<<16), |
378 Int32 = (1<<17), | 380 Int32 = (1<<17), |
379 Int33 = (1<<18), | 381 Int33 = (1<<18), |
380 RightB = (1<<19), | 382 RightB = (1<<19), |
381 | 383 |
382 BotL = (1<<21), | 384 BotL = (1<<21), |
383 BotC = (1<<22), | 385 BotC = (1<<22), |
384 BotR = (1<<23) | 386 BotR = (1<<23) |
385 }; | 387 }; |
386 | 388 |
387 #include "LineFont.h" | 389 #include "LineFont.h" |
388 | 390 |
389 static void drawLineChar(QPainter& paint, int x, int y, int w, int h, uchar code) | 391 static void drawLineChar(QPainter& paint, int x, int y, int w, int h, uchar code) |
390 { | 392 { |
391 //Calculate cell midpoints, end points. | 393 //Calculate cell midpoints, end points. |
392 int cx = x + w/2; | 394 int cx = x + w/2; |
393 int cy = y + h/2; | 395 int cy = y + h/2; |
394 int ex = x + w - 1; | 396 int ex = x + w - 1; |
395 int ey = y + h - 1; | 397 int ey = y + h - 1; |
396 | 398 |
397 quint32 toDraw = LineChars[code]; | 399 quint32 toDraw = LineChars[code]; |
398 | 400 |
399 //Top _lines: | 401 //Top _lines: |
400 if (toDraw & TopL) | 402 if (toDraw & TopL) |
401 paint.drawLine(cx-1, y, cx-1, cy-2); | 403 paint.drawLine(cx-1, y, cx-1, cy-2); |
402 if (toDraw & TopC) | 404 if (toDraw & TopC) |
403 paint.drawLine(cx, y, cx, cy-2); | 405 paint.drawLine(cx, y, cx, cy-2); |
404 if (toDraw & TopR) | 406 if (toDraw & TopR) |
405 paint.drawLine(cx+1, y, cx+1, cy-2); | 407 paint.drawLine(cx+1, y, cx+1, cy-2); |
406 | 408 |
407 //Bot _lines: | 409 //Bot _lines: |
408 if (toDraw & BotL) | 410 if (toDraw & BotL) |
409 paint.drawLine(cx-1, cy+2, cx-1, ey); | 411 paint.drawLine(cx-1, cy+2, cx-1, ey); |
410 if (toDraw & BotC) | 412 if (toDraw & BotC) |
411 paint.drawLine(cx, cy+2, cx, ey); | 413 paint.drawLine(cx, cy+2, cx, ey); |
412 if (toDraw & BotR) | 414 if (toDraw & BotR) |
413 paint.drawLine(cx+1, cy+2, cx+1, ey); | 415 paint.drawLine(cx+1, cy+2, cx+1, ey); |
414 | 416 |
415 //Left _lines: | 417 //Left _lines: |
416 if (toDraw & LeftT) | 418 if (toDraw & LeftT) |
417 paint.drawLine(x, cy-1, cx-2, cy-1); | 419 paint.drawLine(x, cy-1, cx-2, cy-1); |
418 if (toDraw & LeftC) | 420 if (toDraw & LeftC) |
419 paint.drawLine(x, cy, cx-2, cy); | 421 paint.drawLine(x, cy, cx-2, cy); |
420 if (toDraw & LeftB) | 422 if (toDraw & LeftB) |
421 paint.drawLine(x, cy+1, cx-2, cy+1); | 423 paint.drawLine(x, cy+1, cx-2, cy+1); |
422 | 424 |
423 //Right _lines: | 425 //Right _lines: |
424 if (toDraw & RightT) | 426 if (toDraw & RightT) |
425 paint.drawLine(cx+2, cy-1, ex, cy-1); | 427 paint.drawLine(cx+2, cy-1, ex, cy-1); |
426 if (toDraw & RightC) | 428 if (toDraw & RightC) |
427 paint.drawLine(cx+2, cy, ex, cy); | 429 paint.drawLine(cx+2, cy, ex, cy); |
428 if (toDraw & RightB) | 430 if (toDraw & RightB) |
429 paint.drawLine(cx+2, cy+1, ex, cy+1); | 431 paint.drawLine(cx+2, cy+1, ex, cy+1); |
430 | 432 |
431 //Intersection points. | 433 //Intersection points. |
432 if (toDraw & Int11) | 434 if (toDraw & Int11) |
433 paint.drawPoint(cx-1, cy-1); | 435 paint.drawPoint(cx-1, cy-1); |
434 if (toDraw & Int12) | 436 if (toDraw & Int12) |
435 paint.drawPoint(cx, cy-1); | 437 paint.drawPoint(cx, cy-1); |
436 if (toDraw & Int13) | 438 if (toDraw & Int13) |
437 paint.drawPoint(cx+1, cy-1); | 439 paint.drawPoint(cx+1, cy-1); |
438 | 440 |
439 if (toDraw & Int21) | 441 if (toDraw & Int21) |
440 paint.drawPoint(cx-1, cy); | 442 paint.drawPoint(cx-1, cy); |
441 if (toDraw & Int22) | 443 if (toDraw & Int22) |
442 paint.drawPoint(cx, cy); | 444 paint.drawPoint(cx, cy); |
443 if (toDraw & Int23) | 445 if (toDraw & Int23) |
444 paint.drawPoint(cx+1, cy); | 446 paint.drawPoint(cx+1, cy); |
445 | 447 |
446 if (toDraw & Int31) | 448 if (toDraw & Int31) |
447 paint.drawPoint(cx-1, cy+1); | 449 paint.drawPoint(cx-1, cy+1); |
448 if (toDraw & Int32) | 450 if (toDraw & Int32) |
449 paint.drawPoint(cx, cy+1); | 451 paint.drawPoint(cx, cy+1); |
450 if (toDraw & Int33) | 452 if (toDraw & Int33) |
451 paint.drawPoint(cx+1, cy+1); | 453 paint.drawPoint(cx+1, cy+1); |
452 | 454 |
453 } | 455 } |
454 | 456 |
455 void TerminalView::drawLineCharString( QPainter& painter, int x, int y, const QString& str, | 457 void TerminalView::drawLineCharString( QPainter& painter, int x, int y, const QString& str, |
456 const Character* attributes) | 458 const Character* attributes) |
457 { | 459 { |
458 const QPen& currentPen = painter.pen(); | 460 const QPen& currentPen = painter.pen(); |
459 | 461 |
460 if ( attributes->rendition & RE_BOLD ) | 462 if ( attributes->rendition & RE_BOLD ) |
461 { | 463 { |
462 QPen boldPen(currentPen); | 464 QPen boldPen(currentPen); |
463 boldPen.setWidth(3); | 465 boldPen.setWidth(3); |
464 painter.setPen( boldPen ); | 466 painter.setPen( boldPen ); |
465 } | 467 } |
466 | 468 |
467 for (int i=0 ; i < str.length(); i++) | 469 for (int i=0 ; i < str.length(); i++) |
468 { | 470 { |
469 uchar code = str[i].cell(); | 471 uchar code = str[i].cell(); |
470 if (LineChars[code]) | 472 if (LineChars[code]) |
471 drawLineChar(painter, x + (_fontWidth*i), y, _fontWidth, _fontHeight, code); | 473 drawLineChar(painter, x + (_fontWidth*i), y, _fontWidth, _fontHeight, code); |
472 } | 474 } |
473 | 475 |
474 painter.setPen( currentPen ); | 476 painter.setPen( currentPen ); |
475 } | 477 } |
476 | 478 |
477 void TerminalView::setKeyboardCursorShape(KeyboardCursorShape shape) | 479 void TerminalView::setKeyboardCursorShape(KeyboardCursorShape shape) |
478 { | 480 { |
479 _cursorShape = shape; | 481 _cursorShape = shape; |
480 } | 482 } |
481 TerminalView::KeyboardCursorShape TerminalView::keyboardCursorShape() const | 483 TerminalView::KeyboardCursorShape TerminalView::keyboardCursorShape() const |
482 { | 484 { |
483 return _cursorShape; | 485 return _cursorShape; |
484 } | 486 } |
485 void TerminalView::setKeyboardCursorColor(bool useForegroundColor, const QColor& color) | 487 void TerminalView::setKeyboardCursorColor(bool useForegroundColor, const QColor& color) |
486 { | 488 { |
487 if (useForegroundColor) | 489 if (useForegroundColor) |
488 _cursorColor = QColor(); // an invalid color means that | 490 _cursorColor = QColor(); // an invalid color means that |
489 // the foreground color of the | 491 // the foreground color of the |
490 // current character should | 492 // current character should |
491 // be used | 493 // be used |
492 | 494 |
493 else | 495 else |
494 _cursorColor = color; | 496 _cursorColor = color; |
495 } | 497 } |
496 QColor TerminalView::keyboardCursorColor() const | 498 QColor TerminalView::keyboardCursorColor() const |
497 { | 499 { |
498 return _cursorColor; | 500 return _cursorColor; |
499 } | 501 } |
500 | 502 |
501 void TerminalView::setOpacity(qreal opacity) | 503 void TerminalView::setOpacity(qreal opacity) |
502 { | 504 { |
503 QColor color(_blendColor); | 505 QColor color(_blendColor); |
504 color.setAlphaF(opacity); | 506 color.setAlphaF(opacity); |
505 | 507 |
506 // enable automatic background filling to prevent the display | 508 // enable automatic background filling to prevent the display |
507 // flickering if there is no transparency | 509 // flickering if there is no transparency |
508 if ( color.alpha() == 255 ) | 510 if ( color.alpha() == 255 ) |
509 { | 511 { |
510 setAutoFillBackground(true); | 512 setAutoFillBackground(true); |
511 } | 513 } |
512 else | 514 else |
513 { | 515 { |
514 setAutoFillBackground(false); | 516 setAutoFillBackground(false); |
515 } | 517 } |
516 | 518 |
517 _blendColor = color.rgba(); | 519 _blendColor = color.rgba(); |
518 } | 520 } |
519 | 521 |
520 void TerminalView::drawBackground(QPainter& painter, const QRect& rect, const QColor& backgroundColor, bool useOpacitySetting ) | 522 void TerminalView::drawBackground(QPainter& painter, const QRect& rect, const QColor& backgroundColor, bool useOpacitySetting ) |
521 { | 523 { |
522 // the area of the widget showing the contents of the terminal display is drawn | 524 // the area of the widget showing the contents of the terminal display is drawn |
523 // using the background color from the color scheme set with setColorTable() | 525 // using the background color from the color scheme set with setColorTable() |
524 // | 526 // |
525 // the area of the widget behind the scroll-bar is drawn using the background | 527 // the area of the widget behind the scroll-bar is drawn using the background |
526 // brush from the scroll-bar's palette, to give the effect of the scroll-bar | 528 // brush from the scroll-bar's palette, to give the effect of the scroll-bar |
527 // being outside of the terminal display and visual consistency with other KDE | 529 // being outside of the terminal display and visual consistency with other KDE |
528 // applications. | 530 // applications. |
529 // | 531 // |
530 QRect scrollBarArea = _scrollBar->isVisible() ? | 532 QRect scrollBarArea = _scrollBar->isVisible() ? |
531 rect.intersected(_scrollBar->geometry()) : | 533 rect.intersected(_scrollBar->geometry()) : |
532 QRect(); | 534 QRect(); |
533 QRegion contentsRegion = QRegion(rect).subtracted(scrollBarArea); | 535 QRegion contentsRegion = QRegion(rect).subtracted(scrollBarArea); |
534 QRect contentsRect = contentsRegion.boundingRect(); | 536 QRect contentsRect = contentsRegion.boundingRect(); |
535 | 537 |
536 if ( HAVE_TRANSPARENCY && qAlpha(_blendColor) < 0xff && useOpacitySetting ) | 538 if ( HAVE_TRANSPARENCY && qAlpha(_blendColor) < 0xff && useOpacitySetting ) |
539 { | |
540 QColor color(backgroundColor); | |
541 color.setAlpha(qAlpha(_blendColor)); | |
542 | |
543 painter.save(); | |
544 painter.setCompositionMode(QPainter::CompositionMode_Source); | |
545 painter.fillRect(contentsRect, color); | |
546 painter.restore(); | |
547 } | |
548 else { | |
549 painter.fillRect(contentsRect, backgroundColor); | |
550 } | |
551 | |
552 painter.fillRect(scrollBarArea,_scrollBar->palette().background()); | |
553 } | |
554 | |
555 void TerminalView::drawCursor(QPainter& painter, | |
556 const QRect& rect, | |
557 const QColor& foregroundColor, | |
558 const QColor& /*backgroundColor*/, | |
559 bool& invertCharacterColor) | |
560 { | |
561 QRect cursorRect = rect; | |
562 cursorRect.setHeight(_fontHeight - _lineSpacing - 1); | |
563 | |
564 if (!_cursorBlinking) | |
565 { | |
566 if ( _cursorColor.isValid() ) | |
567 painter.setPen(_cursorColor); | |
568 else { | |
569 painter.setPen(foregroundColor); | |
570 } | |
571 | |
572 if ( _cursorShape == BlockCursor ) | |
537 { | 573 { |
538 QColor color(backgroundColor); | 574 // draw the cursor outline, adjusting the area so that |
539 color.setAlpha(qAlpha(_blendColor)); | 575 // it is draw entirely inside 'rect' |
540 | 576 int penWidth = qMax(1,painter.pen().width()); |
541 painter.save(); | 577 |
542 painter.setCompositionMode(QPainter::CompositionMode_Source); | 578 painter.drawRect(cursorRect.adjusted(penWidth/2, |
543 painter.fillRect(contentsRect, color); | 579 penWidth/2, |
544 painter.restore(); | 580 - penWidth/2 - penWidth%2, |
545 } | 581 - penWidth/2 - penWidth%2)); |
546 else { | 582 if ( hasFocus() ) |
547 painter.fillRect(contentsRect, backgroundColor); | |
548 } | |
549 | |
550 painter.fillRect(scrollBarArea,_scrollBar->palette().background()); | |
551 } | |
552 | |
553 void TerminalView::drawCursor(QPainter& painter, | |
554 const QRect& rect, | |
555 const QColor& foregroundColor, | |
556 const QColor& /*backgroundColor*/, | |
557 bool& invertCharacterColor) | |
558 { | |
559 QRect cursorRect = rect; | |
560 cursorRect.setHeight(_fontHeight - _lineSpacing - 1); | |
561 | |
562 if (!_cursorBlinking) | |
563 { | |
564 if ( _cursorColor.isValid() ) | |
565 painter.setPen(_cursorColor); | |
566 else { | |
567 painter.setPen(foregroundColor); | |
568 } | |
569 | |
570 if ( _cursorShape == BlockCursor ) | |
571 { | |
572 // draw the cursor outline, adjusting the area so that | |
573 // it is draw entirely inside 'rect' | |
574 int penWidth = qMax(1,painter.pen().width()); | |
575 | |
576 painter.drawRect(cursorRect.adjusted(penWidth/2, | |
577 penWidth/2, | |
578 - penWidth/2 - penWidth%2, | |
579 - penWidth/2 - penWidth%2)); | |
580 if ( hasFocus() ) | |
581 { | 583 { |
582 painter.fillRect(cursorRect, _cursorColor.isValid() ? _cursorColor : foregroundColor); | 584 painter.fillRect(cursorRect, _cursorColor.isValid() ? _cursorColor : foregroundColor); |
583 | 585 |
584 if ( !_cursorColor.isValid() ) | 586 if ( !_cursorColor.isValid() ) |
585 { | 587 { |
586 // invert the colour used to draw the text to ensure that the character at | 588 // invert the colour used to draw the text to ensure that the character at |
587 // the cursor position is readable | 589 // the cursor position is readable |
588 invertCharacterColor = true; | 590 invertCharacterColor = true; |
589 } | 591 } |
590 } | 592 } |
591 } | 593 } |
592 else if ( _cursorShape == UnderlineCursor ) | 594 else if ( _cursorShape == UnderlineCursor ) |
593 painter.drawLine(cursorRect.left(), | 595 painter.drawLine(cursorRect.left(), |
594 cursorRect.bottom(), | 596 cursorRect.bottom(), |
595 cursorRect.right(), | 597 cursorRect.right(), |
596 cursorRect.bottom()); | 598 cursorRect.bottom()); |
597 else if ( _cursorShape == IBeamCursor ) | 599 else if ( _cursorShape == IBeamCursor ) |
598 painter.drawLine(cursorRect.left(), | 600 painter.drawLine(cursorRect.left(), |
599 cursorRect.top(), | 601 cursorRect.top(), |
600 cursorRect.left(), | 602 cursorRect.left(), |
601 cursorRect.bottom()); | 603 cursorRect.bottom()); |
602 | 604 |
603 } | 605 } |
604 } | 606 } |
605 | 607 |
606 void TerminalView::drawCharacters(QPainter& painter, | 608 void TerminalView::drawCharacters(QPainter& painter, |
607 const QRect& rect, | 609 const QRect& rect, |
608 const QString& text, | 610 const QString& text, |
609 const Character* style, | 611 const Character* style, |
610 bool invertCharacterColor) | 612 bool invertCharacterColor) |
611 { | 613 { |
612 // don't draw text which is currently blinking | 614 // don't draw text which is currently blinking |
613 if ( _blinking && (style->rendition & RE_BLINK) ) | 615 if ( _blinking && (style->rendition & RE_BLINK) ) |
614 return; | 616 return; |
615 | 617 |
616 // setup bold and underline | 618 // setup bold and underline |
617 bool useBold = style->rendition & RE_BOLD || style->isBold(_colorTable) || font().bold(); | 619 bool useBold = style->rendition & RE_BOLD || style->isBold(_colorTable) || font().bold(); |
618 bool useUnderline = style->rendition & RE_UNDERLINE || font().underline(); | 620 bool useUnderline = style->rendition & RE_UNDERLINE || font().underline(); |
619 | 621 |
620 QFont font = painter.font(); | 622 QFont font = painter.font(); |
621 if ( font.bold() != useBold | 623 if ( font.bold() != useBold |
622 || font.underline() != useUnderline ) | 624 || font.underline() != useUnderline ) |
623 { | 625 { |
624 font.setBold(useBold); | 626 font.setBold(useBold); |
625 font.setUnderline(useUnderline); | 627 font.setUnderline(useUnderline); |
626 painter.setFont(font); | 628 painter.setFont(font); |
627 } | 629 } |
628 | 630 |
629 const CharacterColor& textColor = ( invertCharacterColor ? style->backgroundColor : style->foregroundColor ); | 631 const CharacterColor& textColor = ( invertCharacterColor ? style->backgroundColor : style->foregroundColor ); |
630 const QColor color = textColor.color(_colorTable); | 632 const QColor color = textColor.color(_colorTable); |
631 | 633 |
632 QPen pen = painter.pen(); | 634 QPen pen = painter.pen(); |
633 if ( pen.color() != color ) | 635 if ( pen.color() != color ) |
634 { | 636 { |
635 pen.setColor(color); | 637 pen.setColor(color); |
636 painter.setPen(color); | 638 painter.setPen(color); |
637 } | 639 } |
638 // draw text | 640 // draw text |
639 if ( isLineCharString(text) ) { | 641 if ( isLineCharString(text) ) { |
640 drawLineCharString(painter,rect.x(),rect.y(),text,style); | 642 drawLineCharString(painter,rect.x(),rect.y(),text,style); |
641 } | 643 } |
642 else | 644 else |
643 { | 645 { |
644 // the drawText(rect,flags,string) overload is used here with null flags | 646 // the drawText(rect,flags,string) overload is used here with null flags |
645 // instead of drawText(rect,string) because the (rect,string) overload causes | 647 // instead of drawText(rect,string) because the (rect,string) overload causes |
646 // the application's default layout direction to be used instead of | 648 // the application's default layout direction to be used instead of |
647 // the widget-specific layout direction, which should always be | 649 // the widget-specific layout direction, which should always be |
648 // Qt::LeftToRight for this widget | 650 // Qt::LeftToRight for this widget |
649 painter.drawText(rect,0,text); | 651 painter.drawText(rect,0,text); |
650 } | 652 } |
651 } | 653 } |
652 | 654 |
653 void TerminalView::drawTextFragment(QPainter& painter , | 655 void TerminalView::drawTextFragment(QPainter& painter , |
654 const QRect& rect, | 656 const QRect& rect, |
655 const QString& text, | 657 const QString& text, |
656 const Character* style) | 658 const Character* style) |
657 { | 659 { |
658 painter.save(); | 660 painter.save(); |
659 | 661 |
660 // setup painter | 662 // setup painter |
661 const QColor foregroundColor = style->foregroundColor.color(_colorTable); | 663 const QColor foregroundColor = style->foregroundColor.color(_colorTable); |
662 const QColor backgroundColor = style->backgroundColor.color(_colorTable); | 664 const QColor backgroundColor = style->backgroundColor.color(_colorTable); |
663 | 665 |
664 // draw background if different from the display's background color | 666 // draw background if different from the display's background color |
665 if ( backgroundColor != palette().background().color() ) | 667 if ( backgroundColor != palette().background().color() ) |
666 drawBackground(painter,rect,backgroundColor, false /* do not use transparency */); | 668 drawBackground(painter,rect,backgroundColor, false /* do not use transparency */); |
667 | 669 |
668 // draw cursor shape if the current character is the cursor | 670 // draw cursor shape if the current character is the cursor |
669 // this may alter the foreground and background colors | 671 // this may alter the foreground and background colors |
670 bool invertCharacterColor = false; | 672 bool invertCharacterColor = false; |
671 | 673 |
672 if ( style->rendition & RE_CURSOR ) | 674 if ( style->rendition & RE_CURSOR ) |
673 drawCursor(painter,rect,foregroundColor,backgroundColor,invertCharacterColor); | 675 drawCursor(painter,rect,foregroundColor,backgroundColor,invertCharacterColor); |
674 // draw text | 676 // draw text |
675 drawCharacters(painter,rect,text,style,invertCharacterColor); | 677 drawCharacters(painter,rect,text,style,invertCharacterColor); |
676 | 678 |
677 painter.restore(); | 679 painter.restore(); |
678 } | 680 } |
679 | 681 |
680 void TerminalView::setRandomSeed(uint randomSeed) { _randomSeed = randomSeed; } | 682 void TerminalView::setRandomSeed(uint randomSeed) { _randomSeed = randomSeed; } |
681 uint TerminalView::randomSeed() const { return _randomSeed; } | 683 uint TerminalView::randomSeed() const { return _randomSeed; } |
682 | 684 |
684 /*! | 686 /*! |
685 Set XIM Position | 687 Set XIM Position |
686 */ | 688 */ |
687 void TerminalDisplay::setCursorPos(const int curx, const int cury) | 689 void TerminalDisplay::setCursorPos(const int curx, const int cury) |
688 { | 690 { |
689 QPoint tL = contentsRect().topLeft(); | 691 QPoint tL = contentsRect().topLeft(); |
690 int tLx = tL.x(); | 692 int tLx = tL.x(); |
691 int tLy = tL.y(); | 693 int tLy = tL.y(); |
692 | 694 |
693 int xpos, ypos; | 695 int xpos, ypos; |
694 ypos = _topMargin + tLy + _fontHeight*(cury-1) + _fontAscent; | 696 ypos = _topMargin + tLy + _fontHeight*(cury-1) + _fontAscent; |
695 xpos = _leftMargin + tLx + _fontWidth*curx; | 697 xpos = _leftMargin + tLx + _fontWidth*curx; |
696 //setMicroFocusHint(xpos, ypos, 0, _fontHeight); //### ??? | 698 //setMicroFocusHint(xpos, ypos, 0, _fontHeight); //### ??? |
697 // fprintf(stderr, "x/y = %d/%d\txpos/ypos = %d/%d\n", curx, cury, xpos, ypos); | 699 // fprintf(stderr, "x/y = %d/%d\txpos/ypos = %d/%d\n", curx, cury, xpos, ypos); |
698 _cursorLine = cury; | 700 _cursorLine = cury; |
699 _cursorCol = curx; | 701 _cursorCol = curx; |
700 } | 702 } |
701 #endif | 703 #endif |
702 | 704 |
703 // scrolls the image by 'lines', down if lines > 0 or up otherwise. | 705 // scrolls the image by 'lines', down if lines > 0 or up otherwise. |
704 // | 706 // |
713 // scrolled aligns properly with the character grid - | 715 // scrolled aligns properly with the character grid - |
714 // which has a top left point at (_leftMargin,_topMargin) , | 716 // which has a top left point at (_leftMargin,_topMargin) , |
715 // a cell width of _fontWidth and a cell height of _fontHeight). | 717 // a cell width of _fontWidth and a cell height of _fontHeight). |
716 void TerminalView::scrollImage(int lines , const QRect& screenWindowRegion) | 718 void TerminalView::scrollImage(int lines , const QRect& screenWindowRegion) |
717 { | 719 { |
718 // if the flow control warning is enabled this will interfere with the | 720 // if the flow control warning is enabled this will interfere with the |
719 // scrolling optimisations and cause artifacts. the simple solution here | 721 // scrolling optimisations and cause artifacts. the simple solution here |
720 // is to just disable the optimisation whilst it is visible | 722 // is to just disable the optimisation whilst it is visible |
721 if ( _outputSuspendedLabel && _outputSuspendedLabel->isVisible() ) { | 723 if ( _outputSuspendedLabel && _outputSuspendedLabel->isVisible() ) { |
722 return; | 724 return; |
723 } | 725 } |
724 | 726 |
725 // constrain the region to the display | 727 // constrain the region to the display |
726 // the bottom of the region is capped to the number of lines in the display's | 728 // the bottom of the region is capped to the number of lines in the display's |
727 // internal image - 2, so that the height of 'region' is strictly less | 729 // internal image - 2, so that the height of 'region' is strictly less |
728 // than the height of the internal image. | 730 // than the height of the internal image. |
729 QRect region = screenWindowRegion; | 731 QRect region = screenWindowRegion; |
730 region.setBottom( qMin(region.bottom(),this->_lines-2) ); | 732 region.setBottom( qMin(region.bottom(),this->_lines-2) ); |
731 | 733 |
732 if ( lines == 0 | 734 if ( lines == 0 |
733 || _image == 0 | 735 || _image == 0 |
734 || !region.isValid() | 736 || !region.isValid() |
735 || (region.top() + abs(lines)) >= region.bottom() | 737 || (region.top() + abs(lines)) >= region.bottom() |
736 || this->_lines <= region.height() ) return; | 738 || this->_lines <= region.height() ) return; |
737 | 739 |
738 QRect scrollRect; | 740 QRect scrollRect; |
739 | 741 |
740 void* firstCharPos = &_image[ region.top() * this->_columns ]; | 742 void* firstCharPos = &_image[ region.top() * this->_columns ]; |
741 void* lastCharPos = &_image[ (region.top() + abs(lines)) * this->_columns ]; | 743 void* lastCharPos = &_image[ (region.top() + abs(lines)) * this->_columns ]; |
742 | 744 |
743 int top = _topMargin + (region.top() * _fontHeight); | 745 int top = _topMargin + (region.top() * _fontHeight); |
744 int linesToMove = region.height() - abs(lines); | 746 int linesToMove = region.height() - abs(lines); |
745 int bytesToMove = linesToMove * | 747 int bytesToMove = linesToMove * |
746 this->_columns * | 748 this->_columns * |
747 sizeof(Character); | 749 sizeof(Character); |
748 | 750 |
749 Q_ASSERT( linesToMove > 0 ); | 751 Q_ASSERT( linesToMove > 0 ); |
750 Q_ASSERT( bytesToMove > 0 ); | 752 Q_ASSERT( bytesToMove > 0 ); |
751 | 753 |
752 //scroll internal image | 754 //scroll internal image |
753 if ( lines > 0 ) | 755 if ( lines > 0 ) |
754 { | 756 { |
755 // check that the memory areas that we are going to move are valid | 757 // check that the memory areas that we are going to move are valid |
756 Q_ASSERT( (char*)lastCharPos + bytesToMove < | 758 Q_ASSERT( (char*)lastCharPos + bytesToMove < |
757 (char*)(_image + (this->_lines * this->_columns)) ); | 759 (char*)(_image + (this->_lines * this->_columns)) ); |
758 | 760 |
759 Q_ASSERT( (lines*this->_columns) < _imageSize ); | 761 Q_ASSERT( (lines*this->_columns) < _imageSize ); |
760 | 762 |
761 //scroll internal image down | 763 //scroll internal image down |
762 memmove( firstCharPos , lastCharPos , bytesToMove ); | 764 memmove( firstCharPos , lastCharPos , bytesToMove ); |
763 | 765 |
764 //set region of display to scroll, making sure that | 766 //set region of display to scroll, making sure that |
765 //the region aligns correctly to the character grid | 767 //the region aligns correctly to the character grid |
766 scrollRect = QRect( _leftMargin , top, | 768 scrollRect = QRect( _leftMargin , top, |
767 this->_usedColumns * _fontWidth , | 769 this->_usedColumns * _fontWidth , |
768 linesToMove * _fontHeight ); | 770 linesToMove * _fontHeight ); |
769 } | 771 } |
770 else | 772 else |
771 { | 773 { |
772 // check that the memory areas that we are going to move are valid | 774 // check that the memory areas that we are going to move are valid |
773 Q_ASSERT( (char*)firstCharPos + bytesToMove < | 775 Q_ASSERT( (char*)firstCharPos + bytesToMove < |
774 (char*)(_image + (this->_lines * this->_columns)) ); | 776 (char*)(_image + (this->_lines * this->_columns)) ); |
775 | 777 |
776 //scroll internal image up | 778 //scroll internal image up |
777 memmove( lastCharPos , firstCharPos , bytesToMove ); | 779 memmove( lastCharPos , firstCharPos , bytesToMove ); |
778 | 780 |
779 //set region of the display to scroll, making sure that | 781 //set region of the display to scroll, making sure that |
780 //the region aligns correctly to the character grid | 782 //the region aligns correctly to the character grid |
781 QPoint topPoint( _leftMargin , top + abs(lines)*_fontHeight ); | 783 QPoint topPoint( _leftMargin , top + abs(lines)*_fontHeight ); |
782 | 784 |
783 scrollRect = QRect( topPoint , | 785 scrollRect = QRect( topPoint , |
784 QSize( this->_usedColumns*_fontWidth , | 786 QSize( this->_usedColumns*_fontWidth , |
785 linesToMove * _fontHeight )); | 787 linesToMove * _fontHeight )); |
786 } | 788 } |
787 | 789 |
788 //scroll the display vertically to match internal _image | 790 //scroll the display vertically to match internal _image |
789 scroll( 0 , _fontHeight * (-lines) , scrollRect ); | 791 scroll( 0 , _fontHeight * (-lines) , scrollRect ); |
790 } | 792 } |
791 | 793 |
792 QRegion TerminalView::hotSpotRegion() const | 794 QRegion TerminalView::hotSpotRegion() const |
793 { | 795 { |
794 QRegion region; | 796 QRegion region; |
795 foreach( Filter::HotSpot* hotSpot , _filterChain->hotSpots() ) | 797 foreach( Filter::HotSpot* hotSpot , _filterChain->hotSpots() ) |
796 { | 798 { |
797 QRect rect; | 799 QRect rect; |
798 rect.setLeft(hotSpot->startColumn()); | 800 rect.setLeft(hotSpot->startColumn()); |
799 rect.setTop(hotSpot->startLine()); | 801 rect.setTop(hotSpot->startLine()); |
800 rect.setRight(hotSpot->endColumn()); | 802 rect.setRight(hotSpot->endColumn()); |
801 rect.setBottom(hotSpot->endLine()); | 803 rect.setBottom(hotSpot->endLine()); |
802 | 804 |
803 region |= imageToWidget(rect); | 805 region |= imageToWidget(rect); |
804 } | 806 } |
805 return region; | 807 return region; |
806 } | 808 } |
807 | 809 |
808 void TerminalView::processFilters() | 810 void TerminalView::processFilters() |
809 { | 811 { |
810 if (!_screenWindow) | 812 if (!_screenWindow) |
811 return; | 813 return; |
812 | 814 |
813 QRegion preUpdateHotSpots = hotSpotRegion(); | 815 QRegion preUpdateHotSpots = hotSpotRegion(); |
814 | 816 |
815 // use _screenWindow->getImage() here rather than _image because | 817 // use _screenWindow->getImage() here rather than _image because |
816 // other classes may call processFilters() when this display's | 818 // other classes may call processFilters() when this display's |
817 // ScreenWindow emits a scrolled() signal - which will happen before | 819 // ScreenWindow emits a scrolled() signal - which will happen before |
818 // updateImage() is called on the display and therefore _image is | 820 // updateImage() is called on the display and therefore _image is |
819 // out of date at this point | 821 // out of date at this point |
820 _filterChain->setImage( _screenWindow->getImage(), | 822 _filterChain->setImage( _screenWindow->getImage(), |
821 _screenWindow->windowLines(), | 823 _screenWindow->windowLines(), |
822 _screenWindow->windowColumns(), | 824 _screenWindow->windowColumns(), |
823 _screenWindow->getLineProperties() ); | 825 _screenWindow->getLineProperties() ); |
824 _filterChain->process(); | 826 _filterChain->process(); |
825 | 827 |
826 QRegion postUpdateHotSpots = hotSpotRegion(); | 828 QRegion postUpdateHotSpots = hotSpotRegion(); |
827 | 829 |
828 update( preUpdateHotSpots | postUpdateHotSpots ); | 830 update( preUpdateHotSpots | postUpdateHotSpots ); |
829 } | 831 } |
830 | 832 |
831 void TerminalView::updateImage() | 833 void TerminalView::updateImage() |
832 { | 834 { |
833 if ( !_screenWindow ) | 835 if ( !_screenWindow ) |
834 return; | 836 return; |
835 updateLineProperties(); | 837 updateLineProperties(); |
836 | 838 |
837 // optimization - scroll the existing image where possible and | 839 // optimization - scroll the existing image where possible and |
838 // avoid expensive text drawing for parts of the image that | 840 // avoid expensive text drawing for parts of the image that |
839 // can simply be moved up or down | 841 // can simply be moved up or down |
846 int columns = _screenWindow->windowColumns(); | 848 int columns = _screenWindow->windowColumns(); |
847 | 849 |
848 setScroll( _screenWindow->currentLine() , _screenWindow->lineCount() ); | 850 setScroll( _screenWindow->currentLine() , _screenWindow->lineCount() ); |
849 | 851 |
850 if (!_image) | 852 if (!_image) |
851 updateImageSize(); // Create _image | 853 updateImageSize(); // Create _image |
852 | 854 |
853 Q_ASSERT( this->_usedLines <= this->_lines ); | 855 Q_ASSERT( this->_usedLines <= this->_lines ); |
854 Q_ASSERT( this->_usedColumns <= this->_columns ); | 856 Q_ASSERT( this->_usedColumns <= this->_columns ); |
855 | 857 |
856 int y,x,len; | 858 int y,x,len; |
876 // be 'dirty' ( ie. have changed from the old _image to the new _image ) and | 878 // be 'dirty' ( ie. have changed from the old _image to the new _image ) and |
877 // which therefore need to be repainted | 879 // which therefore need to be repainted |
878 int dirtyLineCount = 0; | 880 int dirtyLineCount = 0; |
879 | 881 |
880 for (y = 0; y < linesToUpdate; y++) | 882 for (y = 0; y < linesToUpdate; y++) |
881 { | 883 { |
882 const Character* currentLine = &_image[y*this->_columns]; | 884 const Character* currentLine = &_image[y*this->_columns]; |
883 const Character* const newLine = &newimg[y*columns]; | 885 const Character* const newLine = &newimg[y*columns]; |
884 | 886 |
885 bool updateLine = false; | 887 bool updateLine = false; |
886 | 888 |
887 // The dirty mask indicates which characters need repainting. We also | 889 // The dirty mask indicates which characters need repainting. We also |
888 // mark surrounding neighbours dirty, in case the character exceeds | 890 // mark surrounding neighbours dirty, in case the character exceeds |
889 // its cell boundaries | 891 // its cell boundaries |
890 memset(dirtyMask, 0, columnsToUpdate+2); | 892 memset(dirtyMask, 0, columnsToUpdate+2); |
891 | 893 |
892 for( x = 0 ; x < columnsToUpdate ; x++) | 894 for( x = 0 ; x < columnsToUpdate ; x++) |
893 { | |
894 if ( newLine[x] != currentLine[x] ) | |
895 { | 895 { |
896 dirtyMask[x] = true; | 896 if ( newLine[x] != currentLine[x] ) |
897 } | 897 { |
898 } | 898 dirtyMask[x] = true; |
899 | 899 } |
900 if (!_resizing) // not while _resizing, we're expecting a paintEvent | 900 } |
901 for (x = 0; x < columnsToUpdate; x++) | 901 |
902 { | 902 if (!_resizing) // not while _resizing, we're expecting a paintEvent |
903 _hasBlinker |= (newLine[x].rendition & RE_BLINK); | 903 for (x = 0; x < columnsToUpdate; x++) |
904 | 904 { |
905 // Start drawing if this character or the next one differs. | 905 _hasBlinker |= (newLine[x].rendition & RE_BLINK); |
906 // We also take the next one into account to handle the situation | 906 |
907 // where characters exceed their cell width. | 907 // Start drawing if this character or the next one differs. |
908 if (dirtyMask[x]) | 908 // We also take the next one into account to handle the situation |
909 { | 909 // where characters exceed their cell width. |
910 quint16 c = newLine[x+0].character; | 910 if (dirtyMask[x]) |
911 if ( !c ) | 911 { |
912 continue; | 912 quint16 c = newLine[x+0].character; |
913 int p = 0; | 913 if ( !c ) |
914 disstrU[p++] = c; //fontMap(c); | 914 continue; |
915 bool lineDraw = isLineChar(c); | 915 int p = 0; |
916 bool doubleWidth = (x+1 == columnsToUpdate) ? false : (newLine[x+1].character == 0); | 916 disstrU[p++] = c; //fontMap(c); |
917 cr = newLine[x].rendition; | 917 bool lineDraw = isLineChar(c); |
918 _clipboard = newLine[x].backgroundColor; | 918 bool doubleWidth = (x+1 == columnsToUpdate) ? false : (newLine[x+1].character == 0); |
919 if (newLine[x].foregroundColor != cf) cf = newLine[x].foregroundColor; | 919 cr = newLine[x].rendition; |
920 int lln = columnsToUpdate - x; | 920 _clipboard = newLine[x].backgroundColor; |
921 for (len = 1; len < lln; len++) | 921 if (newLine[x].foregroundColor != cf) cf = newLine[x].foregroundColor; |
922 int lln = columnsToUpdate - x; | |
923 for (len = 1; len < lln; len++) | |
924 { | |
925 const Character& ch = newLine[x+len]; | |
926 | |
927 if (!ch.character) | |
928 continue; // Skip trailing part of multi-col chars. | |
929 | |
930 bool nextIsDoubleWidth = (x+len+1 == columnsToUpdate) ? false : (newLine[x+len+1].character == 0); | |
931 | |
932 if ( ch.foregroundColor != cf || | |
933 ch.backgroundColor != _clipboard || | |
934 ch.rendition != cr || | |
935 !dirtyMask[x+len] || | |
936 isLineChar(c) != lineDraw || | |
937 nextIsDoubleWidth != doubleWidth ) | |
938 break; | |
939 | |
940 disstrU[p++] = c; //fontMap(c); | |
941 } | |
942 | |
943 QString unistr(disstrU, p); | |
944 | |
945 bool saveFixedFont = _fixedFont; | |
946 if (lineDraw) | |
947 _fixedFont = false; | |
948 if (doubleWidth) | |
949 _fixedFont = false; | |
950 | |
951 updateLine = true; | |
952 | |
953 _fixedFont = saveFixedFont; | |
954 x += len - 1; | |
955 } | |
956 | |
957 } | |
958 | |
959 //both the top and bottom halves of double height _lines must always be redrawn | |
960 //although both top and bottom halves contain the same characters, only | |
961 //the top one is actually | |
962 //drawn. | |
963 if (_lineProperties.count() > y) | |
964 updateLine |= (_lineProperties[y] & LINE_DOUBLEHEIGHT); | |
965 | |
966 // if the characters on the line are different in the old and the new _image | |
967 // then this line must be repainted. | |
968 if (updateLine) | |
922 { | 969 { |
923 const Character& ch = newLine[x+len]; | 970 dirtyLineCount++; |
924 | 971 |
925 if (!ch.character) | 972 // add the area occupied by this line to the region which needs to be |
926 continue; // Skip trailing part of multi-col chars. | 973 // repainted |
927 | 974 QRect dirtyRect = QRect( _leftMargin+tLx , |
928 bool nextIsDoubleWidth = (x+len+1 == columnsToUpdate) ? false : (newLine[x+len+1].character == 0); | 975 _topMargin+tLy+_fontHeight*y , |
929 | 976 _fontWidth * columnsToUpdate , |
930 if ( ch.foregroundColor != cf || | 977 _fontHeight ); |
931 ch.backgroundColor != _clipboard || | 978 |
932 ch.rendition != cr || | 979 dirtyRegion |= dirtyRect; |
933 !dirtyMask[x+len] || | 980 } |
934 isLineChar(c) != lineDraw || | 981 |
935 nextIsDoubleWidth != doubleWidth ) | 982 // replace the line of characters in the old _image with the |
936 break; | 983 // current line of the new _image |
937 | 984 memcpy((void*)currentLine,(const void*)newLine,columnsToUpdate*sizeof(Character)); |
938 disstrU[p++] = c; //fontMap(c); | 985 } |
939 } | |
940 | |
941 QString unistr(disstrU, p); | |
942 | |
943 bool saveFixedFont = _fixedFont; | |
944 if (lineDraw) | |
945 _fixedFont = false; | |
946 if (doubleWidth) | |
947 _fixedFont = false; | |
948 | |
949 updateLine = true; | |
950 | |
951 _fixedFont = saveFixedFont; | |
952 x += len - 1; | |
953 } | |
954 | |
955 } | |
956 | |
957 //both the top and bottom halves of double height _lines must always be redrawn | |
958 //although both top and bottom halves contain the same characters, only | |
959 //the top one is actually | |
960 //drawn. | |
961 if (_lineProperties.count() > y) | |
962 updateLine |= (_lineProperties[y] & LINE_DOUBLEHEIGHT); | |
963 | |
964 // if the characters on the line are different in the old and the new _image | |
965 // then this line must be repainted. | |
966 if (updateLine) | |
967 { | |
968 dirtyLineCount++; | |
969 | |
970 // add the area occupied by this line to the region which needs to be | |
971 // repainted | |
972 QRect dirtyRect = QRect( _leftMargin+tLx , | |
973 _topMargin+tLy+_fontHeight*y , | |
974 _fontWidth * columnsToUpdate , | |
975 _fontHeight ); | |
976 | |
977 dirtyRegion |= dirtyRect; | |
978 } | |
979 | |
980 // replace the line of characters in the old _image with the | |
981 // current line of the new _image | |
982 memcpy((void*)currentLine,(const void*)newLine,columnsToUpdate*sizeof(Character)); | |
983 } | |
984 | 986 |
985 // if the new _image is smaller than the previous _image, then ensure that the area | 987 // if the new _image is smaller than the previous _image, then ensure that the area |
986 // outside the new _image is cleared | 988 // outside the new _image is cleared |
987 if ( linesToUpdate < _usedLines ) | 989 if ( linesToUpdate < _usedLines ) |
988 { | 990 { |
989 dirtyRegion |= QRect( _leftMargin+tLx , | 991 dirtyRegion |= QRect( _leftMargin+tLx , |
990 _topMargin+tLy+_fontHeight*linesToUpdate , | 992 _topMargin+tLy+_fontHeight*linesToUpdate , |
991 _fontWidth * this->_columns , | 993 _fontWidth * this->_columns , |
992 _fontHeight * (_usedLines-linesToUpdate) ); | 994 _fontHeight * (_usedLines-linesToUpdate) ); |
993 } | 995 } |
994 _usedLines = linesToUpdate; | 996 _usedLines = linesToUpdate; |
995 | 997 |
996 if ( columnsToUpdate < _usedColumns ) | 998 if ( columnsToUpdate < _usedColumns ) |
997 { | 999 { |
998 dirtyRegion |= QRect( _leftMargin+tLx+columnsToUpdate*_fontWidth , | 1000 dirtyRegion |= QRect( _leftMargin+tLx+columnsToUpdate*_fontWidth , |
999 _topMargin+tLy , | 1001 _topMargin+tLy , |
1000 _fontWidth * (_usedColumns-columnsToUpdate) , | 1002 _fontWidth * (_usedColumns-columnsToUpdate) , |
1001 _fontHeight * this->_lines ); | 1003 _fontHeight * this->_lines ); |
1002 } | 1004 } |
1003 _usedColumns = columnsToUpdate; | 1005 _usedColumns = columnsToUpdate; |
1004 | 1006 |
1005 dirtyRegion |= _inputMethodData.previousPreeditRect; | 1007 dirtyRegion |= _inputMethodData.previousPreeditRect; |
1006 | 1008 |
1007 // update the parts of the display which have changed | 1009 // update the parts of the display which have changed |
1015 } | 1017 } |
1016 | 1018 |
1017 void TerminalView::showResizeNotification() | 1019 void TerminalView::showResizeNotification() |
1018 { | 1020 { |
1019 if (_terminalSizeHint && isVisible()) | 1021 if (_terminalSizeHint && isVisible()) |
1020 { | 1022 { |
1021 if (_terminalSizeStartup) { | 1023 if (_terminalSizeStartup) { |
1022 _terminalSizeStartup=false; | 1024 _terminalSizeStartup=false; |
1023 return; | 1025 return; |
1024 } | 1026 } |
1025 if (!_resizeWidget) | 1027 if (!_resizeWidget) |
1026 { | 1028 { |
1027 _resizeWidget = new QLabel(("Size: XXX x XXX"), this); | 1029 _resizeWidget = new QLabel(("Size: XXX x XXX"), this); |
1028 _resizeWidget->setMinimumWidth(_resizeWidget->fontMetrics().width(("Size: XXX x XXX"))); | 1030 _resizeWidget->setMinimumWidth(_resizeWidget->fontMetrics().width(("Size: XXX x XXX"))); |
1029 _resizeWidget->setMinimumHeight(_resizeWidget->sizeHint().height()); | 1031 _resizeWidget->setMinimumHeight(_resizeWidget->sizeHint().height()); |
1030 _resizeWidget->setAlignment(Qt::AlignCenter); | 1032 _resizeWidget->setAlignment(Qt::AlignCenter); |
1031 | 1033 |
1032 _resizeWidget->setStyleSheet("background-color:palette(window);border-style:solid;border-width:1px;border-color:palette(dark)"); | 1034 _resizeWidget->setStyleSheet("background-color:palette(window);border-style:solid;border-width:1px;border-color:palette(dark)"); |
1033 | 1035 |
1034 _resizeTimer = new QTimer(this); | 1036 _resizeTimer = new QTimer(this); |
1035 _resizeTimer->setSingleShot(true); | 1037 _resizeTimer->setSingleShot(true); |
1036 connect(_resizeTimer, SIGNAL(timeout()), _resizeWidget, SLOT(hide())); | 1038 connect(_resizeTimer, SIGNAL(timeout()), _resizeWidget, SLOT(hide())); |
1037 | 1039 |
1038 } | 1040 } |
1039 QString sizeStr; | 1041 QString sizeStr; |
1040 sizeStr.sprintf("Size: %d x %d", _columns, _lines); | 1042 sizeStr.sprintf("Size: %d x %d", _columns, _lines); |
1041 _resizeWidget->setText(sizeStr); | 1043 _resizeWidget->setText(sizeStr); |
1042 _resizeWidget->move((width()-_resizeWidget->width())/2, | 1044 _resizeWidget->move((width()-_resizeWidget->width())/2, |
1043 (height()-_resizeWidget->height())/2+20); | 1045 (height()-_resizeWidget->height())/2+20); |
1044 _resizeWidget->show(); | 1046 _resizeWidget->show(); |
1045 _resizeTimer->start(1000); | 1047 _resizeTimer->start(1000); |
1046 } | 1048 } |
1047 } | 1049 } |
1048 | 1050 |
1049 void TerminalView::setBlinkingCursor(bool blink) | 1051 void TerminalView::setBlinkingCursor(bool blink) |
1050 { | 1052 { |
1051 _hasBlinkingCursor=blink; | 1053 _hasBlinkingCursor=blink; |
1052 | 1054 |
1053 if (blink && !_blinkCursorTimer->isActive()) | 1055 if (blink && !_blinkCursorTimer->isActive()) |
1054 _blinkCursorTimer->start(BLINK_DELAY); | 1056 _blinkCursorTimer->start(BLINK_DELAY); |
1055 | 1057 |
1056 if (!blink && _blinkCursorTimer->isActive()) | 1058 if (!blink && _blinkCursorTimer->isActive()) |
1057 { | 1059 { |
1058 _blinkCursorTimer->stop(); | 1060 _blinkCursorTimer->stop(); |
1059 if (_cursorBlinking) | 1061 if (_cursorBlinking) |
1060 blinkCursorEvent(); | 1062 blinkCursorEvent(); |
1061 else | 1063 else |
1062 _cursorBlinking = false; | 1064 _cursorBlinking = false; |
1063 } | 1065 } |
1064 } | 1066 } |
1065 | 1067 |
1066 void TerminalView::paintEvent( QPaintEvent* pe ) | 1068 void TerminalView::paintEvent( QPaintEvent* pe ) |
1067 { | 1069 { |
1068 updateImage(); | 1070 updateImage(); |
1069 //qDebug("%s %d paintEvent", __FILE__, __LINE__); | 1071 //qDebug("%s %d paintEvent", __FILE__, __LINE__); |
1070 QPainter paint(this); | 1072 QPainter paint(this); |
1071 //qDebug("%s %d paintEvent %d %d", __FILE__, __LINE__, paint.window().top(), paint.window().right()); | 1073 //qDebug("%s %d paintEvent %d %d", __FILE__, __LINE__, paint.window().top(), paint.window().right()); |
1072 | 1074 |
1073 foreach (QRect rect, (pe->region() & contentsRect()).rects()) | 1075 foreach (QRect rect, (pe->region() & contentsRect()).rects()) |
1074 { | 1076 { |
1075 drawBackground(paint,rect,palette().background().color(), true /* use opacity setting */); | 1077 drawBackground(paint,rect,palette().background().color(), true /* use opacity setting */); |
1076 drawContents(paint, rect); | 1078 drawContents(paint, rect); |
1077 } | 1079 } |
1078 // drawBackground(paint,contentsRect(),palette().background().color(), true /* use opacity setting */); | 1080 // drawBackground(paint,contentsRect(),palette().background().color(), true /* use opacity setting */); |
1079 // drawContents(paint, contentsRect()); | 1081 // drawContents(paint, contentsRect()); |
1080 drawInputMethodPreeditString(paint,preeditRect()); | 1082 //drawInputMethodPreeditString(paint,preeditRect()); |
1081 paintFilters(paint); | 1083 //paintFilters(paint); |
1082 | 1084 |
1083 paint.end(); | 1085 paint.end(); |
1084 } | 1086 } |
1085 | 1087 |
1086 QPoint TerminalView::cursorPosition() const | 1088 QPoint TerminalView::cursorPosition() const |
1087 { | 1089 { |
1088 if (_screenWindow) | 1090 if (_screenWindow) |
1089 return _screenWindow->cursorPosition(); | 1091 return _screenWindow->cursorPosition(); |
1090 else | 1092 else |
1091 return QPoint(0,0); | 1093 return QPoint(0,0); |
1092 } | 1094 } |
1093 | 1095 |
1094 QRect TerminalView::preeditRect() const | 1096 QRect TerminalView::preeditRect() const |
1095 { | 1097 { |
1096 const int preeditLength = string_width(_inputMethodData.preeditString); | 1098 const int preeditLength = string_width(_inputMethodData.preeditString); |
1097 | 1099 |
1098 if ( preeditLength == 0 ) | 1100 if ( preeditLength == 0 ) |
1099 return QRect(); | 1101 return QRect(); |
1100 | 1102 |
1101 return QRect(_leftMargin + _fontWidth*cursorPosition().x(), | 1103 return QRect(_leftMargin + _fontWidth*cursorPosition().x(), |
1102 _topMargin + _fontHeight*cursorPosition().y(), | 1104 _topMargin + _fontHeight*cursorPosition().y(), |
1103 _fontWidth*preeditLength, | 1105 _fontWidth*preeditLength, |
1104 _fontHeight); | 1106 _fontHeight); |
1105 } | 1107 } |
1106 | 1108 |
1107 void TerminalView::drawInputMethodPreeditString(QPainter& painter , const QRect& rect) | 1109 void TerminalView::drawInputMethodPreeditString(QPainter& painter , const QRect& rect) |
1108 { | 1110 { |
1109 if ( _inputMethodData.preeditString.isEmpty() ) { | 1111 if ( _inputMethodData.preeditString.isEmpty() ) { |
1110 return; | 1112 return; |
1111 } | 1113 } |
1112 const QPoint cursorPos = cursorPosition(); | 1114 const QPoint cursorPos = cursorPosition(); |
1113 | 1115 |
1114 bool invertColors = false; | 1116 bool invertColors = false; |
1115 const QColor background = _colorTable[DEFAULT_BACK_COLOR].color; | 1117 const QColor background = _colorTable[DEFAULT_BACK_COLOR].color; |
1116 const QColor foreground = _colorTable[DEFAULT_FORE_COLOR].color; | 1118 const QColor foreground = _colorTable[DEFAULT_FORE_COLOR].color; |
1117 const Character* style = &_image[loc(cursorPos.x(),cursorPos.y())]; | 1119 const Character* style = &_image[loc(cursorPos.x(),cursorPos.y())]; |
1118 | 1120 |
1119 drawBackground(painter,rect,background,true); | 1121 drawBackground(painter,rect,background,true); |
1120 drawCursor(painter,rect,foreground,background,invertColors); | 1122 drawCursor(painter,rect,foreground,background,invertColors); |
1121 drawCharacters(painter,rect,_inputMethodData.preeditString,style,invertColors); | 1123 drawCharacters(painter,rect,_inputMethodData.preeditString,style,invertColors); |
1122 | 1124 |
1123 _inputMethodData.previousPreeditRect = rect; | 1125 _inputMethodData.previousPreeditRect = rect; |
1124 } | 1126 } |
1125 | 1127 |
1126 FilterChain* TerminalView::filterChain() const | 1128 FilterChain* TerminalView::filterChain() const |
1127 { | 1129 { |
1128 return _filterChain; | 1130 return _filterChain; |
1129 } | 1131 } |
1130 | 1132 |
1131 void TerminalView::paintFilters(QPainter& painter) | 1133 void TerminalView::paintFilters(QPainter& painter) |
1132 { | 1134 { |
1133 //qDebug("%s %d paintFilters", __FILE__, __LINE__); | 1135 //qDebug("%s %d paintFilters", __FILE__, __LINE__); |
1134 | 1136 |
1135 // get color of character under mouse and use it to draw | 1137 // get color of character under mouse and use it to draw |
1136 // lines for filters | 1138 // lines for filters |
1137 QPoint cursorPos = mapFromGlobal(QCursor::pos()); | 1139 QPoint cursorPos = mapFromGlobal(QCursor::pos()); |
1138 int cursorLine; | 1140 int cursorLine; |
1139 int cursorColumn; | 1141 int cursorColumn; |
1140 getCharacterPosition( cursorPos , cursorLine , cursorColumn ); | 1142 getCharacterPosition( cursorPos , cursorLine , cursorColumn ); |
1141 Character cursorCharacter = _image[loc(cursorColumn,cursorLine)]; | 1143 Character cursorCharacter = _image[loc(cursorColumn,cursorLine)]; |
1142 | 1144 |
1143 painter.setPen( QPen(cursorCharacter.foregroundColor.color(colorTable())) ); | 1145 painter.setPen( QPen(cursorCharacter.foregroundColor.color(colorTable())) ); |
1144 | 1146 |
1145 // iterate over hotspots identified by the display's currently active filters | 1147 // iterate over hotspots identified by the display's currently active filters |
1146 // and draw appropriate visuals to indicate the presence of the hotspot | 1148 // and draw appropriate visuals to indicate the presence of the hotspot |
1147 | 1149 |
1148 QList<Filter::HotSpot*> spots = _filterChain->hotSpots(); | 1150 QList<Filter::HotSpot*> spots = _filterChain->hotSpots(); |
1149 QListIterator<Filter::HotSpot*> iter(spots); | 1151 QListIterator<Filter::HotSpot*> iter(spots); |
1150 while (iter.hasNext()) | 1152 while (iter.hasNext()) |
1151 { | 1153 { |
1152 Filter::HotSpot* spot = iter.next(); | 1154 Filter::HotSpot* spot = iter.next(); |
1153 | 1155 |
1154 for ( int line = spot->startLine() ; line <= spot->endLine() ; line++ ) | 1156 for ( int line = spot->startLine() ; line <= spot->endLine() ; line++ ) |
1155 { | 1157 { |
1156 int startColumn = 0; | 1158 int startColumn = 0; |
1157 int endColumn = _columns-1; // TODO use number of _columns which are actually | 1159 int endColumn = _columns-1; // TODO use number of _columns which are actually |
1158 // occupied on this line rather than the width of the | 1160 // occupied on this line rather than the width of the |
1159 // display in _columns | 1161 // display in _columns |
1160 | 1162 |
1161 // ignore whitespace at the end of the lines | 1163 // ignore whitespace at the end of the lines |
1162 while ( QChar(_image[loc(endColumn,line)].character).isSpace() && endColumn > 0 ) | 1164 while ( QChar(_image[loc(endColumn,line)].character).isSpace() && endColumn > 0 ) |
1163 endColumn--; | 1165 endColumn--; |
1164 | 1166 |
1165 // increment here because the column which we want to set 'endColumn' to | 1167 // increment here because the column which we want to set 'endColumn' to |
1166 // is the first whitespace character at the end of the line | 1168 // is the first whitespace character at the end of the line |
1167 endColumn++; | 1169 endColumn++; |
1168 | 1170 |
1169 if ( line == spot->startLine() ) | 1171 if ( line == spot->startLine() ) |
1170 startColumn = spot->startColumn(); | 1172 startColumn = spot->startColumn(); |
1171 if ( line == spot->endLine() ) | 1173 if ( line == spot->endLine() ) |
1172 endColumn = spot->endColumn(); | 1174 endColumn = spot->endColumn(); |
1173 | 1175 |
1174 // subtract one pixel from | 1176 // subtract one pixel from |
1175 // the right and bottom so that | 1177 // the right and bottom so that |
1176 // we do not overdraw adjacent | 1178 // we do not overdraw adjacent |
1177 // hotspots | 1179 // hotspots |
1178 // | 1180 // |
1179 // subtracting one pixel from all sides also prevents an edge case where | 1181 // subtracting one pixel from all sides also prevents an edge case where |
1180 // moving the mouse outside a link could still leave it underlined | 1182 // moving the mouse outside a link could still leave it underlined |
1181 // because the check below for the position of the cursor | 1183 // because the check below for the position of the cursor |
1182 // finds it on the border of the target area | 1184 // finds it on the border of the target area |
1183 QRect r; | 1185 QRect r; |
1184 r.setCoords( startColumn*_fontWidth + 1, line*_fontHeight + 1, | 1186 r.setCoords( startColumn*_fontWidth + 1, line*_fontHeight + 1, |
1185 endColumn*_fontWidth - 1, (line+1)*_fontHeight - 1 ); | 1187 endColumn*_fontWidth - 1, (line+1)*_fontHeight - 1 ); |
1186 | 1188 |
1187 // Underline link hotspots | 1189 // Underline link hotspots |
1188 if ( spot->type() == Filter::HotSpot::Link ) | 1190 if ( spot->type() == Filter::HotSpot::Link ) |
1189 { | 1191 { |
1190 QFontMetrics metrics(font()); | 1192 QFontMetrics metrics(font()); |
1191 | 1193 |
1192 // find the baseline (which is the invisible line that the characters in the font sit on, | 1194 // find the baseline (which is the invisible line that the characters in the font sit on, |
1193 // with some having tails dangling below) | 1195 // with some having tails dangling below) |
1194 int baseline = r.bottom() - metrics.descent(); | 1196 int baseline = r.bottom() - metrics.descent(); |
1195 // find the position of the underline below that | 1197 // find the position of the underline below that |
1196 int underlinePos = baseline + metrics.underlinePos(); | 1198 int underlinePos = baseline + metrics.underlinePos(); |
1197 | 1199 |
1198 if ( r.contains( mapFromGlobal(QCursor::pos()) ) ) | 1200 if ( r.contains( mapFromGlobal(QCursor::pos()) ) ) |
1199 painter.drawLine( r.left() , underlinePos , | 1201 painter.drawLine( r.left() , underlinePos , |
1200 r.right() , underlinePos ); | 1202 r.right() , underlinePos ); |
1201 } | 1203 } |
1202 // Marker hotspots simply have a transparent rectanglular shape | 1204 // Marker hotspots simply have a transparent rectanglular shape |
1203 // drawn on top of them | 1205 // drawn on top of them |
1204 else if ( spot->type() == Filter::HotSpot::Marker ) | 1206 else if ( spot->type() == Filter::HotSpot::Marker ) |
1205 { | 1207 { |
1206 //TODO - Do not use a hardcoded colour for this | 1208 //TODO - Do not use a hardcoded colour for this |
1207 painter.fillRect(r,QBrush(QColor(255,0,0,120))); | 1209 painter.fillRect(r,QBrush(QColor(255,0,0,120))); |
1208 } | 1210 } |
1209 } | 1211 } |
1210 } | 1212 } |
1211 } | 1213 } |
1212 void TerminalView::drawContents(QPainter &paint, const QRect &rect) | 1214 void TerminalView::drawContents(QPainter &paint, const QRect &rect) |
1213 { | 1215 { |
1214 //qDebug("%s %d drawContents and rect x=%d y=%d w=%d h=%d", __FILE__, __LINE__, rect.x(), rect.y(),rect.width(),rect.height()); | 1216 //qDebug("%s %d drawContents and rect x=%d y=%d w=%d h=%d", __FILE__, __LINE__, rect.x(), rect.y(),rect.width(),rect.height()); |
1215 | 1217 |
1216 QPoint tL = contentsRect().topLeft(); | 1218 QPoint topLeft = contentsRect().topLeft(); |
1217 // int tLx = tL.x(); | 1219 // Take the topmost vertical position for the view. |
1218 int tLy = tL.y(); | 1220 int topLeftY = topLeft.y(); |
1219 | 1221 |
1220 int tLx = (_contentWidth - _usedColumns * _fontWidth)/2; | 1222 // In Konsole, the view has been centered. Don't do that here, since there |
1221 // int tLy = (_contentHeight - _usedLines * _fontHeight)/2; | 1223 // are strange hopping effects during a resize when the view does no match |
1222 //qDebug("%d %d %d %d", tLx, tLy, _contentWidth, _usedColumns * _fontWidth); | 1224 // exactly the widget width. |
1223 | 1225 // int topLeftX = (_contentWidth - _usedColumns * _fontWidth) / 2; |
1224 int lux = qMin(_usedColumns-1, qMax(0,(rect.left() - tLx - _leftMargin ) / _fontWidth)); | 1226 int topLeftX = 0; |
1225 int luy = qMin(_usedLines-1, qMax(0, (rect.top() - tLy - _topMargin ) / _fontHeight)); | 1227 |
1226 int rlx = qMin(_usedColumns-1, qMax(0, (rect.right() - tLx - _leftMargin ) / _fontWidth)); | 1228 int leftUpperX = qMin(_usedColumns-1, qMax(0,(rect.left() - topLeftX - _leftMargin ) / _fontWidth)); |
1227 int rly = qMin(_usedLines-1, qMax(0, (rect.bottom() - tLy - _topMargin ) / _fontHeight)); | 1229 int leftUpperY = qMin(_usedLines-1, qMax(0, (rect.top() - topLeftY - _topMargin ) / _fontHeight)); |
1230 int rightLowerX = qMin(_usedColumns-1, qMax(0, (rect.right() - topLeftX - _leftMargin ) / _fontWidth)); | |
1231 int rightLowerY = qMin(_usedLines-1, qMax(0, (rect.bottom() - topLeftY - _topMargin ) / _fontHeight)); | |
1228 | 1232 |
1229 const int bufferSize = _usedColumns; | 1233 const int bufferSize = _usedColumns; |
1230 QChar *disstrU = new QChar[bufferSize]; | 1234 QChar *disstrU = new QChar[bufferSize]; |
1231 for (int y = luy; y <= rly; y++) | 1235 for (int y = leftUpperY; y <= rightLowerY; y++) |
1232 { | 1236 { |
1233 quint16 c = _image[loc(lux,y)].character; | 1237 quint16 c = _image[loc(leftUpperX,y)].character; |
1234 int x = lux; | 1238 int x = leftUpperX; |
1235 if(!c && x) | 1239 if(!c && x) |
1236 x--; // Search for start of multi-column character | 1240 x--; // Search for start of multi-column character |
1237 for (; x <= rlx; x++) | 1241 for (; x <= rightLowerX; x++) |
1238 { | |
1239 int len = 1; | |
1240 int p = 0; | |
1241 | |
1242 // is this a single character or a sequence of characters ? | |
1243 if ( _image[loc(x,y)].rendition & RE_EXTENDED_CHAR ) | |
1244 { | |
1245 // sequence of characters | |
1246 ushort extendedCharLength = 0; | |
1247 ushort* chars = ExtendedCharTable::instance | |
1248 .lookupExtendedChar(_image[loc(x,y)].charSequence,extendedCharLength); | |
1249 for ( int index = 0 ; index < extendedCharLength ; index++ ) | |
1250 { | 1242 { |
1251 Q_ASSERT( p < bufferSize ); | 1243 int len = 1; |
1252 disstrU[p++] = chars[index]; | 1244 int p = 0; |
1253 } | 1245 |
1254 } | 1246 // is this a single character or a sequence of characters ? |
1255 else | 1247 if ( _image[loc(x,y)].rendition & RE_EXTENDED_CHAR ) |
1256 { | 1248 { |
1257 // single character | 1249 // sequence of characters |
1258 c = _image[loc(x,y)].character; | 1250 ushort extendedCharLength = 0; |
1259 if (c) | 1251 ushort* chars = ExtendedCharTable::instance |
1260 { | 1252 .lookupExtendedChar(_image[loc(x,y)].charSequence,extendedCharLength); |
1261 Q_ASSERT( p < bufferSize ); | 1253 for ( int index = 0 ; index < extendedCharLength ; index++ ) |
1262 disstrU[p++] = c; //fontMap(c); | 1254 { |
1263 } | 1255 Q_ASSERT( p < bufferSize ); |
1264 } | 1256 disstrU[p++] = chars[index]; |
1265 | 1257 } |
1266 bool lineDraw = isLineChar(c); | 1258 } |
1267 bool doubleWidth = (_image[ qMin(loc(x,y)+1,_imageSize) ].character == 0); | 1259 else |
1268 CharacterColor currentForeground = _image[loc(x,y)].foregroundColor; | 1260 { |
1269 CharacterColor currentBackground = _image[loc(x,y)].backgroundColor; | 1261 // single character |
1270 quint8 currentRendition = _image[loc(x,y)].rendition; | 1262 c = _image[loc(x,y)].character; |
1271 | 1263 if (c) |
1272 while (x+len <= rlx && | 1264 { |
1273 _image[loc(x+len,y)].foregroundColor == currentForeground && | 1265 Q_ASSERT( p < bufferSize ); |
1274 _image[loc(x+len,y)].backgroundColor == currentBackground && | 1266 disstrU[p++] = c; //fontMap(c); |
1275 _image[loc(x+len,y)].rendition == currentRendition && | 1267 } |
1276 (_image[ qMin(loc(x+len,y)+1,_imageSize) ].character == 0) == doubleWidth && | 1268 } |
1277 isLineChar( c = _image[loc(x+len,y)].character) == lineDraw) // Assignment! | 1269 |
1278 { | 1270 bool lineDraw = isLineChar(c); |
1279 if (c) | 1271 bool doubleWidth = (_image[ qMin(loc(x,y)+1,_imageSize) ].character == 0); |
1280 disstrU[p++] = c; //fontMap(c); | 1272 CharacterColor currentForeground = _image[loc(x,y)].foregroundColor; |
1281 if (doubleWidth) // assert((_image[loc(x+len,y)+1].character == 0)), see above if condition | 1273 CharacterColor currentBackground = _image[loc(x,y)].backgroundColor; |
1282 len++; // Skip trailing part of multi-column character | 1274 quint8 currentRendition = _image[loc(x,y)].rendition; |
1283 len++; | 1275 |
1284 } | 1276 while (x+len <= rightLowerX && |
1285 if ((x+len < _usedColumns) && (!_image[loc(x+len,y)].character)) | 1277 _image[loc(x+len,y)].foregroundColor == currentForeground && |
1286 len++; // Adjust for trailing part of multi-column character | 1278 _image[loc(x+len,y)].backgroundColor == currentBackground && |
1287 | 1279 _image[loc(x+len,y)].rendition == currentRendition && |
1288 bool save__fixedFont = _fixedFont; | 1280 (_image[ qMin(loc(x+len,y)+1,_imageSize) ].character == 0) == doubleWidth && |
1289 if (lineDraw) | 1281 isLineChar( c = _image[loc(x+len,y)].character) == lineDraw) // Assignment! |
1282 { | |
1283 if (c) | |
1284 disstrU[p++] = c; //fontMap(c); | |
1285 if (doubleWidth) // assert((_image[loc(x+len,y)+1].character == 0)), see above if condition | |
1286 len++; // Skip trailing part of multi-column character | |
1287 len++; | |
1288 } | |
1289 if ((x+len < _usedColumns) && (!_image[loc(x+len,y)].character)) | |
1290 len++; // Adjust for trailing part of multi-column character | |
1291 | |
1292 bool save__fixedFont = _fixedFont; | |
1293 if (lineDraw) | |
1290 _fixedFont = false; | 1294 _fixedFont = false; |
1291 if (doubleWidth) | 1295 if (doubleWidth) |
1292 _fixedFont = false; | 1296 _fixedFont = false; |
1293 QString unistr(disstrU,p); | 1297 QString unistr(disstrU,p); |
1294 | 1298 |
1295 if (y < _lineProperties.size()) | 1299 if (y < _lineProperties.size()) |
1296 { | 1300 { |
1297 if (_lineProperties[y] & LINE_DOUBLEWIDTH) { | 1301 if (_lineProperties[y] & LINE_DOUBLEWIDTH) { |
1298 paint.scale(2,1); | 1302 paint.scale(2,1); |
1299 } | 1303 } |
1300 | 1304 |
1301 if (_lineProperties[y] & LINE_DOUBLEHEIGHT) { | 1305 if (_lineProperties[y] & LINE_DOUBLEHEIGHT) { |
1302 paint.scale(1,2); | 1306 paint.scale(1,2); |
1303 } | 1307 } |
1304 } | 1308 } |
1305 | 1309 |
1306 //calculate the area in which the text will be drawn | 1310 // calculate the area in which the text will be drawn |
1307 QRect textArea = QRect( _leftMargin+tLx+_fontWidth*x , | 1311 QRect textArea = QRect( _leftMargin+topLeftX+_fontWidth*x , |
1308 _topMargin+tLy+_fontHeight*y , | 1312 _topMargin+topLeftY+_fontHeight*y , |
1309 _fontWidth*len, | 1313 _fontWidth*len, |
1310 _fontHeight); | 1314 _fontHeight); |
1311 | 1315 |
1312 //move the calculated area to take account of scaling applied to the painter. | 1316 // move the calculated area to take account of scaling applied to the painter. |
1313 //the position of the area from the origin (0,0) is scaled | 1317 // the position of the area from the origin (0,0) is scaled |
1314 //by the opposite of whatever | 1318 // by the opposite of whatever |
1315 //transformation has been applied to the painter. this ensures that | 1319 // transformation has been applied to the painter. this ensures that |
1316 //painting does actually start from textArea.topLeft() | 1320 // painting does actually start from textArea.topLeft() |
1317 //(instead of textArea.topLeft() * painter-scale) | 1321 // (instead of textArea.topLeft() * painter-scale) |
1318 QMatrix inverted = paint.matrix().inverted(); | 1322 QMatrix inverted = paint.matrix().inverted(); |
1319 // textArea.moveTopLeft( inverted.map(textArea.topLeft()) ); | 1323 textArea.moveCenter( inverted.map(textArea.center()) ); |
1320 textArea.moveCenter( inverted.map(textArea.center()) ); | 1324 |
1321 | 1325 |
1322 | 1326 //paint text fragment |
1323 //paint text fragment | 1327 drawTextFragment( paint, |
1324 drawTextFragment( paint, | 1328 textArea, |
1325 textArea, | 1329 unistr, |
1326 unistr, | 1330 &_image[loc(x,y)] ); |
1327 &_image[loc(x,y)] ); //, | 1331 |
1328 //0, | 1332 |
1329 //!_isPrinting ); | 1333 _fixedFont = save__fixedFont; |
1330 | 1334 |
1331 _fixedFont = save__fixedFont; | 1335 //reset back to single-width, single-height _lines |
1332 | 1336 paint.resetMatrix(); |
1333 //reset back to single-width, single-height _lines | 1337 |
1334 paint.resetMatrix(); | 1338 if (y < _lineProperties.size()-1) |
1335 | 1339 { |
1336 if (y < _lineProperties.size()-1) | 1340 //double-height _lines are represented by two adjacent _lines |
1337 { | 1341 //containing the same characters |
1338 //double-height _lines are represented by two adjacent _lines | 1342 //both _lines will have the LINE_DOUBLEHEIGHT attribute. |
1339 //containing the same characters | 1343 //If the current line has the LINE_DOUBLEHEIGHT attribute, |
1340 //both _lines will have the LINE_DOUBLEHEIGHT attribute. | 1344 //we can therefore skip the next line |
1341 //If the current line has the LINE_DOUBLEHEIGHT attribute, | 1345 if (_lineProperties[y] & LINE_DOUBLEHEIGHT) |
1342 //we can therefore skip the next line | 1346 y++; |
1343 if (_lineProperties[y] & LINE_DOUBLEHEIGHT) | 1347 } |
1344 y++; | 1348 x += len - 1; |
1345 } | 1349 } // for x |
1346 | 1350 } // for y |
1347 x += len - 1; | |
1348 } | |
1349 } | |
1350 delete [] disstrU; | 1351 delete [] disstrU; |
1351 } | 1352 } |
1352 | 1353 |
1353 void TerminalView::blinkEvent() | 1354 void TerminalView::blinkEvent() |
1354 { | 1355 { |
1360 update(); | 1361 update(); |
1361 } | 1362 } |
1362 | 1363 |
1363 QRect TerminalView::imageToWidget(const QRect& imageArea) const | 1364 QRect TerminalView::imageToWidget(const QRect& imageArea) const |
1364 { | 1365 { |
1365 //qDebug("%s %d imageToWidget", __FILE__, __LINE__); | 1366 //qDebug("%s %d imageToWidget", __FILE__, __LINE__); |
1366 QRect result; | 1367 QRect result; |
1367 result.setLeft( _leftMargin + _fontWidth * imageArea.left() ); | 1368 result.setLeft( _leftMargin + _fontWidth * imageArea.left() ); |
1368 result.setTop( _topMargin + _fontHeight * imageArea.top() ); | 1369 result.setTop( _topMargin + _fontHeight * imageArea.top() ); |
1369 result.setWidth( _fontWidth * imageArea.width() ); | 1370 result.setWidth( _fontWidth * imageArea.width() ); |
1370 result.setHeight( _fontHeight * imageArea.height() ); | 1371 result.setHeight( _fontHeight * imageArea.height() ); |
1371 | 1372 |
1372 return result; | 1373 return result; |
1373 } | 1374 } |
1374 | 1375 |
1375 void TerminalView::blinkCursorEvent() | 1376 void TerminalView::blinkCursorEvent() |
1376 { | 1377 { |
1377 _cursorBlinking = !_cursorBlinking; | 1378 _cursorBlinking = !_cursorBlinking; |
1393 } | 1394 } |
1394 | 1395 |
1395 void TerminalView::propagateSize() | 1396 void TerminalView::propagateSize() |
1396 { | 1397 { |
1397 if (_isFixedSize) | 1398 if (_isFixedSize) |
1398 { | 1399 { |
1399 setSize(_columns, _lines); | 1400 setSize(_columns, _lines); |
1400 QWidget::setFixedSize(sizeHint()); | 1401 QWidget::setFixedSize(sizeHint()); |
1401 parentWidget()->adjustSize(); | 1402 parentWidget()->adjustSize(); |
1402 parentWidget()->setFixedSize(parentWidget()->sizeHint()); | 1403 parentWidget()->setFixedSize(parentWidget()->sizeHint()); |
1403 return; | 1404 return; |
1404 } | 1405 } |
1405 if (_image) | 1406 if (_image) |
1406 updateImageSize(); | 1407 updateImageSize(); |
1407 } | 1408 } |
1408 | 1409 |
1409 void TerminalView::updateImageSize() | 1410 void TerminalView::updateImageSize() |
1410 { | 1411 { |
1411 //qDebug("%s %d updateImageSize", __FILE__, __LINE__); | 1412 //qDebug("%s %d updateImageSize", __FILE__, __LINE__); |
1412 Character* oldimg = _image; | 1413 Character* oldimg = _image; |
1413 int oldlin = _lines; | 1414 int oldlin = _lines; |
1414 int oldcol = _columns; | 1415 int oldcol = _columns; |
1415 | 1416 |
1416 makeImage(); | 1417 makeImage(); |
1418 | 1419 |
1419 // copy the old image to reduce flicker | 1420 // copy the old image to reduce flicker |
1420 int lines = qMin(oldlin,_lines); | 1421 int lines = qMin(oldlin,_lines); |
1421 int columns = qMin(oldcol,_columns); | 1422 int columns = qMin(oldcol,_columns); |
1422 | 1423 |
1423 //qDebug("%s %d updateImageSize", __FILE__, __LINE__); | 1424 //qDebug("%s %d updateImageSize", __FILE__, __LINE__); |
1424 if (oldimg) | 1425 if (oldimg) |
1425 { | 1426 { |
1426 for (int line = 0; line < lines; line++) | 1427 for (int line = 0; line < lines; line++) |
1427 { | 1428 { |
1428 memcpy((void*)&_image[_columns*line], | 1429 memcpy((void*)&_image[_columns*line], |
1429 (void*)&oldimg[oldcol*line],columns*sizeof(Character)); | 1430 (void*)&oldimg[oldcol*line],columns*sizeof(Character)); |
1430 } | 1431 } |
1431 delete[] oldimg; | 1432 delete[] oldimg; |
1432 } | 1433 } |
1433 | 1434 |
1434 //qDebug("%s %d updateImageSize", __FILE__, __LINE__); | 1435 //qDebug("%s %d updateImageSize", __FILE__, __LINE__); |
1435 if (_screenWindow) | 1436 if (_screenWindow) |
1436 _screenWindow->setWindowLines(_lines); | 1437 _screenWindow->setWindowLines(_lines); |
1437 | 1438 |
1438 _resizing = (oldlin!=_lines) || (oldcol!=_columns); | 1439 _resizing = (oldlin!=_lines) || (oldcol!=_columns); |
1439 | 1440 |
1440 if ( _resizing ) | 1441 if ( _resizing ) |
1441 { | 1442 { |
1442 //qDebug("%s %d updateImageSize", __FILE__, __LINE__); | 1443 //qDebug("%s %d updateImageSize", __FILE__, __LINE__); |
1443 showResizeNotification(); | 1444 showResizeNotification(); |
1444 emit changedContentSizeSignal(_contentHeight, _contentWidth); // expose resizeEvent | 1445 emit changedContentSizeSignal(_contentHeight, _contentWidth); // expose resizeEvent |
1445 } | 1446 } |
1446 //qDebug("%s %d updateImageSize", __FILE__, __LINE__); | 1447 //qDebug("%s %d updateImageSize", __FILE__, __LINE__); |
1447 | 1448 |
1448 _resizing = false; | 1449 _resizing = false; |
1449 } | 1450 } |
1450 | 1451 |
1451 //showEvent and hideEvent are reimplemented here so that it appears to other classes that the | 1452 //showEvent and hideEvent are reimplemented here so that it appears to other classes that the |
1454 //this allows | 1455 //this allows |
1455 //TODO: Perhaps it would be better to have separate signals for show and hide instead of using | 1456 //TODO: Perhaps it would be better to have separate signals for show and hide instead of using |
1456 //the same signal as the one for a content size change | 1457 //the same signal as the one for a content size change |
1457 void TerminalView::showEvent(QShowEvent*) | 1458 void TerminalView::showEvent(QShowEvent*) |
1458 { | 1459 { |
1459 emit changedContentSizeSignal(_contentHeight,_contentWidth); | 1460 emit changedContentSizeSignal(_contentHeight,_contentWidth); |
1460 } | 1461 } |
1461 void TerminalView::hideEvent(QHideEvent*) | 1462 void TerminalView::hideEvent(QHideEvent*) |
1462 { | 1463 { |
1463 emit changedContentSizeSignal(_contentHeight,_contentWidth); | 1464 emit changedContentSizeSignal(_contentHeight,_contentWidth); |
1464 } | 1465 } |
1465 | 1466 |
1466 /* ------------------------------------------------------------------------- */ | 1467 /* ------------------------------------------------------------------------- */ |
1467 /* */ | 1468 /* */ |
1468 /* Scrollbar */ | 1469 /* Scrollbar */ |
1470 /* ------------------------------------------------------------------------- */ | 1471 /* ------------------------------------------------------------------------- */ |
1471 | 1472 |
1472 void TerminalView::scrollBarPositionChanged(int) | 1473 void TerminalView::scrollBarPositionChanged(int) |
1473 { | 1474 { |
1474 if ( !_screenWindow ) | 1475 if ( !_screenWindow ) |
1475 return; | 1476 return; |
1476 | 1477 |
1477 _screenWindow->scrollTo( _scrollBar->value() ); | 1478 _screenWindow->scrollTo( _scrollBar->value() ); |
1478 | 1479 |
1479 // if the thumb has been moved to the bottom of the _scrollBar then set | 1480 // if the thumb has been moved to the bottom of the _scrollBar then set |
1480 // the display to automatically track new output, | 1481 // the display to automatically track new output, |
1486 updateImage(); | 1487 updateImage(); |
1487 } | 1488 } |
1488 | 1489 |
1489 void TerminalView::setScroll(int cursor, int slines) | 1490 void TerminalView::setScroll(int cursor, int slines) |
1490 { | 1491 { |
1491 //qDebug("%s %d setScroll", __FILE__, __LINE__); | 1492 //qDebug("%s %d setScroll", __FILE__, __LINE__); |
1492 // update _scrollBar if the range or value has changed, | 1493 // update _scrollBar if the range or value has changed, |
1493 // otherwise return | 1494 // otherwise return |
1494 // | 1495 // |
1495 // setting the range or value of a _scrollBar will always trigger | 1496 // setting the range or value of a _scrollBar will always trigger |
1496 // a repaint, so it should be avoided if it is not necessary | 1497 // a repaint, so it should be avoided if it is not necessary |
1497 if ( _scrollBar->minimum() == 0 && | 1498 if ( _scrollBar->minimum() == 0 && |
1498 _scrollBar->maximum() == (slines - _lines) && | 1499 _scrollBar->maximum() == (slines - _lines) && |
1499 _scrollBar->value() == cursor ) | 1500 _scrollBar->value() == cursor ) |
1500 { | 1501 { |
1501 return; | 1502 return; |
1502 } | 1503 } |
1503 | 1504 |
1504 disconnect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int))); | 1505 disconnect(_scrollBar, SIGNAL(valueChanged(int)), this, SLOT(scrollBarPositionChanged(int))); |
1505 _scrollBar->setRange(0,slines - _lines); | 1506 _scrollBar->setRange(0,slines - _lines); |
1506 _scrollBar->setSingleStep(1); | 1507 _scrollBar->setSingleStep(1); |
1507 _scrollBar->setPageStep(_lines); | 1508 _scrollBar->setPageStep(_lines); |
1510 } | 1511 } |
1511 | 1512 |
1512 void TerminalView::setScrollBarPosition(ScrollBarPosition position) | 1513 void TerminalView::setScrollBarPosition(ScrollBarPosition position) |
1513 { | 1514 { |
1514 if (_scrollbarLocation == position) { | 1515 if (_scrollbarLocation == position) { |
1515 // return; | 1516 // return; |
1516 } | 1517 } |
1517 | 1518 |
1518 if ( position == NoScrollBar ) | 1519 if ( position == NoScrollBar ) |
1519 _scrollBar->hide(); | 1520 _scrollBar->hide(); |
1520 else | 1521 else |
1521 _scrollBar->show(); | 1522 _scrollBar->show(); |
1522 | 1523 |
1523 _topMargin = _leftMargin = 1; | 1524 _topMargin = _leftMargin = 1; |
1524 _scrollbarLocation = position; | 1525 _scrollbarLocation = position; |
1525 | 1526 |
1526 propagateSize(); | 1527 propagateSize(); |
1528 } | 1529 } |
1529 | 1530 |
1530 void TerminalView::mousePressEvent(QMouseEvent* ev) | 1531 void TerminalView::mousePressEvent(QMouseEvent* ev) |
1531 { | 1532 { |
1532 if ( _possibleTripleClick && (ev->button()==Qt::LeftButton) ) { | 1533 if ( _possibleTripleClick && (ev->button()==Qt::LeftButton) ) { |
1533 mouseTripleClickEvent(ev); | 1534 mouseTripleClickEvent(ev); |
1534 return; | 1535 return; |
1535 } | 1536 } |
1536 | 1537 |
1537 if ( !contentsRect().contains(ev->pos()) ) return; | 1538 if ( !contentsRect().contains(ev->pos()) ) return; |
1538 | 1539 |
1539 if ( !_screenWindow ) return; | 1540 if ( !_screenWindow ) return; |
1540 | 1541 |
1542 int charColumn; | 1543 int charColumn; |
1543 getCharacterPosition(ev->pos(),charLine,charColumn); | 1544 getCharacterPosition(ev->pos(),charLine,charColumn); |
1544 QPoint pos = QPoint(charColumn,charLine); | 1545 QPoint pos = QPoint(charColumn,charLine); |
1545 | 1546 |
1546 if ( ev->button() == Qt::LeftButton) | 1547 if ( ev->button() == Qt::LeftButton) |
1547 { | 1548 { |
1548 _lineSelectionMode = false; | 1549 _lineSelectionMode = false; |
1549 _wordSelectionMode = false; | 1550 _wordSelectionMode = false; |
1550 | 1551 |
1551 emit isBusySelecting(true); // Keep it steady... | 1552 emit isBusySelecting(true); // Keep it steady... |
1552 // Drag only when the Control key is hold | 1553 // Drag only when the Control key is hold |
1553 bool selected = false; | 1554 bool selected = false; |
1554 | 1555 |
1555 // The receiver of the testIsSelected() signal will adjust | 1556 // The receiver of the testIsSelected() signal will adjust |
1556 // 'selected' accordingly. | 1557 // 'selected' accordingly. |
1557 //emit testIsSelected(pos.x(), pos.y(), selected); | 1558 //emit testIsSelected(pos.x(), pos.y(), selected); |
1558 | 1559 |
1559 selected = _screenWindow->isSelected(pos.x(),pos.y()); | 1560 selected = _screenWindow->isSelected(pos.x(),pos.y()); |
1560 | 1561 |
1561 if ((!_ctrlDrag || ev->modifiers() & Qt::ControlModifier) && selected ) { | 1562 if ((!_ctrlDrag || ev->modifiers() & Qt::ControlModifier) && selected ) { |
1562 // The user clicked inside selected text | 1563 // The user clicked inside selected text |
1563 dragInfo.state = diPending; | 1564 dragInfo.state = diPending; |
1564 dragInfo.start = ev->pos(); | 1565 dragInfo.start = ev->pos(); |
1565 } | 1566 } |
1566 else { | 1567 else { |
1567 // No reason to ever start a drag event | 1568 // No reason to ever start a drag event |
1568 dragInfo.state = diNone; | 1569 dragInfo.state = diNone; |
1569 | 1570 |
1570 _preserveLineBreaks = !( ( ev->modifiers() & Qt::ControlModifier ) && !(ev->modifiers() & Qt::AltModifier) ); | 1571 _preserveLineBreaks = !( ( ev->modifiers() & Qt::ControlModifier ) && !(ev->modifiers() & Qt::AltModifier) ); |
1571 _columnSelectionMode = (ev->modifiers() & Qt::AltModifier) && (ev->modifiers() & Qt::ControlModifier); | 1572 _columnSelectionMode = (ev->modifiers() & Qt::AltModifier) && (ev->modifiers() & Qt::ControlModifier); |
1572 | 1573 |
1574 if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) | |
1575 { | |
1576 _screenWindow->clearSelection(); | |
1577 | |
1578 //emit clearSelectionSignal(); | |
1579 pos.ry() += _scrollBar->value(); | |
1580 _iPntSel = _pntSel = pos; | |
1581 _actSel = 1; // left mouse button pressed but nothing selected yet. | |
1582 | |
1583 } | |
1584 else | |
1585 { | |
1586 emit mouseSignal( 0, charColumn + 1, charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0); | |
1587 } | |
1588 } | |
1589 } | |
1590 else if ( ev->button() == Qt::MidButton ) | |
1591 { | |
1592 if ( _mouseMarks || (!_mouseMarks && (ev->modifiers() & Qt::ShiftModifier)) ) | |
1593 emitSelection(true,ev->modifiers() & Qt::ControlModifier); | |
1594 else | |
1595 emit mouseSignal( 1, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0); | |
1596 } | |
1597 else if ( ev->button() == Qt::RightButton ) | |
1598 { | |
1573 if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) | 1599 if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) |
1574 { | 1600 { |
1575 _screenWindow->clearSelection(); | 1601 emit configureRequest( this, |
1576 | 1602 ev->modifiers() & (Qt::ShiftModifier|Qt::ControlModifier), |
1577 //emit clearSelectionSignal(); | 1603 ev->pos() |
1578 pos.ry() += _scrollBar->value(); | 1604 ); |
1579 _iPntSel = _pntSel = pos; | 1605 } |
1580 _actSel = 1; // left mouse button pressed but nothing selected yet. | |
1581 | |
1582 } | |
1583 else | 1606 else |
1584 { | 1607 emit mouseSignal( 2, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0); |
1585 emit mouseSignal( 0, charColumn + 1, charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0); | 1608 } |
1586 } | |
1587 } | |
1588 } | |
1589 else if ( ev->button() == Qt::MidButton ) | |
1590 { | |
1591 if ( _mouseMarks || (!_mouseMarks && (ev->modifiers() & Qt::ShiftModifier)) ) | |
1592 emitSelection(true,ev->modifiers() & Qt::ControlModifier); | |
1593 else | |
1594 emit mouseSignal( 1, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0); | |
1595 } | |
1596 else if ( ev->button() == Qt::RightButton ) | |
1597 { | |
1598 if (_mouseMarks || (ev->modifiers() & Qt::ShiftModifier)) | |
1599 { | |
1600 emit configureRequest( this, | |
1601 ev->modifiers() & (Qt::ShiftModifier|Qt::ControlModifier), | |
1602 ev->pos() | |
1603 ); | |
1604 } | |
1605 else | |
1606 emit mouseSignal( 2, charColumn +1, charLine +1 +_scrollBar->value() -_scrollBar->maximum() , 0); | |
1607 } | |
1608 | 1609 |
1609 QWidget::mousePressEvent (ev); | 1610 QWidget::mousePressEvent (ev); |
1610 } | 1611 } |
1611 | 1612 |
1612 QList<QAction*> TerminalView::filterActions(const QPoint& position) | 1613 QList<QAction*> TerminalView::filterActions(const QPoint& position) |
1628 | 1629 |
1629 // handle filters | 1630 // handle filters |
1630 // change link hot-spot appearance on mouse-over | 1631 // change link hot-spot appearance on mouse-over |
1631 Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn); | 1632 Filter::HotSpot* spot = _filterChain->hotSpotAt(charLine,charColumn); |
1632 if ( spot && spot->type() == Filter::HotSpot::Link) | 1633 if ( spot && spot->type() == Filter::HotSpot::Link) |
1633 { | 1634 { |
1634 QRect previousHotspotArea = _mouseOverHotspotArea; | 1635 QRect previousHotspotArea = _mouseOverHotspotArea; |
1635 _mouseOverHotspotArea.setCoords( qMin(spot->startColumn() , spot->endColumn()) * _fontWidth, | 1636 _mouseOverHotspotArea.setCoords( qMin(spot->startColumn() , spot->endColumn()) * _fontWidth, |
1636 spot->startLine() * _fontHeight, | 1637 spot->startLine() * _fontHeight, |
1637 qMax(spot->startColumn() , spot->endColumn()) * _fontHeight, | 1638 qMax(spot->startColumn() , spot->endColumn()) * _fontHeight, |
1638 (spot->endLine()+1) * _fontHeight ); | 1639 (spot->endLine()+1) * _fontHeight ); |
1639 | 1640 |
1640 // display tooltips when mousing over links | 1641 // display tooltips when mousing over links |
1641 // TODO: Extend this to work with filter types other than links | 1642 // TODO: Extend this to work with filter types other than links |
1642 const QString& tooltip = spot->tooltip(); | 1643 const QString& tooltip = spot->tooltip(); |
1643 if ( !tooltip.isEmpty() ) | 1644 if ( !tooltip.isEmpty() ) |
1644 { | 1645 { |
1645 QToolTip::showText( mapToGlobal(ev->pos()) , tooltip , this , _mouseOverHotspotArea ); | 1646 QToolTip::showText( mapToGlobal(ev->pos()) , tooltip , this , _mouseOverHotspotArea ); |
1646 } | 1647 } |
1647 | 1648 |
1648 update( _mouseOverHotspotArea | previousHotspotArea ); | 1649 update( _mouseOverHotspotArea | previousHotspotArea ); |
1649 } | 1650 } |
1650 else if ( _mouseOverHotspotArea.isValid() ) | 1651 else if ( _mouseOverHotspotArea.isValid() ) |
1651 { | 1652 { |
1652 update( _mouseOverHotspotArea ); | 1653 update( _mouseOverHotspotArea ); |
1653 // set hotspot area to an invalid rectangle | 1654 // set hotspot area to an invalid rectangle |
1654 _mouseOverHotspotArea = QRect(); | 1655 _mouseOverHotspotArea = QRect(); |
1655 } | 1656 } |
1656 | 1657 |
1657 // for auto-hiding the cursor, we need mouseTracking | 1658 // for auto-hiding the cursor, we need mouseTracking |
1658 if (ev->buttons() == Qt::NoButton ) return; | 1659 if (ev->buttons() == Qt::NoButton ) return; |
1659 | 1660 |
1660 // if the terminal is interested in mouse movements | 1661 // if the terminal is interested in mouse movements |
1661 // then emit a mouse movement signal, unless the shift | 1662 // then emit a mouse movement signal, unless the shift |
1662 // key is being held down, which overrides this. | 1663 // key is being held down, which overrides this. |
1663 if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) | 1664 if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) |
1664 { | 1665 { |
1665 int button = 3; | 1666 int button = 3; |
1666 if (ev->buttons() & Qt::LeftButton) | 1667 if (ev->buttons() & Qt::LeftButton) |
1667 button = 0; | 1668 button = 0; |
1668 if (ev->buttons() & Qt::MidButton) | 1669 if (ev->buttons() & Qt::MidButton) |
1669 button = 1; | 1670 button = 1; |
1670 if (ev->buttons() & Qt::RightButton) | 1671 if (ev->buttons() & Qt::RightButton) |
1671 button = 2; | 1672 button = 2; |
1672 | 1673 |
1673 | 1674 |
1674 emit mouseSignal( button, | 1675 emit mouseSignal( button, |
1675 charColumn + 1, | 1676 charColumn + 1, |
1676 charLine + 1 +_scrollBar->value() -_scrollBar->maximum(), | 1677 charLine + 1 +_scrollBar->value() -_scrollBar->maximum(), |
1677 1 ); | 1678 1 ); |
1678 | 1679 |
1679 return; | 1680 return; |
1680 } | 1681 } |
1681 | 1682 |
1682 if (dragInfo.state == diPending) | 1683 if (dragInfo.state == diPending) |
1683 { | 1684 { |
1684 // we had a mouse down, but haven't confirmed a drag yet | 1685 // we had a mouse down, but haven't confirmed a drag yet |
1685 // if the mouse has moved sufficiently, we will confirm | 1686 // if the mouse has moved sufficiently, we will confirm |
1686 | 1687 |
1687 int distance = 10; //KGlobalSettings::dndEventDelay(); | 1688 int distance = 10; //KGlobalSettings::dndEventDelay(); |
1688 if ( ev->x() > dragInfo.start.x() + distance || ev->x() < dragInfo.start.x() - distance || | 1689 if ( ev->x() > dragInfo.start.x() + distance || ev->x() < dragInfo.start.x() - distance || |
1689 ev->y() > dragInfo.start.y() + distance || ev->y() < dragInfo.start.y() - distance) | 1690 ev->y() > dragInfo.start.y() + distance || ev->y() < dragInfo.start.y() - distance) |
1690 { | 1691 { |
1691 // we've left the drag square, we can start a real drag operation now | 1692 // we've left the drag square, we can start a real drag operation now |
1692 emit isBusySelecting(false); // Ok.. we can breath again. | 1693 emit isBusySelecting(false); // Ok.. we can breath again. |
1693 | 1694 |
1694 _screenWindow->clearSelection(); | 1695 _screenWindow->clearSelection(); |
1695 doDrag(); | 1696 doDrag(); |
1696 } | 1697 } |
1697 return; | 1698 return; |
1698 } | 1699 } |
1699 else if (dragInfo.state == diDragging) | 1700 else if (dragInfo.state == diDragging) |
1700 { | 1701 { |
1701 // this isn't technically needed because mouseMoveEvent is suppressed during | 1702 // this isn't technically needed because mouseMoveEvent is suppressed during |
1702 // Qt drag operations, replaced by dragMoveEvent | 1703 // Qt drag operations, replaced by dragMoveEvent |
1703 return; | 1704 return; |
1704 } | 1705 } |
1705 | 1706 |
1706 if (_actSel == 0) return; | 1707 if (_actSel == 0) return; |
1707 | 1708 |
1708 // don't extend selection while pasting | 1709 // don't extend selection while pasting |
1709 if (ev->buttons() & Qt::MidButton) return; | 1710 if (ev->buttons() & Qt::MidButton) return; |
1710 | 1711 |
1711 extendSelection( ev->pos() ); | 1712 extendSelection( ev->pos() ); |
1712 } | 1713 } |
1713 | 1714 |
1721 void TerminalView::extendSelection(const QPoint& position) { | 1722 void TerminalView::extendSelection(const QPoint& position) { |
1722 QPoint pos = position; | 1723 QPoint pos = position; |
1723 | 1724 |
1724 if (!_screenWindow) { | 1725 if (!_screenWindow) { |
1725 return; | 1726 return; |
1726 } | 1727 } |
1727 | 1728 |
1728 QPoint tL = contentsRect().topLeft(); | 1729 QPoint tL = contentsRect().topLeft(); |
1729 int tLx = tL.x(); | 1730 int tLx = tL.x(); |
1730 int tLy = tL.y(); | 1731 int tLy = tL.y(); |
1731 int scroll = _scrollBar->value(); | 1732 int scroll = _scrollBar->value(); |
1735 // this widget. | 1736 // this widget. |
1736 | 1737 |
1737 // Adjust position within text area bounds. See FIXME above. | 1738 // Adjust position within text area bounds. See FIXME above. |
1738 if (pos.x() < tLx + _leftMargin) { | 1739 if (pos.x() < tLx + _leftMargin) { |
1739 pos.setX(tLx + _leftMargin); | 1740 pos.setX(tLx + _leftMargin); |
1740 } | 1741 } |
1741 if (pos.x() > tLx + _leftMargin + _usedColumns * _fontWidth - 1) { | 1742 if (pos.x() > tLx + _leftMargin + _usedColumns * _fontWidth - 1) { |
1742 pos.setX(tLx + _leftMargin + _usedColumns * _fontWidth); | 1743 pos.setX(tLx + _leftMargin + _usedColumns * _fontWidth); |
1743 } | 1744 } |
1744 if (pos.y() < tLy + _topMargin) { | 1745 if (pos.y() < tLy + _topMargin) { |
1745 pos.setY(tLy + _topMargin); | 1746 pos.setY(tLy + _topMargin); |
1746 } | 1747 } |
1747 if (pos.y() > tLy + _topMargin + _usedLines * _fontHeight - 1) { | 1748 if (pos.y() > tLy + _topMargin + _usedLines * _fontHeight - 1) { |
1748 pos.setY(tLy + _topMargin + _usedLines * _fontHeight - 1); | 1749 pos.setY(tLy + _topMargin + _usedLines * _fontHeight - 1); |
1749 } | 1750 } |
1750 | 1751 |
1751 if (pos.y() == tLy + _topMargin + _usedLines * _fontHeight - 1) { | 1752 if (pos.y() == tLy + _topMargin + _usedLines * _fontHeight - 1) { |
1752 _scrollBar->setValue(_scrollBar->value() + yMouseScroll); // scrollforward | 1753 _scrollBar->setValue(_scrollBar->value() + yMouseScroll); // scrollforward |
1753 } | 1754 } |
1754 if (pos.y() == tLy + _topMargin) { | 1755 if (pos.y() == tLy + _topMargin) { |
1755 _scrollBar->setValue(_scrollBar->value() - yMouseScroll); // scrollback | 1756 _scrollBar->setValue(_scrollBar->value() - yMouseScroll); // scrollback |
1756 } | 1757 } |
1757 | 1758 |
1758 int charColumn = 0; | 1759 int charColumn = 0; |
1759 int charLine = 0; | 1760 int charLine = 0; |
1760 getCharacterPosition(pos, charLine, charColumn); | 1761 getCharacterPosition(pos, charLine, charColumn); |
1761 | 1762 |
1766 QPoint _pntSelCorr = _pntSel; | 1767 QPoint _pntSelCorr = _pntSel; |
1767 _pntSelCorr.ry() -= _scrollBar->value(); | 1768 _pntSelCorr.ry() -= _scrollBar->value(); |
1768 bool swapping = false; | 1769 bool swapping = false; |
1769 | 1770 |
1770 if (_wordSelectionMode) { | 1771 if (_wordSelectionMode) { |
1771 // Extend to word boundaries | 1772 // Extend to word boundaries |
1772 int i = 0; | 1773 int i = 0; |
1773 int selClass = 0; | 1774 int selClass = 0; |
1774 | 1775 |
1775 bool left_not_right = (here.y() < _iPntSelCorr.y() || | 1776 bool left_not_right = (here.y() < _iPntSelCorr.y() || |
1776 (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x())); | 1777 (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x())); |
1777 bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() || | 1778 bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() || |
1778 (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x())); | 1779 (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x())); |
1779 swapping = left_not_right != old_left_not_right; | 1780 swapping = left_not_right != old_left_not_right; |
1780 | 1781 |
1781 // Find left (left_not_right ? from here : from start) | 1782 // Find left (left_not_right ? from here : from start) |
1782 QPoint left = left_not_right ? here : _iPntSelCorr; | 1783 QPoint left = left_not_right ? here : _iPntSelCorr; |
1783 i = loc(left.x(), left.y()); | 1784 i = loc(left.x(), left.y()); |
1784 if (i >= 0 && i <= _imageSize) { | 1785 if (i >= 0 && i <= _imageSize) { |
1785 selClass = charClass(_image[i].character); | 1786 selClass = charClass(_image[i].character); |
1786 while (((left.x() > 0) || (left.y() > 0 && (_lineProperties[left.y() - 1] & LINE_WRAPPED))) | 1787 while (((left.x() > 0) || (left.y() > 0 && (_lineProperties[left.y() - 1] & LINE_WRAPPED))) |
1787 && charClass(_image[i - 1].character) == selClass) { | 1788 && charClass(_image[i - 1].character) == selClass) { |
1788 i--; | 1789 i--; |
1789 if (left.x() > 0) { | 1790 if (left.x() > 0) { |
1790 left.rx()--; | 1791 left.rx()--; |
1791 } else { | 1792 } else { |
1792 left.rx() = _usedColumns - 1; | 1793 left.rx() = _usedColumns - 1; |
1793 left.ry()--; | 1794 left.ry()--; |
1794 } | 1795 } |
1795 } | 1796 } |
1796 } | 1797 } |
1797 | 1798 |
1798 // Find left (left_not_right ? from start : from here) | 1799 // Find left (left_not_right ? from start : from here) |
1799 QPoint right = left_not_right ? _iPntSelCorr : here; | 1800 QPoint right = left_not_right ? _iPntSelCorr : here; |
1800 i = loc(right.x(), right.y()); | 1801 i = loc(right.x(), right.y()); |
1801 if (i >= 0 && i <= _imageSize) { | 1802 if (i >= 0 && i <= _imageSize) { |
1802 selClass = charClass(_image[i].character); | 1803 selClass = charClass(_image[i].character); |
1803 while (((right.x() < _usedColumns - 1) || (right.y() < _usedLines - 1 && (_lineProperties[right.y()] & LINE_WRAPPED))) | 1804 while (((right.x() < _usedColumns - 1) || (right.y() < _usedLines - 1 && (_lineProperties[right.y()] & LINE_WRAPPED))) |
1804 && charClass(_image[i + 1].character) == selClass) { | 1805 && charClass(_image[i + 1].character) == selClass) { |
1805 i++; | 1806 i++; |
1806 if (right.x() < _usedColumns - 1) { | 1807 if (right.x() < _usedColumns - 1) { |
1807 right.rx()++; | 1808 right.rx()++; |
1808 } else { | 1809 } else { |
1809 right.rx() = 0; | 1810 right.rx() = 0; |
1810 right.ry()++; | 1811 right.ry()++; |
1811 } | 1812 } |
1812 } | 1813 } |
1813 } | 1814 } |
1814 | 1815 |
1815 // Pick which is start (ohere) and which is extension (here) | 1816 // Pick which is start (ohere) and which is extension (here) |
1816 if (left_not_right) { | 1817 if (left_not_right) { |
1817 here = left; | 1818 here = left; |
1818 ohere = right; | 1819 ohere = right; |
1819 } else { | 1820 } else { |
1820 here = right; | 1821 here = right; |
1821 ohere = left; | 1822 ohere = left; |
1822 } | 1823 } |
1823 ohere.rx()++; | 1824 ohere.rx()++; |
1824 } | 1825 } |
1825 | 1826 |
1826 if (_lineSelectionMode) { | 1827 if (_lineSelectionMode) { |
1827 // Extend to complete line | 1828 // Extend to complete line |
1828 bool above_not_below = (here.y() < _iPntSelCorr.y()); | 1829 bool above_not_below = (here.y() < _iPntSelCorr.y()); |
1829 | 1830 |
1830 QPoint above = above_not_below ? here : _iPntSelCorr; | 1831 QPoint above = above_not_below ? here : _iPntSelCorr; |
1831 QPoint below = above_not_below ? _iPntSelCorr : here; | 1832 QPoint below = above_not_below ? _iPntSelCorr : here; |
1832 | 1833 |
1833 while (above.y() > 0 && (_lineProperties[above.y() - 1] & LINE_WRAPPED)) { | 1834 while (above.y() > 0 && (_lineProperties[above.y() - 1] & LINE_WRAPPED)) { |
1834 above.ry()--; | 1835 above.ry()--; |
1835 } | 1836 } |
1836 while (below.y() < _usedLines - 1 && (_lineProperties[below.y()] & LINE_WRAPPED)) { | 1837 while (below.y() < _usedLines - 1 && (_lineProperties[below.y()] & LINE_WRAPPED)) { |
1837 below.ry()++; | 1838 below.ry()++; |
1838 } | 1839 } |
1839 | 1840 |
1840 above.setX(0); | 1841 above.setX(0); |
1841 below.setX(_usedColumns - 1); | 1842 below.setX(_usedColumns - 1); |
1842 | 1843 |
1843 // Pick which is start (ohere) and which is extension (here) | 1844 // Pick which is start (ohere) and which is extension (here) |
1844 if (above_not_below) { | 1845 if (above_not_below) { |
1845 here = above; | 1846 here = above; |
1846 ohere = below; | 1847 ohere = below; |
1847 } else { | 1848 } else { |
1848 here = below; | 1849 here = below; |
1849 ohere = above; | 1850 ohere = above; |
1850 } | 1851 } |
1851 | 1852 |
1852 QPoint newSelBegin = QPoint(ohere.x(), ohere.y()); | 1853 QPoint newSelBegin = QPoint(ohere.x(), ohere.y()); |
1853 swapping = !(_tripleSelBegin == newSelBegin); | 1854 swapping = !(_tripleSelBegin == newSelBegin); |
1854 _tripleSelBegin = newSelBegin; | 1855 _tripleSelBegin = newSelBegin; |
1855 | 1856 |
1856 ohere.rx()++; | 1857 ohere.rx()++; |
1857 } | 1858 } |
1858 | 1859 |
1859 int offset = 0; | 1860 int offset = 0; |
1860 if (!_wordSelectionMode && !_lineSelectionMode) { | 1861 if (!_wordSelectionMode && !_lineSelectionMode) { |
1861 int i = 0; | 1862 int i = 0; |
1862 int selClass = 0; | 1863 int selClass = 0; |
1863 | 1864 |
1864 bool left_not_right = (here.y() < _iPntSelCorr.y() || | 1865 bool left_not_right = (here.y() < _iPntSelCorr.y() || |
1865 (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x())); | 1866 (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x())); |
1866 bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() || | 1867 bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() || |
1867 (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x())); | 1868 (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x())); |
1868 swapping = left_not_right != old_left_not_right; | 1869 swapping = left_not_right != old_left_not_right; |
1869 | 1870 |
1870 // Find left (left_not_right ? from here : from start) | 1871 // Find left (left_not_right ? from here : from start) |
1871 QPoint left = left_not_right ? here : _iPntSelCorr; | 1872 QPoint left = left_not_right ? here : _iPntSelCorr; |
1872 | 1873 |
1873 // Find left (left_not_right ? from start : from here) | 1874 // Find left (left_not_right ? from start : from here) |
1874 QPoint right = left_not_right ? _iPntSelCorr : here; | 1875 QPoint right = left_not_right ? _iPntSelCorr : here; |
1875 if (right.x() > 0 && !_columnSelectionMode) { | 1876 if (right.x() > 0 && !_columnSelectionMode) { |
1876 i = loc(right.x(), right.y()); | 1877 i = loc(right.x(), right.y()); |
1877 if (i >= 0 && i <= _imageSize) { | 1878 if (i >= 0 && i <= _imageSize) { |
1878 selClass = charClass(_image[i - 1].character); | 1879 selClass = charClass(_image[i - 1].character); |
1879 if (selClass == ' ') { | 1880 if (selClass == ' ') { |
1880 while (right.x() < _usedColumns - 1 && charClass(_image[i + 1].character) == selClass && (right.y() < _usedLines - 1) && | 1881 while (right.x() < _usedColumns - 1 && charClass(_image[i + 1].character) == selClass && (right.y() < _usedLines - 1) && |
1881 !(_lineProperties[right.y()] & LINE_WRAPPED)) { | 1882 !(_lineProperties[right.y()] & LINE_WRAPPED)) { |
1882 i++; | 1883 i++; |
1883 right.rx()++; | 1884 right.rx()++; |
1884 } | 1885 } |
1885 if (right.x() < _usedColumns - 1) { | 1886 if (right.x() < _usedColumns - 1) { |
1886 right = left_not_right ? _iPntSelCorr : here; | 1887 right = left_not_right ? _iPntSelCorr : here; |
1887 } else { | 1888 } else { |
1888 right.rx()++; // will be balanced later because of offset=-1; | 1889 right.rx()++; // will be balanced later because of offset=-1; |
1889 } | 1890 } |
1890 } | 1891 } |
1891 } | 1892 } |
1892 } | 1893 } |
1893 | 1894 |
1894 // Pick which is start (ohere) and which is extension (here) | 1895 // Pick which is start (ohere) and which is extension (here) |
1895 if (left_not_right) { | 1896 if (left_not_right) { |
1896 here = left; | 1897 here = left; |
1897 ohere = right; | 1898 ohere = right; |
1898 offset = 0; | 1899 offset = 0; |
1899 } else { | 1900 } else { |
1900 here = right; | 1901 here = right; |
1901 ohere = left; | 1902 ohere = left; |
1902 offset = -1; | 1903 offset = -1; |
1903 } | 1904 } |
1904 } | 1905 } |
1905 | 1906 |
1906 if ((here == _pntSelCorr) && (scroll == _scrollBar->value())) { | 1907 if ((here == _pntSelCorr) && (scroll == _scrollBar->value())) { |
1907 return; // not moved | 1908 return; // not moved |
1908 } | 1909 } |
1909 | 1910 |
1910 if (here == ohere) { | 1911 if (here == ohere) { |
1911 return; // It's not left, it's not right. | 1912 return; // It's not left, it's not right. |
1912 } | 1913 } |
1913 | 1914 |
1914 if (_actSel < 2 || swapping) { | 1915 if (_actSel < 2 || swapping) { |
1915 if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) { | 1916 if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) { |
1916 _screenWindow->setSelectionStart(ohere.x(), ohere.y(), true); | 1917 _screenWindow->setSelectionStart(ohere.x(), ohere.y(), true); |
1917 } else { | 1918 } else { |
1918 _screenWindow->setSelectionStart(ohere.x() - 1 - offset , ohere.y(), false); | 1919 _screenWindow->setSelectionStart(ohere.x() - 1 - offset , ohere.y(), false); |
1919 } | 1920 } |
1920 | 1921 |
1921 } | 1922 } |
1922 | 1923 |
1923 _actSel = 2; // within selection | 1924 _actSel = 2; // within selection |
1924 _pntSel = here; | 1925 _pntSel = here; |
1925 _pntSel.ry() += _scrollBar->value(); | 1926 _pntSel.ry() += _scrollBar->value(); |
1926 | 1927 |
1927 if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) { | 1928 if (_columnSelectionMode && !_lineSelectionMode && !_wordSelectionMode) { |
1928 _screenWindow->setSelectionEnd(here.x(), here.y()); | 1929 _screenWindow->setSelectionEnd(here.x(), here.y()); |
1929 } else { | 1930 } else { |
1930 _screenWindow->setSelectionEnd(here.x() + offset, here.y()); | 1931 _screenWindow->setSelectionEnd(here.x() + offset, here.y()); |
1931 } | 1932 } |
1932 } | 1933 } |
1933 | 1934 |
1934 void TerminalView::mouseReleaseEvent(QMouseEvent* ev) | 1935 void TerminalView::mouseReleaseEvent(QMouseEvent* ev) |
1935 { | 1936 { |
1936 if ( !_screenWindow ) | 1937 if ( !_screenWindow ) |
1937 return; | 1938 return; |
1938 | 1939 |
1939 int charLine; | 1940 int charLine; |
1940 int charColumn; | 1941 int charColumn; |
1941 getCharacterPosition(ev->pos(),charLine,charColumn); | 1942 getCharacterPosition(ev->pos(),charLine,charColumn); |
1942 | 1943 |
1943 if ( ev->button() == Qt::LeftButton) | 1944 if ( ev->button() == Qt::LeftButton) |
1944 { | 1945 { |
1945 emit isBusySelecting(false); | 1946 emit isBusySelecting(false); |
1946 if(dragInfo.state == diPending) | 1947 if(dragInfo.state == diPending) |
1947 { | 1948 { |
1948 // We had a drag event pending but never confirmed. Kill selection | 1949 // We had a drag event pending but never confirmed. Kill selection |
1949 _screenWindow->clearSelection(); | 1950 _screenWindow->clearSelection(); |
1950 //emit clearSelectionSignal(); | 1951 //emit clearSelectionSignal(); |
1951 } | 1952 } |
1952 else | 1953 else |
1953 { | 1954 { |
1954 if ( _actSel > 1 ) | 1955 if ( _actSel > 1 ) |
1955 { | 1956 { |
1956 setSelection( _screenWindow->selectedText(_preserveLineBreaks) ); | 1957 setSelection( _screenWindow->selectedText(_preserveLineBreaks) ); |
1957 } | 1958 } |
1958 | 1959 |
1959 _actSel = 0; | 1960 _actSel = 0; |
1960 | 1961 |
1961 //FIXME: emits a release event even if the mouse is | 1962 //FIXME: emits a release event even if the mouse is |
1962 // outside the range. The procedure used in `mouseMoveEvent' | 1963 // outside the range. The procedure used in `mouseMoveEvent' |
1963 // applies here, too. | 1964 // applies here, too. |
1964 | 1965 |
1965 if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) | 1966 if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) |
1966 emit mouseSignal( 3, // release | 1967 emit mouseSignal( 3, // release |
1967 charColumn + 1, | 1968 charColumn + 1, |
1968 charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0); | 1969 charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , 0); |
1969 } | 1970 } |
1970 dragInfo.state = diNone; | 1971 dragInfo.state = diNone; |
1971 } | 1972 } |
1972 | 1973 |
1973 | 1974 |
1974 if ( !_mouseMarks && | 1975 if ( !_mouseMarks && |
1975 ((ev->button() == Qt::RightButton && !(ev->modifiers() & Qt::ShiftModifier)) | 1976 ((ev->button() == Qt::RightButton && !(ev->modifiers() & Qt::ShiftModifier)) |
1976 || ev->button() == Qt::MidButton) ) | 1977 || ev->button() == Qt::MidButton) ) |
1977 { | 1978 { |
1978 emit mouseSignal( 3, | 1979 emit mouseSignal( 3, |
1979 charColumn + 1, | 1980 charColumn + 1, |
1980 charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , | 1981 charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , |
1981 0); | 1982 0); |
1982 } | 1983 } |
1983 | 1984 |
1984 QWidget::mouseReleaseEvent(ev); | 1985 QWidget::mouseReleaseEvent(ev); |
1985 } | 1986 } |
1986 | 1987 |
1987 void TerminalView::getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const | 1988 void TerminalView::getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const |
1988 { | 1989 { |
1989 | 1990 |
1990 column = (widgetPoint.x() + _fontWidth/2 -contentsRect().left()-_leftMargin) / _fontWidth; | 1991 column = (widgetPoint.x() + _fontWidth/2 -contentsRect().left()-_leftMargin) / _fontWidth; |
1991 line = (widgetPoint.y()-contentsRect().top()-_topMargin) / _fontHeight; | 1992 line = (widgetPoint.y()-contentsRect().top()-_topMargin) / _fontHeight; |
1992 | 1993 |
1993 if ( line < 0 ) | 1994 if ( line < 0 ) |
1994 line = 0; | 1995 line = 0; |
1995 if ( column < 0 ) | 1996 if ( column < 0 ) |
1996 column = 0; | 1997 column = 0; |
1997 | 1998 |
1998 if ( line >= _usedLines ) | 1999 if ( line >= _usedLines ) |
1999 line = _usedLines-1; | 2000 line = _usedLines-1; |
2000 | 2001 |
2001 // the column value returned can be equal to _usedColumns, which | 2002 // the column value returned can be equal to _usedColumns, which |
2002 // is the position just after the last character displayed in a line. | 2003 // is the position just after the last character displayed in a line. |
2003 // | 2004 // |
2004 // this is required so that the user can select characters in the right-most | 2005 // this is required so that the user can select characters in the right-most |
2005 // column (or left-most for right-to-left input) | 2006 // column (or left-most for right-to-left input) |
2006 if ( column > _usedColumns ) | 2007 if ( column > _usedColumns ) |
2007 column = _usedColumns; | 2008 column = _usedColumns; |
2008 } | 2009 } |
2009 | 2010 |
2010 void TerminalView::updateLineProperties() | 2011 void TerminalView::updateLineProperties() |
2011 { | 2012 { |
2012 if ( !_screenWindow ) | 2013 if ( !_screenWindow ) |
2013 return; | 2014 return; |
2014 | 2015 |
2015 _lineProperties = _screenWindow->getLineProperties(); | 2016 _lineProperties = _screenWindow->getLineProperties(); |
2016 } | 2017 } |
2017 | 2018 |
2018 void TerminalView::mouseDoubleClickEvent(QMouseEvent* ev) | 2019 void TerminalView::mouseDoubleClickEvent(QMouseEvent* ev) |
2019 { | 2020 { |
2020 if ( ev->button() != Qt::LeftButton) return; | 2021 if ( ev->button() != Qt::LeftButton) return; |
2027 | 2028 |
2028 QPoint pos(charColumn,charLine); | 2029 QPoint pos(charColumn,charLine); |
2029 | 2030 |
2030 // pass on double click as two clicks. | 2031 // pass on double click as two clicks. |
2031 if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) | 2032 if (!_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier)) |
2032 { | 2033 { |
2033 // Send just _ONE_ click event, since the first click of the double click | 2034 // Send just _ONE_ click event, since the first click of the double click |
2034 // was already sent by the click handler | 2035 // was already sent by the click handler |
2035 emit mouseSignal( 0, | 2036 emit mouseSignal( 0, |
2036 pos.x()+1, | 2037 pos.x()+1, |
2037 pos.y()+1 +_scrollBar->value() -_scrollBar->maximum(), | 2038 pos.y()+1 +_scrollBar->value() -_scrollBar->maximum(), |
2038 0 ); // left button | 2039 0 ); // left button |
2039 return; | 2040 return; |
2040 } | 2041 } |
2041 | 2042 |
2042 _screenWindow->clearSelection(); | 2043 _screenWindow->clearSelection(); |
2043 QPoint bgnSel = pos; | 2044 QPoint bgnSel = pos; |
2044 QPoint endSel = pos; | 2045 QPoint endSel = pos; |
2045 int i = loc(bgnSel.x(),bgnSel.y()); | 2046 int i = loc(bgnSel.x(),bgnSel.y()); |
2049 _wordSelectionMode = true; | 2050 _wordSelectionMode = true; |
2050 | 2051 |
2051 // find word boundaries... | 2052 // find word boundaries... |
2052 int selClass = charClass(_image[i].character); | 2053 int selClass = charClass(_image[i].character); |
2053 { | 2054 { |
2054 // find the start of the word | 2055 // find the start of the word |
2055 int x = bgnSel.x(); | 2056 int x = bgnSel.x(); |
2056 while ( ((x>0) || (bgnSel.y()>0 && (_lineProperties[bgnSel.y()-1] & LINE_WRAPPED) )) | 2057 while ( ((x>0) || (bgnSel.y()>0 && (_lineProperties[bgnSel.y()-1] & LINE_WRAPPED) )) |
2057 && charClass(_image[i-1].character) == selClass ) | 2058 && charClass(_image[i-1].character) == selClass ) |
2058 { | 2059 { |
2059 i--; | 2060 i--; |
2060 if (x>0) | 2061 if (x>0) |
2061 x--; | 2062 x--; |
2062 else | 2063 else |
2063 { | 2064 { |
2064 x=_usedColumns-1; | 2065 x=_usedColumns-1; |
2065 bgnSel.ry()--; | 2066 bgnSel.ry()--; |
2066 } | 2067 } |
2067 } | 2068 } |
2068 | 2069 |
2069 bgnSel.setX(x); | 2070 bgnSel.setX(x); |
2070 _screenWindow->setSelectionStart( bgnSel.x() , bgnSel.y() , false ); | 2071 _screenWindow->setSelectionStart( bgnSel.x() , bgnSel.y() , false ); |
2071 | 2072 |
2072 // find the end of the word | 2073 // find the end of the word |
2073 i = loc( endSel.x(), endSel.y() ); | 2074 i = loc( endSel.x(), endSel.y() ); |
2074 x = endSel.x(); | 2075 x = endSel.x(); |
2075 while( ((x<_usedColumns-1) || (endSel.y()<_usedLines-1 && (_lineProperties[endSel.y()] & LINE_WRAPPED) )) | 2076 while( ((x<_usedColumns-1) || (endSel.y()<_usedLines-1 && (_lineProperties[endSel.y()] & LINE_WRAPPED) )) |
2076 && charClass(_image[i+1].character) == selClass ) | 2077 && charClass(_image[i+1].character) == selClass ) |
2077 { | 2078 { |
2078 i++; | 2079 i++; |
2079 if (x<_usedColumns-1) | 2080 if (x<_usedColumns-1) |
2080 x++; | 2081 x++; |
2081 else | 2082 else |
2082 { | 2083 { |
2083 x=0; | 2084 x=0; |
2084 endSel.ry()++; | 2085 endSel.ry()++; |
2085 } | 2086 } |
2086 } | 2087 } |
2087 | 2088 |
2088 endSel.setX(x); | 2089 endSel.setX(x); |
2089 | 2090 |
2090 // In word selection mode don't select @ (64) if at end of word. | 2091 // In word selection mode don't select @ (64) if at end of word. |
2091 if ( ( QChar( _image[i].character ) == '@' ) && ( ( endSel.x() - bgnSel.x() ) > 0 ) ) | 2092 if ( ( QChar( _image[i].character ) == '@' ) && ( ( endSel.x() - bgnSel.x() ) > 0 ) ) |
2092 endSel.setX( x - 1 ); | 2093 endSel.setX( x - 1 ); |
2093 | 2094 |
2094 | 2095 |
2095 _actSel = 2; // within selection | 2096 _actSel = 2; // within selection |
2096 | 2097 |
2097 _screenWindow->setSelectionEnd( endSel.x() , endSel.y() ); | 2098 _screenWindow->setSelectionEnd( endSel.x() , endSel.y() ); |
2098 | 2099 |
2099 setSelection( _screenWindow->selectedText(_preserveLineBreaks) ); | 2100 setSelection( _screenWindow->selectedText(_preserveLineBreaks) ); |
2100 } | 2101 } |
2101 | 2102 |
2102 _possibleTripleClick=true; | 2103 _possibleTripleClick=true; |
2103 | 2104 |
2104 QTimer::singleShot(QApplication::doubleClickInterval(),this, | 2105 QTimer::singleShot(QApplication::doubleClickInterval(),this, |
2105 SLOT(tripleClickTimeout())); | 2106 SLOT(tripleClickTimeout())); |
2111 return; | 2112 return; |
2112 | 2113 |
2113 if ( _mouseMarks ) | 2114 if ( _mouseMarks ) |
2114 _scrollBar->event(ev); | 2115 _scrollBar->event(ev); |
2115 else | 2116 else |
2116 { | 2117 { |
2117 int charLine; | 2118 int charLine; |
2118 int charColumn; | 2119 int charColumn; |
2119 getCharacterPosition( ev->pos() , charLine , charColumn ); | 2120 getCharacterPosition( ev->pos() , charLine , charColumn ); |
2120 | 2121 |
2121 emit mouseSignal( ev->delta() > 0 ? 4 : 5, | 2122 emit mouseSignal( ev->delta() > 0 ? 4 : 5, |
2122 charColumn + 1, | 2123 charColumn + 1, |
2123 charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , | 2124 charLine + 1 +_scrollBar->value() -_scrollBar->maximum() , |
2124 0); | 2125 0); |
2125 } | 2126 } |
2126 } | 2127 } |
2127 | 2128 |
2128 void TerminalView::tripleClickTimeout() | 2129 void TerminalView::tripleClickTimeout() |
2129 { | 2130 { |
2130 _possibleTripleClick=false; | 2131 _possibleTripleClick=false; |
2149 | 2150 |
2150 while (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) ) | 2151 while (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) ) |
2151 _iPntSel.ry()--; | 2152 _iPntSel.ry()--; |
2152 | 2153 |
2153 if (_tripleClickMode == SelectForwardsFromCursor) { | 2154 if (_tripleClickMode == SelectForwardsFromCursor) { |
2154 // find word boundary start | 2155 // find word boundary start |
2155 int i = loc(_iPntSel.x(),_iPntSel.y()); | 2156 int i = loc(_iPntSel.x(),_iPntSel.y()); |
2156 int selClass = charClass(_image[i].character); | 2157 int selClass = charClass(_image[i].character); |
2157 int x = _iPntSel.x(); | 2158 int x = _iPntSel.x(); |
2158 | 2159 |
2159 while ( ((x>0) || | 2160 while ( ((x>0) || |
2160 (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) ) | 2161 (_iPntSel.y()>0 && (_lineProperties[_iPntSel.y()-1] & LINE_WRAPPED) ) |
2161 ) | 2162 ) |
2162 && charClass(_image[i-1].character) == selClass ) | 2163 && charClass(_image[i-1].character) == selClass ) |
2163 { | 2164 { |
2164 i--; | 2165 i--; |
2165 if (x>0) | 2166 if (x>0) |
2166 x--; | 2167 x--; |
2167 else | 2168 else |
2168 { | 2169 { |
2169 x=_columns-1; | 2170 x=_columns-1; |
2170 _iPntSel.ry()--; | 2171 _iPntSel.ry()--; |
2171 } | 2172 } |
2172 } | 2173 } |
2173 | 2174 |
2174 _screenWindow->setSelectionStart( x , _iPntSel.y() , false ); | 2175 _screenWindow->setSelectionStart( x , _iPntSel.y() , false ); |
2175 _tripleSelBegin = QPoint( x, _iPntSel.y() ); | 2176 _tripleSelBegin = QPoint( x, _iPntSel.y() ); |
2176 } | 2177 } |
2177 else if (_tripleClickMode == SelectWholeLine) { | 2178 else if (_tripleClickMode == SelectWholeLine) { |
2178 _screenWindow->setSelectionStart( 0 , _iPntSel.y() , false ); | 2179 _screenWindow->setSelectionStart( 0 , _iPntSel.y() , false ); |
2179 _tripleSelBegin = QPoint( 0, _iPntSel.y() ); | 2180 _tripleSelBegin = QPoint( 0, _iPntSel.y() ); |
2180 } | 2181 } |
2181 | 2182 |
2182 while (_iPntSel.y()<_lines-1 && (_lineProperties[_iPntSel.y()] & LINE_WRAPPED) ) | 2183 while (_iPntSel.y()<_lines-1 && (_lineProperties[_iPntSel.y()] & LINE_WRAPPED) ) |
2183 _iPntSel.ry()++; | 2184 _iPntSel.ry()++; |
2184 | 2185 |
2185 _screenWindow->setSelectionEnd( _columns - 1 , _iPntSel.y() ); | 2186 _screenWindow->setSelectionEnd( _columns - 1 , _iPntSel.y() ); |
2194 | 2195 |
2195 bool TerminalView::focusNextPrevChild( bool next ) | 2196 bool TerminalView::focusNextPrevChild( bool next ) |
2196 { | 2197 { |
2197 if (next) | 2198 if (next) |
2198 return false; // This disables changing the active part in konqueror | 2199 return false; // This disables changing the active part in konqueror |
2199 // when pressing Tab | 2200 // when pressing Tab |
2200 return QWidget::focusNextPrevChild( next ); | 2201 return QWidget::focusNextPrevChild( next ); |
2201 } | 2202 } |
2202 | 2203 |
2203 | 2204 |
2204 int TerminalView::charClass(quint16 ch) const | 2205 int TerminalView::charClass(quint16 ch) const |
2205 { | 2206 { |
2206 QChar qch=QChar(ch); | 2207 QChar qch=QChar(ch); |
2207 if ( qch.isSpace() ) return ' '; | 2208 if ( qch.isSpace() ) return ' '; |
2208 | 2209 |
2209 if ( qch.isLetterOrNumber() || _wordCharacters.contains(qch, Qt::CaseInsensitive ) ) | 2210 if ( qch.isLetterOrNumber() || _wordCharacters.contains(qch, Qt::CaseInsensitive ) ) |
2210 return 'a'; | 2211 return 'a'; |
2211 | 2212 |
2212 // Everything else is weird | 2213 // Everything else is weird |
2213 return 1; | 2214 return 1; |
2214 } | 2215 } |
2215 | 2216 |
2216 void TerminalView::setWordCharacters(const QString& wc) | 2217 void TerminalView::setWordCharacters(const QString& wc) |
2217 { | 2218 { |
2218 _wordCharacters = wc; | 2219 _wordCharacters = wc; |
2219 } | 2220 } |
2220 | 2221 |
2221 void TerminalView::setUsesMouse(bool on) | 2222 void TerminalView::setUsesMouse(bool on) |
2222 { | 2223 { |
2223 _mouseMarks = on; | 2224 _mouseMarks = on; |
2224 setCursor( _mouseMarks ? Qt::IBeamCursor : Qt::ArrowCursor ); | 2225 setCursor( _mouseMarks ? Qt::IBeamCursor : Qt::ArrowCursor ); |
2225 } | 2226 } |
2226 bool TerminalView::usesMouse() const | 2227 bool TerminalView::usesMouse() const |
2227 { | 2228 { |
2228 return _mouseMarks; | 2229 return _mouseMarks; |
2229 } | 2230 } |
2230 | 2231 |
2231 /* ------------------------------------------------------------------------- */ | 2232 /* ------------------------------------------------------------------------- */ |
2232 /* */ | 2233 /* */ |
2233 /* Clipboard */ | 2234 /* Clipboard */ |
2237 #undef KeyPress | 2238 #undef KeyPress |
2238 | 2239 |
2239 void TerminalView::emitSelection(bool useXselection,bool appendReturn) | 2240 void TerminalView::emitSelection(bool useXselection,bool appendReturn) |
2240 { | 2241 { |
2241 if ( !_screenWindow ) | 2242 if ( !_screenWindow ) |
2242 return; | 2243 return; |
2243 | 2244 |
2244 // Paste Clipboard by simulating keypress events | 2245 // Paste Clipboard by simulating keypress events |
2245 QString text = QApplication::clipboard()->text(useXselection ? QClipboard::Selection : | 2246 QString text = QApplication::clipboard()->text(useXselection ? QClipboard::Selection : |
2246 QClipboard::Clipboard); | 2247 QClipboard::Clipboard); |
2247 if(appendReturn) | 2248 if(appendReturn) |
2248 text.append("\r"); | 2249 text.append("\r"); |
2249 if ( ! text.isEmpty() ) | 2250 if ( ! text.isEmpty() ) |
2250 { | 2251 { |
2251 text.replace("\n", "\r"); | 2252 text.replace("\n", "\r"); |
2252 QKeyEvent e(QEvent::KeyPress, 0, Qt::NoModifier, text); | 2253 QKeyEvent e(QEvent::KeyPress, 0, Qt::NoModifier, text); |
2253 emit keyPressedSignal(&e); // expose as a big fat keypress event | 2254 emit keyPressedSignal(&e); // expose as a big fat keypress event |
2254 | 2255 |
2255 _screenWindow->clearSelection(); | 2256 _screenWindow->clearSelection(); |
2256 } | 2257 } |
2257 } | 2258 } |
2258 | 2259 |
2259 void TerminalView::setSelection(const QString& t) | 2260 void TerminalView::setSelection(const QString& t) |
2260 { | 2261 { |
2261 QApplication::clipboard()->setText(t, QClipboard::Selection); | 2262 QApplication::clipboard()->setText(t, QClipboard::Selection); |
2262 } | 2263 } |
2263 | 2264 |
2264 void TerminalView::copyClipboard() | 2265 void TerminalView::copyClipboard() |
2265 { | 2266 { |
2266 if ( !_screenWindow ) | 2267 if ( !_screenWindow ) |
2267 return; | 2268 return; |
2268 | 2269 |
2269 QString text = _screenWindow->selectedText(_preserveLineBreaks); | 2270 QString text = _screenWindow->selectedText(_preserveLineBreaks); |
2270 QApplication::clipboard()->setText(text); | 2271 QApplication::clipboard()->setText(text); |
2271 } | 2272 } |
2272 | 2273 |
2286 /* */ | 2287 /* */ |
2287 /* ------------------------------------------------------------------------- */ | 2288 /* ------------------------------------------------------------------------- */ |
2288 | 2289 |
2289 void TerminalView::keyPressEvent( QKeyEvent* event ) | 2290 void TerminalView::keyPressEvent( QKeyEvent* event ) |
2290 { | 2291 { |
2291 //qDebug("%s %d keyPressEvent and key is %d", __FILE__, __LINE__, event->key()); | 2292 //qDebug("%s %d keyPressEvent and key is %d", __FILE__, __LINE__, event->key()); |
2292 | 2293 |
2293 bool emitKeyPressSignal = true; | 2294 bool emitKeyPressSignal = true; |
2294 | 2295 |
2295 // Keyboard-based navigation | 2296 // Keyboard-based navigation |
2296 if ( event->modifiers() == Qt::ShiftModifier ) | 2297 if ( event->modifiers() == Qt::ShiftModifier ) |
2297 { | 2298 { |
2298 bool update = true; | 2299 bool update = true; |
2299 | 2300 |
2300 if ( event->key() == Qt::Key_PageUp ) | 2301 if ( event->key() == Qt::Key_PageUp ) |
2301 { | 2302 { |
2302 //qDebug("%s %d pageup", __FILE__, __LINE__); | 2303 //qDebug("%s %d pageup", __FILE__, __LINE__); |
2303 _screenWindow->scrollBy( ScreenWindow::ScrollPages , -1 ); | 2304 _screenWindow->scrollBy( ScreenWindow::ScrollPages , -1 ); |
2304 } | 2305 } |
2305 else if ( event->key() == Qt::Key_PageDown ) | 2306 else if ( event->key() == Qt::Key_PageDown ) |
2306 { | 2307 { |
2307 //qDebug("%s %d pagedown", __FILE__, __LINE__); | 2308 //qDebug("%s %d pagedown", __FILE__, __LINE__); |
2308 _screenWindow->scrollBy( ScreenWindow::ScrollPages , 1 ); | 2309 _screenWindow->scrollBy( ScreenWindow::ScrollPages , 1 ); |
2309 } | 2310 } |
2310 else if ( event->key() == Qt::Key_Up ) | 2311 else if ( event->key() == Qt::Key_Up ) |
2311 { | 2312 { |
2312 //qDebug("%s %d keyup", __FILE__, __LINE__); | 2313 //qDebug("%s %d keyup", __FILE__, __LINE__); |
2313 _screenWindow->scrollBy( ScreenWindow::ScrollLines , -1 ); | 2314 _screenWindow->scrollBy( ScreenWindow::ScrollLines , -1 ); |
2314 } | 2315 } |
2315 else if ( event->key() == Qt::Key_Down ) | 2316 else if ( event->key() == Qt::Key_Down ) |
2316 { | 2317 { |
2317 //qDebug("%s %d keydown", __FILE__, __LINE__); | 2318 //qDebug("%s %d keydown", __FILE__, __LINE__); |
2318 _screenWindow->scrollBy( ScreenWindow::ScrollLines , 1 ); | 2319 _screenWindow->scrollBy( ScreenWindow::ScrollLines , 1 ); |
2319 } | 2320 } |
2320 else { | 2321 else { |
2321 update = false; | 2322 update = false; |
2322 } | 2323 } |
2323 | 2324 |
2324 if ( update ) | 2325 if ( update ) |
2325 { | 2326 { |
2326 //qDebug("%s %d updating", __FILE__, __LINE__); | 2327 //qDebug("%s %d updating", __FILE__, __LINE__); |
2327 _screenWindow->setTrackOutput( _screenWindow->atEndOfOutput() ); | 2328 _screenWindow->setTrackOutput( _screenWindow->atEndOfOutput() ); |
2328 | 2329 |
2329 updateLineProperties(); | 2330 updateLineProperties(); |
2330 updateImage(); | 2331 updateImage(); |
2331 | 2332 |
2332 // do not send key press to terminal | 2333 // do not send key press to terminal |
2333 emitKeyPressSignal = false; | 2334 emitKeyPressSignal = false; |
2334 } | 2335 } |
2335 } | 2336 } |
2336 | 2337 |
2337 _screenWindow->setTrackOutput( true ); | 2338 _screenWindow->setTrackOutput( true ); |
2338 | 2339 |
2339 _actSel=0; // Key stroke implies a screen update, so TerminalDisplay won't | 2340 _actSel=0; // Key stroke implies a screen update, so TerminalDisplay won't |
2340 // know where the current selection is. | 2341 // know where the current selection is. |
2341 | 2342 |
2342 if (_hasBlinkingCursor) | 2343 if (_hasBlinkingCursor) |
2343 { | 2344 { |
2344 _blinkCursorTimer->start(BLINK_DELAY); | 2345 _blinkCursorTimer->start(BLINK_DELAY); |
2345 if (_cursorBlinking) | 2346 if (_cursorBlinking) |
2346 blinkCursorEvent(); | 2347 blinkCursorEvent(); |
2347 else | 2348 else |
2348 _cursorBlinking = false; | 2349 _cursorBlinking = false; |
2349 } | 2350 } |
2350 | 2351 |
2351 if ( emitKeyPressSignal && !_readonly ) | 2352 if ( emitKeyPressSignal && !_readonly ) |
2352 emit keyPressedSignal(event); | 2353 emit keyPressedSignal(event); |
2353 | 2354 |
2354 if (_readonly) { | 2355 if (_readonly) { |
2355 event->ignore(); | 2356 event->ignore(); |
2356 } | 2357 } |
2357 else { | 2358 else { |
2358 event->accept(); | 2359 event->accept(); |
2359 } | 2360 } |
2360 } | 2361 } |
2361 | 2362 |
2362 void TerminalView::inputMethodEvent( QInputMethodEvent* event ) | 2363 void TerminalView::inputMethodEvent( QInputMethodEvent* event ) |
2363 { | 2364 { |
2364 QKeyEvent keyEvent(QEvent::KeyPress,0,Qt::NoModifier,event->commitString()); | 2365 QKeyEvent keyEvent(QEvent::KeyPress,0,Qt::NoModifier,event->commitString()); |
2365 emit keyPressedSignal(&keyEvent); | 2366 emit keyPressedSignal(&keyEvent); |
2366 | 2367 |
2367 _inputMethodData.preeditString = event->preeditString(); | 2368 _inputMethodData.preeditString = event->preeditString(); |
2368 update(preeditRect() | _inputMethodData.previousPreeditRect); | 2369 update(preeditRect() | _inputMethodData.previousPreeditRect); |
2369 | 2370 |
2370 event->accept(); | 2371 event->accept(); |
2371 } | 2372 } |
2372 QVariant TerminalView::inputMethodQuery( Qt::InputMethodQuery query ) const | 2373 QVariant TerminalView::inputMethodQuery( Qt::InputMethodQuery query ) const |
2373 { | 2374 { |
2374 const QPoint cursorPos = _screenWindow ? _screenWindow->cursorPosition() : QPoint(0,0); | 2375 const QPoint cursorPos = _screenWindow ? _screenWindow->cursorPosition() : QPoint(0,0); |
2375 switch ( query ) | 2376 switch ( query ) |
2376 { | 2377 { |
2377 case Qt::ImMicroFocus: | 2378 case Qt::ImMicroFocus: |
2378 return imageToWidget(QRect(cursorPos.x(),cursorPos.y(),1,1)); | 2379 return imageToWidget(QRect(cursorPos.x(),cursorPos.y(),1,1)); |
2379 break; | 2380 break; |
2380 case Qt::ImFont: | 2381 case Qt::ImFont: |
2381 return font(); | 2382 return font(); |
2382 break; | 2383 break; |
2383 case Qt::ImCursorPosition: | 2384 case Qt::ImCursorPosition: |
2384 // return the cursor position within the current line | 2385 // return the cursor position within the current line |
2385 return cursorPos.x(); | 2386 return cursorPos.x(); |
2386 break; | 2387 break; |
2387 case Qt::ImSurroundingText: | 2388 case Qt::ImSurroundingText: |
2388 { | 2389 { |
2389 // return the text from the current line | 2390 // return the text from the current line |
2390 QString lineText; | 2391 QString lineText; |
2391 QTextStream stream(&lineText); | 2392 QTextStream stream(&lineText); |
2392 PlainTextDecoder decoder; | 2393 PlainTextDecoder decoder; |
2393 decoder.begin(&stream); | 2394 decoder.begin(&stream); |
2394 decoder.decodeLine(&_image[loc(0,cursorPos.y())],_usedColumns,_lineProperties[cursorPos.y()]); | 2395 decoder.decodeLine(&_image[loc(0,cursorPos.y())],_usedColumns,_lineProperties[cursorPos.y()]); |
2395 decoder.end(); | 2396 decoder.end(); |
2396 return lineText; | 2397 return lineText; |
2397 } | 2398 } |
2398 break; | 2399 break; |
2399 case Qt::ImCurrentSelection: | 2400 case Qt::ImCurrentSelection: |
2400 return QString(); | 2401 return QString(); |
2401 break; | 2402 break; |
2402 default: | 2403 default: |
2403 break; | 2404 break; |
2404 } | 2405 } |
2405 | 2406 |
2406 return QVariant(); | 2407 return QVariant(); |
2407 } | 2408 } |
2408 | 2409 |
2409 bool TerminalView::event( QEvent *e ) | 2410 bool TerminalView::event( QEvent *e ) |
2410 { | 2411 { |
2411 if ( e->type() == QEvent::ShortcutOverride ) | 2412 if ( e->type() == QEvent::ShortcutOverride ) |
2412 { | 2413 { |
2413 QKeyEvent* keyEvent = static_cast<QKeyEvent *>( e ); | 2414 QKeyEvent* keyEvent = static_cast<QKeyEvent *>( e ); |
2414 | 2415 |
2415 // a check to see if keyEvent->text() is empty is used | 2416 // a check to see if keyEvent->text() is empty is used |
2416 // to avoid intercepting the press of the modifier key on its own. | 2417 // to avoid intercepting the press of the modifier key on its own. |
2417 // | 2418 // |
2418 // this is important as it allows a press and release of the Alt key | 2419 // this is important as it allows a press and release of the Alt key |
2419 // on its own to focus the menu bar, making it possible to | 2420 // on its own to focus the menu bar, making it possible to |
2420 // work with the menu without using the mouse | 2421 // work with the menu without using the mouse |
2421 if ( (keyEvent->modifiers() == Qt::AltModifier) && | 2422 if ( (keyEvent->modifiers() == Qt::AltModifier) && |
2422 !keyEvent->text().isEmpty() ) | 2423 !keyEvent->text().isEmpty() ) |
2423 { | 2424 { |
2424 keyEvent->accept(); | 2425 keyEvent->accept(); |
2425 return true; | 2426 return true; |
2426 } | 2427 } |
2427 | 2428 |
2428 // Override any of the following shortcuts because | 2429 // Override any of the following shortcuts because |
2429 // they are needed by the terminal | 2430 // they are needed by the terminal |
2430 int keyCode = keyEvent->key() | keyEvent->modifiers(); | 2431 int keyCode = keyEvent->key() | keyEvent->modifiers(); |
2431 switch ( keyCode ) | 2432 switch ( keyCode ) |
2432 { | 2433 { |
2433 // list is taken from the QLineEdit::event() code | 2434 // list is taken from the QLineEdit::event() code |
2434 case Qt::Key_Tab: | 2435 case Qt::Key_Tab: |
2435 case Qt::Key_Delete: | 2436 case Qt::Key_Delete: |
2436 case Qt::Key_Home: | 2437 case Qt::Key_Home: |
2437 case Qt::Key_End: | 2438 case Qt::Key_End: |
2438 case Qt::Key_Backspace: | 2439 case Qt::Key_Backspace: |
2439 case Qt::Key_Left: | 2440 case Qt::Key_Left: |
2440 case Qt::Key_Right: | 2441 case Qt::Key_Right: |
2441 keyEvent->accept(); | 2442 keyEvent->accept(); |
2442 return true; | 2443 return true; |
2443 } | 2444 } |
2444 } | 2445 } |
2445 return QWidget::event( e ); | 2446 return QWidget::event( e ); |
2446 } | 2447 } |
2447 | 2448 |
2448 void TerminalView::setBellMode(int mode) | 2449 void TerminalView::setBellMode(int mode) |
2449 { | 2450 { |
2450 _bellMode=mode; | 2451 _bellMode=mode; |
2451 } | 2452 } |
2452 | 2453 |
2453 void TerminalView::enableBell() | 2454 void TerminalView::enableBell() |
2454 { | 2455 { |
2455 _allowBell = true; | 2456 _allowBell = true; |
2456 } | 2457 } |
2457 | 2458 |
2458 void TerminalView::bell(const QString&) | 2459 void TerminalView::bell(const QString&) |
2459 { | 2460 { |
2460 if (_bellMode==NoBell) return; | 2461 if (_bellMode==NoBell) return; |
2461 | 2462 |
2462 //limit the rate at which bells can occur | 2463 //limit the rate at which bells can occur |
2463 //...mainly for sound effects where rapid bells in sequence | 2464 //...mainly for sound effects where rapid bells in sequence |
2464 //produce a horrible noise | 2465 //produce a horrible noise |
2465 if ( _allowBell ) | 2466 if ( _allowBell ) |
2466 { | 2467 { |
2467 _allowBell = false; | 2468 _allowBell = false; |
2468 QTimer::singleShot(500,this,SLOT(enableBell())); | 2469 QTimer::singleShot(500,this,SLOT(enableBell())); |
2469 | 2470 |
2470 if (_bellMode==SystemBeepBell) | 2471 if (_bellMode==SystemBeepBell) |
2471 { | 2472 { |
2472 // KNotification::beep(); | 2473 // KNotification::beep(); |
2473 } | 2474 } |
2474 else if (_bellMode==NotifyBell) | 2475 else if (_bellMode==NotifyBell) |
2475 { | 2476 { |
2476 // KNotification::event("BellVisible", message,QPixmap(),this); | 2477 // KNotification::event("BellVisible", message,QPixmap(),this); |
2477 } | 2478 } |
2478 else if (_bellMode==VisualBell) | 2479 else if (_bellMode==VisualBell) |
2479 { | 2480 { |
2480 swapColorTable(); | 2481 swapColorTable(); |
2481 QTimer::singleShot(200,this,SLOT(swapColorTable())); | 2482 QTimer::singleShot(200,this,SLOT(swapColorTable())); |
2482 } | 2483 } |
2483 } | 2484 } |
2484 } | 2485 } |
2485 | 2486 |
2486 void TerminalView::swapColorTable() | 2487 void TerminalView::swapColorTable() |
2487 { | 2488 { |
2488 ColorEntry color = _colorTable[1]; | 2489 ColorEntry color = _colorTable[1]; |
2494 | 2495 |
2495 void TerminalView::clearImage() | 2496 void TerminalView::clearImage() |
2496 { | 2497 { |
2497 // We initialize _image[_imageSize] too. See makeImage() | 2498 // We initialize _image[_imageSize] too. See makeImage() |
2498 for (int i = 0; i <= _imageSize; i++) | 2499 for (int i = 0; i <= _imageSize; i++) |
2499 { | 2500 { |
2500 _image[i].character = ' '; | 2501 _image[i].character = ' '; |
2501 _image[i].foregroundColor = CharacterColor(COLOR_SPACE_DEFAULT, | 2502 _image[i].foregroundColor = CharacterColor(COLOR_SPACE_DEFAULT, |
2502 DEFAULT_FORE_COLOR); | 2503 DEFAULT_FORE_COLOR); |
2503 _image[i].backgroundColor = CharacterColor(COLOR_SPACE_DEFAULT, | 2504 _image[i].backgroundColor = CharacterColor(COLOR_SPACE_DEFAULT, |
2504 DEFAULT_BACK_COLOR); | 2505 DEFAULT_BACK_COLOR); |
2505 _image[i].rendition = DEFAULT_RENDITION; | 2506 _image[i].rendition = DEFAULT_RENDITION; |
2506 } | 2507 } |
2507 } | 2508 } |
2508 | 2509 |
2509 void TerminalView::calcGeometry() | 2510 void TerminalView::calcGeometry() |
2510 { | 2511 { |
2511 _scrollBar->resize(QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent), | 2512 _scrollBar->resize(QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent), |
2512 contentsRect().height()); | 2513 contentsRect().height()); |
2513 switch(_scrollbarLocation) | 2514 switch(_scrollbarLocation) |
2514 { | 2515 { |
2515 case NoScrollBar : | 2516 case NoScrollBar : |
2516 _leftMargin = DEFAULT_LEFT_MARGIN; | 2517 _leftMargin = DEFAULT_LEFT_MARGIN; |
2517 _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN; | 2518 _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN; |
2518 break; | 2519 break; |
2519 case ScrollBarLeft : | 2520 case ScrollBarLeft : |
2520 _leftMargin = DEFAULT_LEFT_MARGIN + _scrollBar->width(); | 2521 _leftMargin = DEFAULT_LEFT_MARGIN + _scrollBar->width(); |
2521 _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width(); | 2522 _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width(); |
2522 _scrollBar->move(contentsRect().topLeft()); | 2523 _scrollBar->move(contentsRect().topLeft()); |
2523 break; | 2524 break; |
2524 case ScrollBarRight: | 2525 case ScrollBarRight: |
2525 _leftMargin = DEFAULT_LEFT_MARGIN; | 2526 _leftMargin = DEFAULT_LEFT_MARGIN; |
2526 _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width(); | 2527 _contentWidth = contentsRect().width() - 2 * DEFAULT_LEFT_MARGIN - _scrollBar->width(); |
2527 _scrollBar->move(contentsRect().topRight() - QPoint(_scrollBar->width()-1,0)); | 2528 _scrollBar->move(contentsRect().topRight() - QPoint(_scrollBar->width()-1,0)); |
2528 break; | 2529 break; |
2529 } | 2530 } |
2530 | 2531 |
2531 _topMargin = DEFAULT_TOP_MARGIN; | 2532 _topMargin = DEFAULT_TOP_MARGIN; |
2532 _contentHeight = contentsRect().height() - 2 * DEFAULT_TOP_MARGIN + /* mysterious */ 1; | 2533 _contentHeight = contentsRect().height() - 2 * DEFAULT_TOP_MARGIN + /* mysterious */ 1; |
2533 | 2534 |
2534 if (!_isFixedSize) | 2535 if (!_isFixedSize) |
2535 { | 2536 { |
2536 // ensure that display is always at least one column wide | 2537 // ensure that display is always at least one column wide |
2537 _columns = qMax(1,_contentWidth / _fontWidth); | 2538 _columns = qMax(1,_contentWidth / _fontWidth); |
2538 _usedColumns = qMin(_usedColumns,_columns); | 2539 _usedColumns = qMin(_usedColumns,_columns); |
2539 | 2540 |
2540 // ensure that display is always at least one line high | 2541 // ensure that display is always at least one line high |
2541 _lines = qMax(1,_contentHeight / _fontHeight); | 2542 _lines = qMax(1,_contentHeight / _fontHeight); |
2542 _usedLines = qMin(_usedLines,_lines); | 2543 _usedLines = qMin(_usedLines,_lines); |
2543 } | 2544 } |
2544 } | 2545 } |
2545 | 2546 |
2546 void TerminalView::makeImage() | 2547 void TerminalView::makeImage() |
2547 { | 2548 { |
2548 //qDebug("%s %d makeImage", __FILE__, __LINE__); | 2549 //qDebug("%s %d makeImage", __FILE__, __LINE__); |
2549 calcGeometry(); | 2550 calcGeometry(); |
2550 | 2551 |
2551 // confirm that array will be of non-zero size, since the painting code | 2552 // confirm that array will be of non-zero size, since the painting code |
2552 // assumes a non-zero array length | 2553 // assumes a non-zero array length |
2553 Q_ASSERT( _lines > 0 && _columns > 0 ); | 2554 Q_ASSERT( _lines > 0 && _columns > 0 ); |
2569 // will be used for margins, the scrollbar etc. | 2570 // will be used for margins, the scrollbar etc. |
2570 // we need to allow for this so that '_size' does allow | 2571 // we need to allow for this so that '_size' does allow |
2571 // enough room for the specified number of columns and lines to fit | 2572 // enough room for the specified number of columns and lines to fit |
2572 | 2573 |
2573 QSize newSize = QSize( columns * _fontWidth , | 2574 QSize newSize = QSize( columns * _fontWidth , |
2574 lines * _fontHeight ); | 2575 lines * _fontHeight ); |
2575 | 2576 |
2576 if ( newSize != size() ) | 2577 if ( newSize != size() ) |
2577 { | 2578 { |
2578 _size = newSize; | 2579 _size = newSize; |
2579 updateGeometry(); | 2580 updateGeometry(); |
2580 } | 2581 } |
2581 } | 2582 } |
2582 | 2583 |
2583 void TerminalView::setFixedSize(int cols, int lins) | 2584 void TerminalView::setFixedSize(int cols, int lins) |
2584 { | 2585 { |
2585 _isFixedSize = true; | 2586 _isFixedSize = true; |
2589 _lines = qMax(1,lins); | 2590 _lines = qMax(1,lins); |
2590 _usedColumns = qMin(_usedColumns,_columns); | 2591 _usedColumns = qMin(_usedColumns,_columns); |
2591 _usedLines = qMin(_usedLines,_lines); | 2592 _usedLines = qMin(_usedLines,_lines); |
2592 | 2593 |
2593 if (_image) | 2594 if (_image) |
2594 { | 2595 { |
2595 delete[] _image; | 2596 delete[] _image; |
2596 makeImage(); | 2597 makeImage(); |
2597 } | 2598 } |
2598 setSize(cols, lins); | 2599 setSize(cols, lins); |
2599 QWidget::setFixedSize(_size); | 2600 QWidget::setFixedSize(_size); |
2600 } | 2601 } |
2601 | 2602 |
2602 QSize TerminalView::sizeHint() const | 2603 QSize TerminalView::sizeHint() const |
2612 /* --------------------------------------------------------------------- */ | 2613 /* --------------------------------------------------------------------- */ |
2613 | 2614 |
2614 void TerminalView::dragEnterEvent(QDragEnterEvent* event) | 2615 void TerminalView::dragEnterEvent(QDragEnterEvent* event) |
2615 { | 2616 { |
2616 if (event->mimeData()->hasFormat("text/plain")) | 2617 if (event->mimeData()->hasFormat("text/plain")) |
2617 event->acceptProposedAction(); | 2618 event->acceptProposedAction(); |
2618 } | 2619 } |
2619 | 2620 |
2620 void TerminalView::dropEvent(QDropEvent* event) | 2621 void TerminalView::dropEvent(QDropEvent* event) |
2621 { | 2622 { |
2622 // KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); | 2623 // KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); |
2623 | 2624 |
2624 QString dropText; | 2625 QString dropText; |
2625 /* if (!urls.isEmpty()) | 2626 /* if (!urls.isEmpty()) |
2626 { | 2627 { |
2627 for ( int i = 0 ; i < urls.count() ; i++ ) | 2628 for ( int i = 0 ; i < urls.count() ; i++ ) |
2628 { | 2629 { |
2629 KUrl url = KIO::NetAccess::mostLocalUrl( urls[i] , 0 ); | 2630 KUrl url = KIO::NetAccess::mostLocalUrl( urls[i] , 0 ); |
2630 QString urlText; | 2631 QString urlText; |
2648 { | 2649 { |
2649 dropText = event->mimeData()->text(); | 2650 dropText = event->mimeData()->text(); |
2650 } | 2651 } |
2651 */ | 2652 */ |
2652 if(event->mimeData()->hasFormat("text/plain")) | 2653 if(event->mimeData()->hasFormat("text/plain")) |
2653 { | 2654 { |
2654 emit sendStringToEmu(dropText.toLocal8Bit()); | 2655 emit sendStringToEmu(dropText.toLocal8Bit()); |
2655 } | 2656 } |
2656 } | 2657 } |
2657 | 2658 |
2658 void TerminalView::doDrag() | 2659 void TerminalView::doDrag() |
2659 { | 2660 { |
2660 dragInfo.state = diDragging; | 2661 dragInfo.state = diDragging; |
2666 // Don't delete the QTextDrag object. Qt will delete it when it's done with it. | 2667 // Don't delete the QTextDrag object. Qt will delete it when it's done with it. |
2667 } | 2668 } |
2668 | 2669 |
2669 void TerminalView::outputSuspended(bool suspended) | 2670 void TerminalView::outputSuspended(bool suspended) |
2670 { | 2671 { |
2671 //create the label when this function is first called | 2672 //create the label when this function is first called |
2672 if (!_outputSuspendedLabel) | 2673 if (!_outputSuspendedLabel) |
2673 { | 2674 { |
2674 //This label includes a link to an English language website | 2675 //This label includes a link to an English language website |
2675 //describing the 'flow control' (Xon/Xoff) feature found in almost | 2676 //describing the 'flow control' (Xon/Xoff) feature found in almost |
2676 //all terminal emulators. | 2677 //all terminal emulators. |
2677 //If there isn't a suitable article available in the target language the link | 2678 //If there isn't a suitable article available in the target language the link |
2678 //can simply be removed. | 2679 //can simply be removed. |
2679 _outputSuspendedLabel = new QLabel( ("<qt>Output has been " | 2680 _outputSuspendedLabel = new QLabel( ("<qt>Output has been " |
2680 "<a href=\"http://en.wikipedia.org/wiki/XON\">suspended</a>" | 2681 "<a href=\"http://en.wikipedia.org/wiki/XON\">suspended</a>" |
2681 " by pressing Ctrl+S." | 2682 " by pressing Ctrl+S." |
2682 " Press <b>Ctrl+Q</b> to resume.</qt>"), | 2683 " Press <b>Ctrl+Q</b> to resume.</qt>"), |
2683 this ); | 2684 this ); |
2684 | 2685 |
2685 QPalette palette(_outputSuspendedLabel->palette()); | 2686 QPalette palette(_outputSuspendedLabel->palette()); |
2686 | 2687 |
2687 palette.setColor(QPalette::Normal, QPalette::WindowText, QColor(Qt::white)); | 2688 palette.setColor(QPalette::Normal, QPalette::WindowText, QColor(Qt::white)); |
2688 palette.setColor(QPalette::Normal, QPalette::Window, QColor(Qt::black)); | 2689 palette.setColor(QPalette::Normal, QPalette::Window, QColor(Qt::black)); |
2689 // KColorScheme::adjustForeground(palette,KColorScheme::NeutralText); | 2690 // KColorScheme::adjustForeground(palette,KColorScheme::NeutralText); |
2690 // KColorScheme::adjustBackground(palette,KColorScheme::NeutralBackground); | 2691 // KColorScheme::adjustBackground(palette,KColorScheme::NeutralBackground); |
2691 _outputSuspendedLabel->setPalette(palette); | 2692 _outputSuspendedLabel->setPalette(palette); |
2692 _outputSuspendedLabel->setAutoFillBackground(true); | 2693 _outputSuspendedLabel->setAutoFillBackground(true); |
2693 _outputSuspendedLabel->setBackgroundRole(QPalette::Base); | 2694 _outputSuspendedLabel->setBackgroundRole(QPalette::Base); |
2694 _outputSuspendedLabel->setFont(QApplication::font()); | 2695 _outputSuspendedLabel->setFont(QApplication::font()); |
2695 _outputSuspendedLabel->setMargin(5); | 2696 _outputSuspendedLabel->setMargin(5); |
2696 | 2697 |
2697 //enable activation of "Xon/Xoff" link in label | 2698 //enable activation of "Xon/Xoff" link in label |
2698 _outputSuspendedLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse | | 2699 _outputSuspendedLabel->setTextInteractionFlags(Qt::LinksAccessibleByMouse | |
2699 Qt::LinksAccessibleByKeyboard); | 2700 Qt::LinksAccessibleByKeyboard); |
2700 _outputSuspendedLabel->setOpenExternalLinks(true); | 2701 _outputSuspendedLabel->setOpenExternalLinks(true); |
2701 _outputSuspendedLabel->setVisible(false); | 2702 _outputSuspendedLabel->setVisible(false); |
2702 | 2703 |
2703 _gridLayout->addWidget(_outputSuspendedLabel); | 2704 _gridLayout->addWidget(_outputSuspendedLabel); |
2704 _gridLayout->addItem( new QSpacerItem(0,0,QSizePolicy::Expanding, | 2705 _gridLayout->addItem( new QSpacerItem(0,0,QSizePolicy::Expanding, |
2705 QSizePolicy::Expanding), | 2706 QSizePolicy::Expanding), |
2706 1,0); | 2707 1,0); |
2707 | 2708 |
2708 } | 2709 } |
2709 | 2710 |
2710 _outputSuspendedLabel->setVisible(suspended); | 2711 _outputSuspendedLabel->setVisible(suspended); |
2711 } | 2712 } |
2712 | 2713 |
2713 uint TerminalView::lineSpacing() const | 2714 uint TerminalView::lineSpacing() const |
2714 { | 2715 { |
2715 return _lineSpacing; | 2716 return _lineSpacing; |