Mercurial > hg > octave-shane
changeset 16632:ace0f60672ec
Merge in Adam's changes
author | Jordi Gutiérrez Hermoso <jordigh@octave.org> |
---|---|
date | Wed, 08 May 2013 14:57:45 -0400 |
parents | c979e6db619b (current diff) cbaf19edc4ee (diff) |
children | 8d32a887754a |
files | |
diffstat | 39 files changed, 1358 insertions(+), 378 deletions(-) [+] |
line wrap: on
line diff
--- a/libgui/qterminal/libqterminal/QTerminal.cc +++ b/libgui/qterminal/libqterminal/QTerminal.cc @@ -41,4 +41,33 @@ setCursorType(QTerminalInterface::BlockCursor, cursorBlinking); else if (cursorType == "underline") setCursorType(QTerminalInterface::UnderlineCursor, cursorBlinking); + + bool cursorUseForegroundColor + = settings->value ("terminal/cursorUseForegroundColor",true).toBool (); + + // FIXME -- we shouldn't duplicate this information here and in the + // resource manager. + QList<QColor> default_colors; + + default_colors << QColor(0,0,0) + << QColor(255,255,255) + << QColor(192,192,192) + << QColor(128,128,128); + + setForegroundColor + (settings->value ("terminal/color_f", + QVariant (default_colors.at (0))).value<QColor> ()); + + setBackgroundColor + (settings->value ("terminal/color_b", + QVariant (default_colors.at (1))).value<QColor> ()); + + setSelectionColor + (settings->value ("terminal/color_s", + QVariant (default_colors.at (2))).value<QColor> ()); + + setCursorColor + (cursorUseForegroundColor, + settings->value ("terminal/color_c", + QVariant (default_colors.at (3))).value<QColor> ()); }
--- a/libgui/qterminal/libqterminal/QTerminalInterface.h +++ b/libgui/qterminal/libqterminal/QTerminalInterface.h @@ -24,6 +24,7 @@ #define QTERMINALINTERFACE_H #include <QWidget> +#include <QColor> #include <QMenu> class QTerminalInterface : public QWidget @@ -61,7 +62,13 @@ Q_UNUSED(blinking); } -public slots: + virtual void setBackgroundColor (const QColor& color) = 0; + virtual void setForegroundColor (const QColor& color) = 0; + virtual void setSelectionColor (const QColor& color) = 0; + virtual void setCursorColor (bool useForegroundColor, + const QColor& color) = 0; + + public slots: virtual void copyClipboard() = 0; virtual void pasteClipboard() = 0;
--- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp +++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp @@ -135,6 +135,18 @@ m_terminalView->setBlinkingCursor(blinking); } +// FIXME -- not sure how to make these work properly given the way the +// Unix terminal handles colors. +void QUnixTerminalImpl::setBackgroundColor (const QColor& color) { } +void QUnixTerminalImpl::setForegroundColor (const QColor& color) { } +void QUnixTerminalImpl::setSelectionColor (const QColor& color) { } + +void QUnixTerminalImpl::setCursorColor (bool useForegroundColor, + const QColor& color) +{ + m_terminalView->setKeyboardCursorColor (useForegroundColor, color); +} + void QUnixTerminalImpl::showEvent(QShowEvent *) { m_terminalView->updateImage();
--- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h +++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h @@ -43,6 +43,11 @@ void setCursorType(CursorType type, bool blinking); + void setBackgroundColor (const QColor& color); + void setForegroundColor (const QColor& color); + void setSelectionColor (const QColor& color); + void setCursorColor (bool useForegroundColor, const QColor& color); + public slots: void copyClipboard(); void pasteClipboard();
--- a/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp +++ b/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp @@ -20,6 +20,7 @@ */ #include <QApplication> +#include <QClipboard> #include <QColor> #include <QFont> #include <QHBoxLayout> @@ -30,6 +31,9 @@ #include <QtDebug> #include <QThread> #include <QTimer> +#include <QToolTip> +#include <QCursor> +#include <QMessageBox> #include <fcntl.h> #include <io.h> @@ -39,6 +43,7 @@ #define _WIN32_WINNT 0x0500 #include <windows.h> #include <cstring> +#include <limits> #include "QWinTerminalImpl.h" #include "QTerminalColors.h" @@ -119,13 +124,37 @@ void setupStandardIO (DWORD stdHandleId, int fd, const char* name, const char* devName); + QPoint posToCell (const QPoint& pt); + QString getSelection (void); + void updateSelection (void); + void clearSelection (void); + + QColor backgroundColor (void) const; + QColor foregroundColor (void) const; + QColor selectionColor (void) const; + QColor cursorColor (void) const; + + void setBackgroundColor (const QColor& color); + void setForegroundColor (const QColor& color); + void setSelectionColor (const QColor& color); + void setCursorColor (bool useForegroundColor, const QColor& color); + + void drawTextBackground (QPainter& p, int cx1, int cy1, int cx2, int cy2, + int cw, int ch); + + void drawSelection (QPainter& p, int cx1, int cy1, int cx2, int cy2, + int cw, int ch); + + void drawCursor (QPainter& p); + + void drawText (QPainter& p, int cx1, int cy1, int cx2, int cy2, + int cw, int ch); + private: QWinTerminalImpl* q; private: QFont m_font; - QColor m_backgroundColor; - QColor m_foregroundColor; QString m_command; QConsoleColors m_colors; bool m_inWheelEvent; @@ -140,6 +169,12 @@ QTimer *m_blinkCursorTimer; KeyboardCursorType m_cursorType; + QPoint m_beginSelection; + QPoint m_endSelection; + + QColor m_selectionColor; + QColor m_cursorColor; + HANDLE m_stdOut; HWND m_consoleWindow; CHAR_INFO* m_buffer; @@ -155,11 +190,19 @@ static const int BLINK_DELAY = 500; }; +static void maybeSwapPoints (QPoint& begin, QPoint& end) +{ + if (end.y () < begin.y () + || (end.y () == begin.y () && end.x () < begin.x ())) + qSwap (begin, end); +} + ////////////////////////////////////////////////////////////////////////////// QConsolePrivate::QConsolePrivate (QWinTerminalImpl* parent, const QString& cmd) : q (parent), m_command (cmd), m_hasBlinkingCursor (true), - m_cursorType (BlockCursor), m_process (NULL), m_inWheelEvent (false) + m_cursorType (BlockCursor), m_beginSelection (0, 0), + m_endSelection (0, 0), m_process (NULL), m_inWheelEvent (false) { log (NULL); @@ -242,10 +285,6 @@ GetConsoleTitleW (titleBuf, sizeof (titleBuf)); q->setWindowTitle (QString::fromWCharArray (titleBuf)); - m_backgroundColor = Qt::white; - m_foregroundColor = Qt::black; - SetConsoleTextAttribute (m_stdOut, 0xF0); - m_font.setFamily ("Lucida Console"); m_font.setPointSize (9); m_font.setStyleHint (QFont::TypeWriter); @@ -261,8 +300,26 @@ l->addWidget (m_consoleView, 1); l->addWidget (m_scrollBar, 0); - m_consoleView->setPalette (QPalette (m_backgroundColor)); + // Choose 15 (0xF) as index into the Windows console color map for the + // background and 0 (0x0) as the index for the foreground. This + // selection corresponds to the indices used in the foregroundColor, + // setForegroundColor, backgroundColor, and SetBackgroundColor + // functions. + + SetConsoleTextAttribute (m_stdOut, 0xF0); + + // Defaults. + setBackgroundColor (Qt::white); + setForegroundColor (Qt::black); + setSelectionColor (Qt::lightGray); + setCursorColor (false, Qt::darkGray); + + // FIXME -- should we set the palette? + QPalette palette (backgroundColor ()); + m_consoleView->setPalette (palette); + m_consoleView->setAutoFillBackground (true); + m_consoleView->setFont (m_font); parent->setFocusPolicy (Qt::StrongFocus); parent->winId (); @@ -340,7 +397,372 @@ log ("Failed to open %s: errno=%d.\n", devName, errno); } -////////////////////////////////////////////////////////////////////////////// +QPoint QConsolePrivate::posToCell (const QPoint& p) +{ + return QPoint (m_consoleRect.left () + p.x () / m_charSize.width (), + m_consoleRect.top () + p.y () / m_charSize.height ()); +} + +QString QConsolePrivate::getSelection (void) +{ + QString selection; + + QPoint begin = m_beginSelection; + QPoint end = m_endSelection; + + maybeSwapPoints (begin, end); + + if (begin != end) + { + CHAR_INFO* buf; + COORD bufSize, bufCoord; + SMALL_RECT bufRect; + int nr; + + nr = end.y () - begin.y () + 1; + buf = new CHAR_INFO[m_bufferSize.width () * nr]; + bufSize.X = m_bufferSize.width (); + bufSize.Y = nr; + bufCoord.X = 0; + bufCoord.Y = 0; + + bufRect.Left = 0; + bufRect.Right = m_bufferSize.width (); + bufRect.Top = begin.y (); + bufRect.Bottom = end.y (); + + if (ReadConsoleOutput (m_stdOut, buf, bufSize, bufCoord, &bufRect)) + { + int start_pos = begin.x (); + int end_pos = (nr - 1) * m_bufferSize.width () + end.x (); + int lastNonSpace = -1; + + for (int i = start_pos; i <= end_pos; i++) + { + if (i && (i % m_bufferSize.width ()) == 0) + { + if (lastNonSpace >= 0) + selection.truncate (lastNonSpace); + selection.append ('\n'); + lastNonSpace = selection.length (); + } + + QChar c (buf[i].Char.UnicodeChar); + + selection.append (c); + if (! c.isSpace ()) + lastNonSpace = selection.length (); + } + + if (lastNonSpace >= 0) + selection.truncate (lastNonSpace); + } + } + + return selection; +} + +void QConsolePrivate::updateSelection (void) +{ + QPoint begin = m_beginSelection; + QPoint end = m_endSelection; + + maybeSwapPoints (begin, end); + + begin.rx () = 0; + end.rx () = m_consoleRect.width (); + + m_consoleView->update (); +} + +void QConsolePrivate::clearSelection (void) +{ + m_beginSelection = m_endSelection = QPoint (); + + m_consoleView->update (); +} + +QColor QConsolePrivate::backgroundColor (void) const +{ + return m_colors[15]; +} + +QColor QConsolePrivate::foregroundColor (void) const +{ + return m_colors[0]; +} + +QColor QConsolePrivate::selectionColor (void) const +{ + return m_selectionColor; +} + +QColor QConsolePrivate::cursorColor (void) const +{ + return m_cursorColor.isValid () ? m_cursorColor : foregroundColor (); +} + +void QConsolePrivate::setBackgroundColor (const QColor& color) +{ + m_colors[15] = color; +} + +void QConsolePrivate::setForegroundColor (const QColor& color) +{ + m_colors[0] = color; +} + +void QConsolePrivate::setSelectionColor (const QColor& color) +{ + m_selectionColor = color; +} + +void QConsolePrivate::setCursorColor (bool useForegroundColor, + const QColor& color) +{ + m_cursorColor = useForegroundColor ? QColor () : color; +} + +void QConsolePrivate::drawTextBackground (QPainter& p, int cx1, int cy1, + int cx2, int cy2, int cw, int ch) +{ + p.save (); + + int ascent = p.fontMetrics ().ascent (); + int stride = m_consoleRect.width (); + int y = ascent + cy1 * ch;; + + for (int j = cy1; j <= cy2; j++, y += ch) + { + int len = 0; + bool hasChar = false; + int x = cx1 * cw; + WORD attr = 0; + + for (int i = cx1; i <= cx2; i++) + { + CHAR_INFO* ci = &(m_buffer[stride*j+i]); + + if ((ci->Attributes & 0x00ff) != attr) + { + // Character attributes changed + if (len != 0) + { + // String buffer not empty -> draw it + if (hasChar || (attr & 0x00f0)) + { + if (attr & 0x00f0) + p.fillRect (x, y-ascent, len * cw, ch, p.brush ()); + } + + x += (len * cw); + len = 0; + hasChar = false; + } + // Update current brush and store current attributes + attr = (ci->Attributes & 0x00ff); + p.setBrush (m_colors[(attr >> 4) & 0x000f]); + } + + // Append current character to the string buffer + len++; + if (ci->Char.UnicodeChar != L' ') + hasChar = true; + } + + if (len != 0 && (hasChar || (attr & 0x00f0))) + { + // Line end reached, but string buffer not empty -> draw it + // No need to update s or x, they will be reset on the next + // for-loop iteration + + if (attr & 0x00f0) + p.fillRect (x, y-ascent, len * cw, ch, p.brush ()); + } + } + + p.restore (); +} + +void QConsolePrivate::drawSelection (QPainter& p, int cx1, int cy1, + int cx2, int cy2, int cw, int ch) +{ + p.save (); + + QPoint begin = m_beginSelection; + QPoint end = m_endSelection; + + bool haveSelection = (begin != end); + + if (haveSelection) + maybeSwapPoints (begin, end); + + int scrollOffset = m_consoleRect.top (); + + begin.ry () -= scrollOffset; + end.ry () -= scrollOffset; + + int ascent = p.fontMetrics ().ascent (); + int stride = m_consoleRect.width (); + + int y = ascent + cy1 * ch;; + for (int j = cy1; j <= cy2; j++, y += ch) + { + int charsThisLine = 0; + int len = 0; + bool hasChar = false; + WORD attr = 0; + + for (int i = cx1; i <= cx2; i++) + { + CHAR_INFO* ci = &(m_buffer[stride*j+i]); + + if ((ci->Attributes & 0x00ff) != attr) + { + // Character attributes changed + if (len != 0) + { + charsThisLine += len; + len = 0; + hasChar = false; + } + + // Store current attributes + attr = (ci->Attributes & 0x00ff); + } + + // Append current character to the string buffer + len++; + if (ci->Char.UnicodeChar != L' ') + hasChar = true; + } + + if (len != 0 && (hasChar || (attr & 0x00f0))) + charsThisLine += len; + + if (haveSelection && j >= begin.y () && j <= end.y ()) + { + int selectionBegin = j == begin.y () ? begin.x (): 0; + + int len = ((j == end.y () && end.x () < charsThisLine) + ? end.x () - selectionBegin + 1 + : stride - selectionBegin); + + p.fillRect (selectionBegin * cw, y-ascent, len * cw, ch, + selectionColor ()); + } + } + + p.restore (); +} + +void QConsolePrivate::drawCursor (QPainter& p) +{ + if (! m_cursorBlinking) + { + p.save (); + + QRect rect = cursorRect (); + QColor color = cursorColor (); + + p.setPen (color); + + if (m_cursorType == QConsolePrivate::BlockCursor) + { + if (q->hasFocus ()) + p.fillRect (rect, color); + else + { + // draw the cursor outline, adjusting the area so that + // it is draw entirely inside 'rect' + + int penWidth = qMax (1, p.pen().width()); + + p.drawRect (rect.adjusted (penWidth/2, penWidth/2, + - penWidth/2 - penWidth%2, + - penWidth/2 - penWidth%2)); + } + } + else if (m_cursorType == QConsolePrivate::UnderlineCursor) + { + p.drawLine (rect.left (), rect.bottom (), + rect.right (), rect.bottom ()); + } + else if (m_cursorType == QConsolePrivate::IBeamCursor) + { + p.drawLine (rect.left (), rect.top (), + rect.left (), rect.bottom ()); + } + + p.restore (); + } +} + +void QConsolePrivate::drawText (QPainter& p, int cx1, int cy1, + int cx2, int cy2, int cw, int ch) +{ + p.save (); + + p.setFont (m_font); + p.setPen (foregroundColor ()); + + QString s; + s.reserve (cx2 - cx1 + 1); + + int ascent = p.fontMetrics ().ascent (); + int stride = m_consoleRect.width (); + + int y = ascent + cy1 * ch;; + for (int j = cy1; j <= cy2; j++, y += ch) + { + // Reset string buffer and starting X coordinate + s.clear (); + bool hasChar = false; + int x = cx1 * cw; + WORD attr = 0; + + for (int i = cx1; i <= cx2; i++) + { + CHAR_INFO* ci = &(m_buffer[stride*j+i]); + + if ((ci->Attributes & 0x00ff) != attr) + { + // Character attributes changed + if (! s.isEmpty ()) + { + // String buffer not empty -> draw it + if (hasChar || (attr & 0x00f0)) + p.drawText (x, y, s); + + x += (s.length () * cw); + s.clear (); + hasChar = false; + } + // Update current pen and store current attributes + attr = (ci->Attributes & 0x00ff); + p.setPen (m_colors[attr & 0x000f]); + } + + // Append current character to the string buffer + s.append (ci->Char.UnicodeChar); + if (ci->Char.UnicodeChar != L' ') + hasChar = true; + } + + if (! s.isEmpty () && (hasChar || (attr & 0x00f0))) + { + // Line end reached, but string buffer not empty -> draw it + // No need to update s or x, they will be reset on the next + // for-loop iteration + + p.drawText (x, y, s); + } + } + + p.restore (); +} + +///////////////////////////////////////////////////////////////////////////// void QConsolePrivate::closeStandardIO (int fd, DWORD stdHandleId, const char* name) @@ -384,10 +806,10 @@ QFontMetrics fm (m_font); QSize winSize = m_consoleView->size (); - m_charSize.rwidth () = fm.maxWidth (); + m_charSize.rwidth () = fm.averageCharWidth (); m_charSize.rheight () = fm.lineSpacing (); - m_consoleRect.setWidth (winSize.width () / fm.maxWidth ()); + m_consoleRect.setWidth (winSize.width () / fm.averageCharWidth ()); m_consoleRect.setHeight (winSize.height () / fm.lineSpacing ()); m_bufferSize.rwidth () = m_consoleRect.width (); @@ -753,6 +1175,29 @@ delete d; } +void QWinTerminalImpl::mouseMoveEvent (QMouseEvent *event) +{ + d->m_endSelection = d->posToCell (event->pos ()); + + updateSelection (); +} + +void QWinTerminalImpl::mousePressEvent (QMouseEvent *event) +{ + if (event->button () == Qt::LeftButton) + d->m_beginSelection = d->posToCell (event->pos ()); +} + +void QWinTerminalImpl::mouseReleaseEvent (QMouseEvent *event) +{ + if (event->button () == Qt::LeftButton) + { + d->m_endSelection = d->posToCell (event->pos ()); + + updateSelection (); + } +} + ////////////////////////////////////////////////////////////////////////////// void QWinTerminalImpl::viewResizeEvent (QConsoleView*, QResizeEvent*) @@ -766,124 +1211,25 @@ void QWinTerminalImpl::viewPaintEvent (QConsoleView* w, QPaintEvent* event) { QPainter p (w); - int cw = d->m_charSize.width (), ch = d->m_charSize.height (); - int ascent, stride, cx1, cy1, cx2, cy2, x, y; - WORD attr = 0; - QString s; - bool hasChar = false; + + int cw = d->m_charSize.width (); + int ch = d->m_charSize.height (); QRect updateRect = event->rect (); - cx1 = updateRect.left () / cw; - cy1 = updateRect.top () / ch; - cx2 = qMin (d->m_consoleRect.width () - 1, updateRect.right () / cw); - cy2 = qMin (d->m_consoleRect.height () - 1, updateRect.bottom () / ch); + int cx1 = updateRect.left () / cw; + int cy1 = updateRect.top () / ch; + int cx2 = qMin (d->m_consoleRect.width () - 1, updateRect.right () / cw); + int cy2 = qMin (d->m_consoleRect.height () - 1, updateRect.bottom () / ch); if (cx1 > d->m_consoleRect.width () - 1 || cy1 > d->m_consoleRect.height () - 1) return; - p.setFont (d->m_font); - p.setPen (d->m_foregroundColor); - - ascent = p.fontMetrics ().ascent (); - stride = d->m_consoleRect.width (); - - s.reserve (cx2 - cx1 + 1); - y = ascent + cy1 * ch;; - - for (int j = cy1; j <= cy2; j++, y += ch) - { - // Reset string buffer and starting X coordinate - s.clear (); - hasChar = false; - x = cx1 * cw; - - for (int i = cx1; i <= cx2; i++) - { - CHAR_INFO* ci = &(d->m_buffer[stride*j+i]); - - if ((ci->Attributes & 0x00ff) != attr) - { - // Character attributes changed - if (! s.isEmpty ()) - { - // String buffer not empty -> draw it - if (hasChar || (attr & 0x00f0)) - { - if (attr & 0x00f0) - p.fillRect (x, y-ascent, s.length () * cw, ch, - p.brush ()); - p.drawText (x, y, s); - } - x += (s.length () * cw); - s.clear (); - hasChar = false; - } - // Update current pen and store current attributes - // FIXME: what about background? - attr = (ci->Attributes & 0x00ff); - p.setPen (d->m_colors[attr & 0x000f]); - p.setBrush (d->m_colors[(attr >> 4) & 0x000f]); - } - - // Append current character to the string buffer - s.append (ci->Char.UnicodeChar); - if (ci->Char.UnicodeChar != L' ') - hasChar = true; - } - - if (! s.isEmpty () && (hasChar || (attr & 0x00f0))) - { - // Line end reached, but string buffer not empty -> draw it - // No need to update s or x, they will be reset on the next - // for-loop iteration - if (attr & 0x00f0) - p.fillRect (x, y-ascent, s.length () * cw, ch, p.brush ()); - p.drawText (x, y, s); - } - } - - if (! d->m_cursorBlinking) - { - QColor cursorColor = d->m_colors[7]; - QRect cursorRect = d->cursorRect (); - - p.setPen (d->m_foregroundColor); - - if (d->m_cursorType == QConsolePrivate::BlockCursor) - { - if (hasFocus ()) - { - p.setCompositionMode (QPainter::RasterOp_SourceXorDestination); - - p.fillRect (cursorRect, cursorColor); - } - else - { - // draw the cursor outline, adjusting the area so that - // it is draw entirely inside 'rect' - - int penWidth = qMax (1, p.pen().width()); - - p.setBrush (Qt::NoBrush); - - p.drawRect (cursorRect.adjusted (penWidth/2, penWidth/2, - - penWidth/2 - penWidth%2, - - penWidth/2 - penWidth%2)); - } - } - else if (d->m_cursorType == QConsolePrivate::UnderlineCursor) - { - p.drawLine (cursorRect.left (), cursorRect.bottom (), - cursorRect.right (), cursorRect.bottom ()); - } - else if (d->m_cursorType == QConsolePrivate::IBeamCursor) - { - p.drawLine (cursorRect.left (), cursorRect.top (), - cursorRect.left (), cursorRect.bottom ()); - } - } + d->drawTextBackground (p, cx1, cy1, cx2, cy2, cw, ch); + d->drawSelection (p, cx1, cy1, cx2, cy2, cw, ch); + d->drawCursor (p); + d->drawText (p, cx1, cy1, cx2, cy2, cw, ch); } void QWinTerminalImpl::blinkCursorEvent (void) @@ -965,6 +1311,11 @@ d->monitorConsole (); } +void QWinTerminalImpl::updateSelection (void) +{ + d->updateSelection (); +} + ////////////////////////////////////////////////////////////////////////////// void QWinTerminalImpl::focusInEvent (QFocusEvent* event) @@ -1031,6 +1382,27 @@ setBlinkingCursor (blinking); } +void QWinTerminalImpl::setBackgroundColor (const QColor& color) +{ + d->setBackgroundColor (color); +} + +void QWinTerminalImpl::setForegroundColor (const QColor& color) +{ + d->setForegroundColor (color); +} + +void QWinTerminalImpl::setSelectionColor (const QColor& color) +{ + d->setSelectionColor (color); +} + +void QWinTerminalImpl::setCursorColor (bool useForegroundColor, + const QColor& color) +{ + d->setCursorColor (useForegroundColor, color); +} + ////////////////////////////////////////////////////////////////////////////// void QWinTerminalImpl::setTerminalFont (const QFont& f) @@ -1052,10 +1424,17 @@ void QWinTerminalImpl::copyClipboard (void) { + QClipboard *clipboard = QApplication::clipboard (); + + clipboard->setText (d->getSelection ()); } ////////////////////////////////////////////////////////////////////////////// void QWinTerminalImpl::pasteClipboard (void) { + QString text = QApplication::clipboard()->text (QClipboard::Clipboard); + + if (! text.isEmpty ()) + sendText (text); }
--- a/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.h +++ b/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.h @@ -30,6 +30,7 @@ class QPaintEvent; class QResizeEvent; class QWheelEvent; +class QPoint; class QConsolePrivate; class QConsoleThread; @@ -54,6 +55,11 @@ void sendText (const QString& s); void setCursorType (CursorType type, bool blinking); + void setBackgroundColor (const QColor& color); + void setForegroundColor (const QColor& color); + void setSelectionColor (const QColor& color); + void setCursorColor (bool useForegoundColor, const QColor& color); + public slots: void copyClipboard (void); void pasteClipboard (void); @@ -74,10 +80,14 @@ void keyPressEvent (QKeyEvent*); bool winEvent (MSG*, long*); virtual void start (void); + void mouseMoveEvent (QMouseEvent *event); + void mousePressEvent (QMouseEvent *event); + void mouseReleaseEvent (QMouseEvent *event); private slots: void scrollValueChanged (int value); void monitorConsole (void); + void updateSelection (void); private: QConsolePrivate* d;
--- a/libgui/src/color-picker.cc +++ b/libgui/src/color-picker.cc @@ -49,8 +49,17 @@ // draw the button with the actual color (using a stylesheet) void color_picker::update_button () { - QString css = QString("background-color: %1; border: none;" ) - .arg(_color.name()); + // Is this the right place to look for a "foreground" color that would + // provide a reasonable border for the color swatches? + QWidget *p = parentWidget (); + + QString bordercolor + = p ? p->palette().text().color().name() : QString ("#000000"); + + QString css = QString("background-color: %1; border: 1px solid %2;") + .arg(_color.name()) + .arg(bordercolor); + setStyleSheet(css); repaint (); }
--- a/libgui/src/dialog.cc +++ b/libgui/src/dialog.cc @@ -163,7 +163,7 @@ // Make the last button the button pressed when <esc> key activated. if (i == N-1) { -#define ACTIVE_ESCAPE true +#define ACTIVE_ESCAPE 1 #if ACTIVE_ESCAPE setEscapeButton (pbutton); #else @@ -231,7 +231,7 @@ for (int j = 0; j < prompt.length (); j++) { if (j > 0) -#define RICH_TEXT true +#define RICH_TEXT 1 #if RICH_TEXT prompt_string.append ("<br>"); #else @@ -327,7 +327,7 @@ : QDialog () { -#define LINE_EDIT_FOLLOWS_PROMPT false +#define LINE_EDIT_FOLLOWS_PROMPT 0 #if LINE_EDIT_FOLLOWS_PROMPT // Prompt on left followed by input on right.
--- a/libgui/src/files-dock-widget.cc +++ b/libgui/src/files-dock-widget.cc @@ -28,9 +28,9 @@ #include "files-dock-widget.h" #include <QApplication> +#include <QClipboard> #include <QFileInfo> #include <QCompleter> -#include <QSettings> #include <QProcess> #include <QDebug> #include <QHeaderView> @@ -42,9 +42,23 @@ #include <QToolButton> #include <QUrl> #include <QDesktopServices> +#include <QFileDialog> #include "load-save.h" +class FileTreeViewer : public QTreeView +{ +public: + + FileTreeViewer (QWidget *p) : QTreeView (p) { } + + void mousePressEvent (QMouseEvent *e) + { + if (e->button () != Qt::RightButton) + QTreeView::mousePressEvent (e); + } +}; + files_dock_widget::files_dock_widget (QWidget *p) : octave_dock_widget (p) { @@ -63,9 +77,6 @@ connect (this, SIGNAL (displayed_directory_changed (const QString&)), parent (), SLOT (set_current_working_directory (const QString&))); - connect (parent (), SIGNAL (settings_changed (const QSettings *)), - this, SLOT (notice_settings (const QSettings *))); - // Create a toolbar _navigation_tool_bar = new QToolBar ("", container); _navigation_tool_bar->setAllowedAreas (Qt::TopToolBarArea); @@ -104,6 +115,10 @@ popdown_button->setDefaultAction(new QAction(QIcon(":/actions/icons/gear.png"),"", _navigation_tool_bar)); popdown_menu->addSeparator(); + popdown_menu->addAction (QIcon (":/actions/icons/search.png"), + tr ("Search directory"), + this, SLOT (popdownmenu_search_dir (bool))); + popdown_menu->addSeparator(); popdown_menu->addAction(QIcon(":/actions/icons/filenew.png"), tr ("New File"), this, SLOT(popdownmenu_newfile(bool))); @@ -130,7 +145,8 @@ curr_dir.absolutePath ()); // Attach the model to the QTreeView and set the root index - _file_tree_view = new QTreeView (container); + _file_tree_view = new FileTreeViewer (container); + _file_tree_view->setSelectionMode (QAbstractItemView::ExtendedSelection); _file_tree_view->setModel (_file_system_model); _file_tree_view->setRootIndex (rootPathIndex); _file_tree_view->setSortingEnabled (true); @@ -327,6 +343,9 @@ menu.addAction (tr("Open in Default Application"), this, SLOT (contextmenu_open_in_app (bool))); + menu.addAction (tr("Copy Selection to Clipboard"), + this, SLOT (contextmenu_copy_selection (bool))); + if (info.isFile () && info.suffix () == "m") menu.addAction (QIcon (":/actions/icons/artsbuilderexecute.png"), tr("Run"), this, SLOT(contextmenu_run(bool))); @@ -387,6 +406,26 @@ } void +files_dock_widget::contextmenu_copy_selection (bool) +{ + QItemSelectionModel *m = _file_tree_view->selectionModel (); + QModelIndexList rows = m->selectedRows (); + + QStringList selection; + + for (QModelIndexList::iterator it = rows.begin (); it != rows.end (); it++) + { + QFileInfo info = _file_system_model->fileInfo (*it); + + selection << info.fileName (); + } + + QClipboard *clipboard = QApplication::clipboard (); + + clipboard->setText (selection.join ("\n")); +} + +void files_dock_widget::contextmenu_load (bool) { QItemSelectionModel *m = _file_tree_view->selectionModel (); @@ -573,6 +612,14 @@ } void +files_dock_widget::popdownmenu_search_dir (bool) +{ + QString dir + = QFileDialog::getExistingDirectory (this, tr ("Set directory of file browser")); + process_set_current_dir (dir); +} + +void files_dock_widget::popdownmenu_newdir (bool) { process_new_dir(_file_system_model->rootPath());
--- a/libgui/src/files-dock-widget.h +++ b/libgui/src/files-dock-widget.h @@ -34,7 +34,7 @@ #include <QVBoxLayout> #include <QAction> #include <QTreeView> -#include <QSettings> +#include <QMouseEvent> #include <QComboBox> #include "octave-dock-widget.h" @@ -86,6 +86,7 @@ /* context menu actions */ void contextmenu_open (bool); void contextmenu_open_in_app (bool); + void contextmenu_copy_selection (bool); void contextmenu_run (bool); void contextmenu_load (bool); void contextmenu_rename (bool); @@ -97,6 +98,7 @@ /* popdown menu options */ void popdownmenu_newfile(bool); void popdownmenu_newdir(bool); + void popdownmenu_search_dir (bool); signals:
new file mode 100755 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..6ed5fface345dc0330e25526d9b158792c15e5e6 GIT binary patch literal 2449 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 P00000NkvXXu0mjfbZfxS
--- a/libgui/src/m-editor/file-editor.cc +++ b/libgui/src/m-editor/file-editor.cc @@ -319,9 +319,8 @@ // open a file from the mru list void -file_editor::request_mru_open_file (void) +file_editor::request_mru_open_file (QAction *action) { - QAction *action = qobject_cast<QAction *> (sender ()); if (action) { request_open_file (action->data ().toString ()); @@ -625,6 +624,36 @@ } void +file_editor::request_close_file (bool) +{ + emit fetab_close_request (_tab_widget->currentWidget ()); +} + +void +file_editor::request_close_all_files (bool) +{ + int index; + while ((index = _tab_widget->currentIndex ()) > -1) + emit fetab_close_request (_tab_widget->widget (index)); +} + +void +file_editor::request_close_other_files (bool) +{ + int index = 0; + QWidget *tabID = _tab_widget->currentWidget (); + + while (_tab_widget->count () > 1) + { + if (tabID != _tab_widget->widget (index)) + emit fetab_close_request (_tab_widget->widget (index)); + else + index++; + } +} + + +void file_editor::handle_tab_close_request (int index) { // Signal to the tabs a request to close whomever matches the identifying @@ -848,22 +877,40 @@ // menu bar QMenu *fileMenu = new QMenu (tr ("&File"), _menu_bar); - fileMenu->addAction (new_action); - fileMenu->addAction (open_action); - fileMenu->addAction (save_action); - fileMenu->addAction (save_as_action); - fileMenu->addSeparator (); + _mru_file_menu = new QMenu (tr ("&Recent Editor Files"), fileMenu); - for (int i = 0; i < MaxMRUFiles; ++i) _mru_file_menu->addAction (_mru_file_actions[i]); + fileMenu->addAction (new_action); + fileMenu->addAction (open_action); fileMenu->addMenu (_mru_file_menu); - _menu_bar->addMenu (fileMenu); + + fileMenu->addSeparator (); + fileMenu->addAction (save_action); + fileMenu->addAction (save_as_action); + + fileMenu->addSeparator (); + fileMenu->addAction (QIcon::fromTheme("window-close", + QIcon (":/actions/icons/fileclose.png")), + tr ("&Close"), + this, SLOT (request_close_file (bool)), + QKeySequence::Close); + fileMenu->addAction (QIcon::fromTheme("window-close", + QIcon (":/actions/icons/fileclose.png")), + tr ("Close All"), + this, SLOT (request_close_all_files (bool))); + fileMenu->addAction (QIcon::fromTheme("window-close", + QIcon (":/actions/icons/fileclose.png")), + tr ("Close Other Files"), + this, SLOT (request_close_other_files (bool))); fileMenu->addSeparator (); fileMenu->addAction (print_action); + _menu_bar->addMenu (fileMenu); + + QMenu *editMenu = new QMenu (tr ("&Edit"), _menu_bar); editMenu->addAction (undo_action); editMenu->addAction (redo_action); @@ -906,9 +953,6 @@ editor_widget->setLayout (vbox_layout); setWidget (editor_widget); - connect (parent (), SIGNAL (settings_changed (const QSettings *)), - this, SLOT (notice_settings (const QSettings *))); - connect (parent (), SIGNAL (new_file_signal (const QString&)), this, SLOT (request_new_file (const QString&))); @@ -984,12 +1028,8 @@ connect (goto_line_action, SIGNAL (triggered ()), this, SLOT (request_goto_line ())); - // The actions of the mru file menu - for (int i = 0; i < MaxMRUFiles; ++i) - { - connect (_mru_file_actions[i], SIGNAL (triggered ()), - this, SLOT (request_mru_open_file ())); - } + connect (_mru_file_menu, SIGNAL (triggered (QAction *)), + this, SLOT (request_mru_open_file (QAction *))); mru_menu_update ();
--- a/libgui/src/m-editor/file-editor.h +++ b/libgui/src/m-editor/file-editor.h @@ -29,7 +29,6 @@ #include <QStatusBar> #include <QCloseEvent> #include <QTabWidget> -#include <QSettings> #include <map> @@ -106,7 +105,10 @@ void request_new_script (const QString& commands); void request_new_function (const QString& commands); void request_open_file (void); - void request_mru_open_file (void); + void request_close_file (bool); + void request_close_all_files (bool); + void request_close_other_files (bool); + void request_mru_open_file (QAction *action); void request_print_file (void); void request_undo (void);
--- a/libgui/src/module.mk +++ b/libgui/src/module.mk @@ -23,6 +23,7 @@ src/icons/editcut.png \ src/icons/editdelete.png \ src/icons/editpaste.png \ + src/icons/fileclose.png \ src/icons/filenew.png \ src/icons/fileopen.png \ src/icons/fileprint.png \
--- a/libgui/src/octave-dock-widget.h +++ b/libgui/src/octave-dock-widget.h @@ -24,6 +24,7 @@ #define octave_dock_widget_h 1 #include <QDockWidget> +#include <QSettings> class octave_dock_widget : public QDockWidget { @@ -39,6 +40,9 @@ connect (this, SIGNAL (topLevelChanged (bool)), this, SLOT (top_level_changed (bool))); + + connect (p, SIGNAL (settings_changed (const QSettings*)), + this, SLOT (notice_settings (const QSettings*))); } virtual ~octave_dock_widget () { } @@ -49,6 +53,7 @@ this, SLOT (handle_visibility (bool))); } + signals: /** Custom signal that tells whether a user has clicked away @@ -82,6 +87,10 @@ focus (); } + virtual void notice_settings (const QSettings*) + { + } + protected slots: /** Slot to steer changing visibility from outside. */
--- a/libgui/src/resource-manager.cc +++ b/libgui/src/resource-manager.cc @@ -217,6 +217,24 @@ << QColor(255,190,255); } +QStringList +resource_manager::terminal_color_names (void) +{ + return QStringList () << QObject::tr ("foreground") + << QObject::tr ("background") + << QObject::tr ("selection") + << QObject::tr ("cursor"); +} + +QList<QColor> +resource_manager::terminal_default_colors (void) +{ + return QList<QColor> () << QColor(0,0,0) + << QColor(255,255,255) + << QColor(192,192,192) + << QColor(128,128,128); +} + const char* resource_manager::octave_keywords (void) {
--- a/libgui/src/resource-manager.h +++ b/libgui/src/resource-manager.h @@ -87,6 +87,10 @@ static QStringList storage_class_names (void); static QList<QColor> storage_class_default_colors (void); + static QString terminal_color_chars (void) { return "fbsc"; } + static QStringList terminal_color_names (void); + static QList<QColor> terminal_default_colors (void); + private: static resource_manager *instance;
--- a/libgui/src/resource.qrc +++ b/libgui/src/resource.qrc @@ -5,6 +5,7 @@ <file>icons/editcut.png</file> <file>icons/editdelete.png</file> <file>icons/editpaste.png</file> + <file>icons/fileclose.png</file> <file>icons/filenew.png</file> <file>icons/fileopen.png</file> <file>icons/filesave.png</file>
--- a/libgui/src/settings-dialog.cc +++ b/libgui/src/settings-dialog.cc @@ -31,6 +31,7 @@ #include <QSettings> #include <QDir> #include <QFileInfo> +#include <QVector> #ifdef HAVE_QSCINTILLA #include <QScrollArea> @@ -97,6 +98,7 @@ ui->useProxyServer->setChecked (settings->value ("useProxyServer",false).toBool ()); ui->proxyHostName->setText (settings->value ("proxyHostName").toString ()); ui->terminal_cursorBlinking->setChecked (settings->value ("terminal/cursorBlinking",true).toBool ()); + ui->terminal_cursorUseForegroundColor->setChecked (settings->value ("terminal/cursorUseForegroundColor",true).toBool ()); QString cursorType = settings->value ("terminal/cursorType","ibeam").toString (); @@ -129,6 +131,9 @@ // qorkspace colors read_workspace_colors (settings); + // terminal colors + read_terminal_colors (settings); + #ifdef HAVE_QSCINTILLA // editor styles: create lexer, read settings, and create dialog elements QsciLexer *lexer; @@ -150,7 +155,9 @@ lexer = new QsciLexerBash (); read_lexer_settings (lexer,settings); delete lexer; -#endif +#endif + + ui->tabWidget->setCurrentIndex (settings->value("settings/last_tab",0).toInt ()); } settings_dialog::~settings_dialog () @@ -181,11 +188,11 @@ int styles[MaxLexerStyles]; // array for saving valid styles (enum is not continuous) int max_style = get_valid_lexer_styles (lexer, styles); QGridLayout *style_grid = new QGridLayout (); - QLabel *description[max_style]; - QFontComboBox *select_font[max_style]; - QSpinBox *font_size[max_style]; - QCheckBox *attrib_font[3][max_style]; - color_picker *color[max_style]; + QVector<QLabel*> description (max_style); + QVector<QFontComboBox*> select_font (max_style); + QVector<QSpinBox*> font_size (max_style); + QVector<QCheckBox*> attrib_font (3 * max_style); + QVector<color_picker*> color (max_style); int default_size = 10; QFont default_font = QFont (); for (int i = 0; i < max_style; i++) // create dialog elements for all styles @@ -217,25 +224,25 @@ font_size[i]->setValue (actual_font.pointSize ()-default_size); font_size[i]->setToolTip ("Difference to the defalt size"); } - attrib_font[0][i] = new QCheckBox (tr("b")); - attrib_font[1][i] = new QCheckBox (tr("i")); - attrib_font[2][i] = new QCheckBox (tr("u")); - attrib_font[0][i]->setChecked(Qt::Checked && actual_font.bold ()); - attrib_font[0][i]->setObjectName (actual_name+"_bold"); - attrib_font[1][i]->setChecked(Qt::Checked && actual_font.italic ()); - attrib_font[1][i]->setObjectName (actual_name+"_italic"); - attrib_font[2][i]->setChecked(Qt::Checked && actual_font.underline ()); - attrib_font[2][i]->setObjectName (actual_name+"_underline"); + attrib_font[0+3*i] = new QCheckBox (tr("b")); + attrib_font[1+3*i] = new QCheckBox (tr("i")); + attrib_font[2+3*i] = new QCheckBox (tr("u")); + attrib_font[0+3*i]->setChecked(Qt::Checked && actual_font.bold ()); + attrib_font[0+3*i]->setObjectName (actual_name+"_bold"); + attrib_font[1+3*i]->setChecked(Qt::Checked && actual_font.italic ()); + attrib_font[1+3*i]->setObjectName (actual_name+"_italic"); + attrib_font[2+3*i]->setChecked(Qt::Checked && actual_font.underline ()); + attrib_font[2+3*i]->setObjectName (actual_name+"_underline"); color[i] = new color_picker (lexer->color (styles[i])); color[i]->setObjectName (actual_name+"_color"); int column = 1; - style_grid->addWidget (description[i], i,column++); - style_grid->addWidget (select_font[i], i,column++); - style_grid->addWidget (font_size[i], i,column++); - style_grid->addWidget (attrib_font[0][i],i,column++); - style_grid->addWidget (attrib_font[1][i],i,column++); - style_grid->addWidget (attrib_font[2][i],i,column++); - style_grid->addWidget (color[i], i,column++); + style_grid->addWidget (description[i], i, column++); + style_grid->addWidget (select_font[i], i, column++); + style_grid->addWidget (font_size[i], i, column++); + style_grid->addWidget (attrib_font[0+3*i], i, column++); + style_grid->addWidget (attrib_font[1+3*i], i, column++); + style_grid->addWidget (attrib_font[2+3*i], i, column++); + style_grid->addWidget (color[i], i, column++); } // place grid with elements into the tab QScrollArea *scroll_area = new QScrollArea (); @@ -244,6 +251,9 @@ scroll_area_contents->setLayout (style_grid); scroll_area->setWidget (scroll_area_contents); ui->tabs_editor_styles->addTab (scroll_area,lexer->language ()); + + ui->tabs_editor_styles->setCurrentIndex ( + settings->value("settings/last_editor_styles_tab",0).toInt ()); } #endif @@ -257,8 +267,8 @@ int nr_of_classes = class_chars.length (); QGridLayout *style_grid = new QGridLayout (); - QLabel *description[nr_of_classes]; - color_picker *color[nr_of_classes]; + QVector<QLabel*> description (nr_of_classes); + QVector<color_picker*> color (nr_of_classes); int column = 0; int row = 0; @@ -285,6 +295,43 @@ ui->workspace_colors_box->setLayout (style_grid); } +void +settings_dialog::read_terminal_colors (QSettings *settings) +{ + + QList<QColor> default_colors = resource_manager::terminal_default_colors (); + QStringList class_names = resource_manager::terminal_color_names (); + QString class_chars = resource_manager::terminal_color_chars (); + int nr_of_classes = class_chars.length (); + + QGridLayout *style_grid = new QGridLayout (); + QVector<QLabel*> description (nr_of_classes); + QVector<color_picker*> color (nr_of_classes); + + int column = 0; + int row = 0; + for (int i = 0; i < nr_of_classes; i++) + { + description[i] = new QLabel (class_names.at (i)); + description[i]->setAlignment (Qt::AlignRight); + QVariant default_var = default_colors.at (i); + QColor setting_color = settings->value ("terminal/color_"+class_chars.mid (i,1), + default_var).value<QColor> (); + color[i] = new color_picker (setting_color); + color[i]->setObjectName ("terminal_color_"+class_chars.mid (i,1)); + color[i]->setMinimumSize (30,10); + style_grid->addWidget (description[i], row,2*column); + style_grid->addWidget (color[i], row,2*column+1); + if (++column == 2) + { + row++; + column = 0; + } + } + + // place grid with elements into the tab + ui->terminal_colors_box->setLayout (style_grid); +} void settings_dialog::write_changed_settings () @@ -330,6 +377,7 @@ settings->setValue ("proxyUserName", ui->proxyUserName->text ()); settings->setValue ("proxyPassword", ui->proxyPassword->text ()); settings->setValue ("terminal/cursorBlinking", ui->terminal_cursorBlinking->isChecked ()); + settings->setValue ("terminal/cursorUseForegroundColor", ui->terminal_cursorUseForegroundColor->isChecked ()); // the cursor QString cursorType; @@ -366,6 +414,10 @@ #endif write_workspace_colors (settings); + + write_terminal_colors (settings); + + settings->setValue("settings/last_tab",ui->tabWidget->currentIndex ()); } #ifdef HAVE_QSCINTILLA @@ -424,6 +476,9 @@ lexer->setColor (color->color (),styles[i]); } lexer->writeSettings (*settings); + + settings->setValue ( + "settings/last_editor_styles_tab",ui->tabs_editor_styles->currentIndex ()); } #endif @@ -444,3 +499,20 @@ } settings->sync (); } + +void +settings_dialog::write_terminal_colors (QSettings *settings) +{ + QString class_chars = resource_manager::terminal_color_chars (); + color_picker *color; + + for (int i = 0; i < class_chars.length (); i++) + { + color = ui->terminal_colors_box->findChild <color_picker *>( + "terminal_color_"+class_chars.mid (i,1)); + if (color) + settings->setValue ("terminal/color_"+class_chars.mid (i,1), + color->color ()); + } + settings->sync (); +}
--- a/libgui/src/settings-dialog.h +++ b/libgui/src/settings-dialog.h @@ -52,6 +52,9 @@ void read_workspace_colors (QSettings *settings); void write_workspace_colors (QSettings *settings); + + void read_terminal_colors (QSettings *settings); + void write_terminal_colors (QSettings *settings); }; #endif // SETTINGSDIALOG_H
--- a/libgui/src/settings-dialog.ui +++ b/libgui/src/settings-dialog.ui @@ -32,7 +32,7 @@ <item> <widget class="QTabWidget" name="tabWidget"> <property name="currentIndex"> - <number>0</number> + <number>3</number> </property> <widget class="QWidget" name="tab_4"> <property name="enabled"> @@ -317,126 +317,167 @@ <attribute name="title"> <string>Terminal</string> </attribute> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_5"> - <item> - <widget class="QLabel" name="label_11"> - <property name="text"> - <string>Font</string> - </property> - </widget> - </item> - <item> - <widget class="QFontComboBox" name="terminal_fontName"> - <property name="editable"> - <bool>false</bool> - </property> - <property name="fontFilters"> - <set>QFontComboBox::MonospacedFonts</set> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_12"> - <property name="text"> - <string>Font Size</string> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="terminal_fontSize"> - <property name="minimum"> - <number>2</number> - </property> - <property name="maximum"> - <number>96</number> - </property> - <property name="value"> - <number>10</number> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_5"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Cursor type:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="terminal_cursorType"/> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QCheckBox" name="terminal_cursorBlinking"> - <property name="text"> - <string>Cursor blinking</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item> - <spacer name="verticalSpacer_3"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>321</height> - </size> - </property> - </spacer> - </item> - </layout> + <widget class="QWidget" name="horizontalLayoutWidget"> + <property name="geometry"> + <rect> + <x>10</x> + <y>50</y> + <width>631</width> + <height>31</height> + </rect> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Cursor type:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="terminal_cursorType"/> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QCheckBox" name="terminal_cursorBlinking"> + <property name="text"> + <string>Cursor blinking</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="terminal_cursorUseForegroundColor"> + <property name="text"> + <string>Use Foreground Color</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="verticalLayoutWidget_2"> + <property name="geometry"> + <rect> + <x>10</x> + <y>90</y> + <width>631</width> + <height>164</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="terminal_colors_box"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>162</height> + </size> + </property> + <property name="title"> + <string>Terminal Colors</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="verticalLayoutWidget_3"> + <property name="geometry"> + <rect> + <x>10</x> + <y>260</y> + <width>631</width> + <height>121</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout_8"> + <item> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <widget class="QWidget" name="layoutWidget"> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>631</width> + <height>30</height> + </rect> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <widget class="QLabel" name="label_11"> + <property name="text"> + <string>Font</string> + </property> + </widget> + </item> + <item> + <widget class="QFontComboBox" name="terminal_fontName"> + <property name="editable"> + <bool>false</bool> + </property> + <property name="fontFilters"> + <set>QFontComboBox::MonospacedFonts</set> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_12"> + <property name="text"> + <string>Font Size</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="terminal_fontSize"> + <property name="minimum"> + <number>2</number> + </property> + <property name="maximum"> + <number>96</number> + </property> + <property name="value"> + <number>10</number> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> </widget> <widget class="QWidget" name="tab_2"> <attribute name="title"> @@ -513,6 +554,12 @@ <height>81</height> </rect> </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>81</height> + </size> + </property> <property name="title"> <string>Storage Class Colors</string> </property>
--- a/libgui/src/terminal-dock-widget.cc +++ b/libgui/src/terminal-dock-widget.cc @@ -38,9 +38,6 @@ setWindowTitle (tr ("Command Window")); setWidget (terminal); - connect (parent (), SIGNAL (settings_changed (const QSettings *)), - this, SLOT (notice_settings (const QSettings *))); - connect (this, SIGNAL (visibilityChanged (bool)), this, SLOT (handle_visibility (bool)));
--- a/libgui/src/workspace-view.cc +++ b/libgui/src/workspace-view.cc @@ -78,9 +78,6 @@ connect (this, SIGNAL (command_requested (const QString&)), p, SLOT (execute_command_in_terminal (const QString&))); - connect (parent (), SIGNAL (settings_changed (const QSettings *)), - this, SLOT (notice_settings (const QSettings *))); - } workspace_view::~workspace_view (void)
--- a/libinterp/interpfcn/debug.cc +++ b/libinterp/interpfcn/debug.cc @@ -316,19 +316,27 @@ { if (! do_add_breakpoint_1 (dbg_fcn, fname, line, retval)) { - typedef std::map<std::string, octave_value>::const_iterator - subfunction_map_const_iterator; + // Search subfunctions in the order they appear in the file. + + const std::list<std::string> subfcn_names + = dbg_fcn->subfunction_names (); std::map<std::string, octave_value> subfcns = dbg_fcn->subfunctions (); - for (subfunction_map_const_iterator p = subfcns.begin (); - p != subfcns.end (); p++) + for (std::list<std::string>::const_iterator p = subfcn_names.begin (); + p != subfcn_names.end (); p++) { - octave_user_code *dbg_subfcn = p->second.user_code_value (); + std::map<std::string, octave_value>::const_iterator + q = subfcns.find (*p); - if (do_add_breakpoint_1 (dbg_subfcn, fname, line, retval)) - break; + if (q != subfcns.end ()) + { + octave_user_code *dbg_subfcn = q->second.user_code_value (); + + if (do_add_breakpoint_1 (dbg_subfcn, fname, line, retval)) + break; + } } } } @@ -342,6 +350,56 @@ int +bp_table::do_remove_breakpoint_1 (octave_user_code *fcn, + const std::string& fname, + const bp_table::intmap& line) +{ + int retval = 0; + + std::string file = fcn->fcn_file_name (); + + tree_statement_list *cmds = fcn->body (); + + // FIXME -- move the operation on cmds to the + // tree_statement_list class? + + if (cmds) + { + octave_value_list results = cmds->list_breakpoints (); + + if (results.length () > 0) + { + octave_idx_type len = line.size (); + + for (int i = 0; i < len; i++) + { + const_intmap_iterator p = line.find (i); + + if (p != line.end ()) + { + int lineno = p->second; + + cmds->delete_breakpoint (lineno); + + if (! file.empty ()) + octave_link::update_breakpoint (false, file, lineno); + } + } + + results = cmds->list_breakpoints (); + + bp_set_iterator it = bp_set.find (fname); + if (results.length () == 0 && it != bp_set.end ()) + bp_set.erase (it); + } + + retval = results.length (); + } + + return retval; +} + +int bp_table::do_remove_breakpoint (const std::string& fname, const bp_table::intmap& line) { @@ -360,41 +418,28 @@ if (dbg_fcn) { - std::string file = dbg_fcn->fcn_file_name (); + retval = do_remove_breakpoint_1 (dbg_fcn, fname, line); - tree_statement_list *cmds = dbg_fcn->body (); + // Search subfunctions in the order they appear in the file. - // FIXME -- move the operation on cmds to the - // tree_statement_list class? - if (cmds) - { - octave_value_list results = cmds->list_breakpoints (); + const std::list<std::string> subfcn_names + = dbg_fcn->subfunction_names (); - if (results.length () > 0) - { - for (int i = 0; i < len; i++) - { - const_intmap_iterator p = line.find (i); + std::map<std::string, octave_value> subfcns + = dbg_fcn->subfunctions (); - if (p != line.end ()) - { - int lineno = p->second; - - cmds->delete_breakpoint (lineno); + for (std::list<std::string>::const_iterator p = subfcn_names.begin (); + p != subfcn_names.end (); p++) + { + std::map<std::string, octave_value>::const_iterator + q = subfcns.find (*p); - if (! file.empty ()) - octave_link::update_breakpoint (false, file, lineno); - } - } - - results = cmds->list_breakpoints (); + if (q != subfcns.end ()) + { + octave_user_code *dbg_subfcn = q->second.user_code_value (); - bp_set_iterator it = bp_set.find (fname); - if (results.length () == 0 && it != bp_set.end ()) - bp_set.erase (it); + retval += do_remove_breakpoint_1 (dbg_subfcn, fname, line); } - - retval = results.length (); } } else @@ -406,6 +451,27 @@ return retval; } +bp_table::intmap +bp_table::do_remove_all_breakpoints_in_file_1 (octave_user_code *fcn, + const std::string& fname) +{ + intmap retval; + + std::string file = fcn->fcn_file_name (); + + tree_statement_list *cmds = fcn->body (); + + if (cmds) + { + retval = cmds->remove_all_breakpoints (file); + + bp_set_iterator it = bp_set.find (fname); + if (it != bp_set.end ()) + bp_set.erase (it); + } + + return retval; +} bp_table::intmap bp_table::do_remove_all_breakpoints_in_file (const std::string& fname, @@ -417,17 +483,24 @@ if (dbg_fcn) { - std::string file = dbg_fcn->fcn_file_name (); + retval = do_remove_all_breakpoints_in_file_1 (dbg_fcn, fname); + + // Order is not important here. - tree_statement_list *cmds = dbg_fcn->body (); + typedef std::map<std::string, octave_value>::const_iterator + subfcns_const_iterator; - if (cmds) + std::map<std::string, octave_value> subfcns = dbg_fcn->subfunctions (); + + for (subfcns_const_iterator p = subfcns.begin (); + p != subfcns.end (); p++) { - retval = cmds->remove_all_breakpoints (file); + octave_user_code *dbg_subfcn = p->second.user_code_value (); - bp_set_iterator it = bp_set.find (fname); - if (it != bp_set.end ()) - bp_set.erase (it); + intmap tmp = do_remove_all_breakpoints_in_file_1 (dbg_subfcn, fname); + + // Merge new list with retval. + retval.insert (tmp.begin (), tmp.end ()); } } else if (! silent)
--- a/libinterp/interpfcn/debug.h +++ b/libinterp/interpfcn/debug.h @@ -120,8 +120,14 @@ intmap do_add_breakpoint (const std::string& fname, const intmap& lines); + int do_remove_breakpoint_1 (octave_user_code *fcn, const std::string&, + const intmap& lines); + int do_remove_breakpoint (const std::string&, const intmap& lines); + intmap do_remove_all_breakpoints_in_file_1 (octave_user_code *fcn, + const std::string& fname); + intmap do_remove_all_breakpoints_in_file (const std::string& fname, bool silent);
--- a/libinterp/interpfcn/load-save.h +++ b/libinterp/interpfcn/load-save.h @@ -83,7 +83,7 @@ bool list_only, bool swap, bool verbose, const string_vector& argv, int argv_idx, int argc, int nargout); -extern bool is_octave_data_file (const std::string& file); +extern OCTINTERP_API bool is_octave_data_file (const std::string& file); extern void do_save (std::ostream& os, const symbol_table::symbol_record& sr,
--- a/libinterp/interpfcn/octave-link.h +++ b/libinterp/interpfcn/octave-link.h @@ -41,7 +41,9 @@ // buffering access operations to octave and executing them in the // readline event hook, which lives in the octave thread. -class octave_link +class +OCTINTERP_API +octave_link { protected:
--- a/libinterp/octave-value/ov-fcn.h +++ b/libinterp/octave-value/ov-fcn.h @@ -134,6 +134,18 @@ virtual void unlock_subfunctions (void) { } + virtual void maybe_relocate_end (void) { } + + // Not valid until after the function is completley parsed. + virtual bool has_subfunctions (void) const { return false; } + + virtual void stash_subfunction_names (const std::list<std::string>&) { } + + virtual std::list<std::string> subfunction_names (void) const + { + return std::list<std::string> (); + } + void mark_relative (void) { relative = true; } bool is_relative (void) const { return relative; }
--- a/libinterp/octave-value/ov-usr-fcn.cc +++ b/libinterp/octave-value/ov-usr-fcn.cc @@ -248,6 +248,70 @@ file_name = nm; } +// If there is no explicit end statement at the end of the function, +// relocate the no_op that was generated for the end of file condition +// to appear on the next line after the last statement in the file, or +// the next line after the function keyword if there are no statements. +// More precisely, the new location should probably be on the next line +// after the end of the parameter list, but we aren't tracking that +// information (yet). + +void +octave_user_function::maybe_relocate_end_internal (void) +{ + if (cmd_list && ! cmd_list->empty ()) + { + tree_statement *last_stmt = cmd_list->back (); + + if (last_stmt && last_stmt->is_end_of_fcn_or_script () + && last_stmt->is_end_of_file ()) + { + tree_statement_list::reverse_iterator + next_to_last_elt = cmd_list->rbegin (); + + next_to_last_elt++; + + int new_eof_line; + int new_eof_col; + + if (next_to_last_elt == cmd_list->rend ()) + { + new_eof_line = beginning_line (); + new_eof_col = beginning_column (); + } + else + { + tree_statement *next_to_last_stmt = *next_to_last_elt; + + new_eof_line = next_to_last_stmt->line (); + new_eof_col = next_to_last_stmt->column (); + } + + last_stmt->set_location (new_eof_line + 1, new_eof_col); + } + } +} + +void +octave_user_function::maybe_relocate_end (void) +{ + std::map<std::string, octave_value> fcns = subfunctions (); + + if (! fcns.empty ()) + { + for (std::map<std::string, octave_value>::iterator p = fcns.begin (); + p != fcns.end (); p++) + { + octave_user_function *f = (p->second).user_function_value (); + + if (f) + f->maybe_relocate_end_internal (); + } + } + + maybe_relocate_end_internal (); +} + std::string octave_user_function::profiler_name (void) const { @@ -320,6 +384,19 @@ return symbol_table::subfunctions_defined_in_scope (local_scope); } +bool +octave_user_function::has_subfunctions (void) const +{ + return ! subfcn_names.empty (); +} + +void +octave_user_function::stash_subfunction_names + (const std::list<std::string>& names) +{ + subfcn_names = names; +} + octave_value_list octave_user_function::all_va_args (const octave_value_list& args) {
--- a/libinterp/octave-value/ov-usr-fcn.h +++ b/libinterp/octave-value/ov-usr-fcn.h @@ -208,6 +208,20 @@ location_column = col; } + int beginning_line (void) const { return location_line; } + int beginning_column (void) const { return location_column; } + + void stash_fcn_end_location (int line, int col) + { + end_location_line = line; + end_location_column = col; + } + + int ending_line (void) const { return end_location_line; } + int ending_column (void) const { return end_location_column; } + + void maybe_relocate_end (void); + void stash_parent_fcn_name (const std::string& p) { parent_name = p; } void stash_parent_fcn_scope (symbol_table::scope_id ps) { parent_scope = ps; } @@ -266,6 +280,15 @@ std::map<std::string, octave_value> subfunctions (void) const; + bool has_subfunctions (void) const; + + void stash_subfunction_names (const std::list<std::string>& names); + + std::list<std::string> subfunction_names (void) const + { + return subfcn_names; + } + octave_value_list all_va_args (const octave_value_list& args); void stash_function_name (const std::string& s) { my_name = s; } @@ -406,10 +429,16 @@ // Location where this function was defined. int location_line; int location_column; + int end_location_line; + int end_location_column; // The name of the parent function, if any. std::string parent_name; + // The list of subfunctions (if any) in the order they appear in the + // file. + std::list<std::string> subfcn_names; + // The time the file was parsed. octave_time t_parsed; @@ -458,6 +487,8 @@ jit_function_info *jit_info; #endif + void maybe_relocate_end_internal (void); + void print_code_function_header (void); void print_code_function_trailer (void);
--- a/libinterp/parse-tree/oct-parse.in.yy +++ b/libinterp/parse-tree/oct-parse.in.yy @@ -219,14 +219,16 @@ %token <tok_val> METAQUERY %token <tok_val> SUPERCLASSREF %token <tok_val> GET SET +%token <tok_val> FCN // Other tokens. %token END_OF_INPUT LEXICAL_ERROR -%token FCN INPUT_FILE CLASSDEF +%token INPUT_FILE CLASSDEF // %token VARARGIN VARARGOUT // Nonterminals we construct. -%type <comment_type> stash_comment function_beg classdef_beg +%type <tok_val> function_beg +%type <comment_type> stash_comment classdef_beg %type <comment_type> properties_beg methods_beg events_beg enum_beg %type <sep_type> sep_no_nl opt_sep_no_nl nl opt_nl sep opt_sep %type <tree_type> input @@ -1119,9 +1121,9 @@ if (! lexer.reading_fcn_file) { tree_statement *end_of_script - = parser.make_end ("endscript", - lexer.input_line_number, - lexer.current_input_column); + = parser.make_end ("endscript", true, + lexer.input_line_number, + lexer.current_input_column); parser.make_script ($3, end_of_script); } @@ -1134,23 +1136,25 @@ // Function definition // =================== -function_beg : push_fcn_symtab FCN stash_comment +function_beg : push_fcn_symtab FCN { - $$ = $3; + $$ = $2; if (lexer.reading_classdef_file || lexer.parsing_classdef) lexer.maybe_classdef_get_set_method = true; } ; -function : function_beg function1 +function : function_beg stash_comment function1 { - $$ = parser.finish_function (0, $2, $1); + $$ = parser.finish_function (0, $3, $2, $1->line (), + $1->column ()); parser.recover_from_parsing_function (); } - | function_beg return_list '=' function1 + | function_beg stash_comment return_list '=' function1 { - $$ = parser.finish_function ($2, $4, $1); + $$ = parser.finish_function ($3, $5, $2, $1->line (), + $1->column ()); parser.recover_from_parsing_function (); } ; @@ -1199,7 +1203,8 @@ { parser.endfunction_found = true; if (parser.end_token_ok ($1, token::function_end)) - $$ = parser.make_end ("endfunction", $1->line (), $1->column ()); + $$ = parser.make_end ("endfunction", false, + $1->line (), $1->column ()); else ABORT_PARSE; } @@ -1233,9 +1238,9 @@ YYABORT; } - $$ = parser.make_end ("endfunction", - lexer.input_line_number, - lexer.current_input_column); + $$ = parser.make_end ("endfunction", true, + lexer.input_line_number, + lexer.current_input_column); } ; @@ -1255,7 +1260,8 @@ lexer.parsing_classdef = false; if (parser.end_token_ok ($1, token::classdef_end)) - $$ = parser.make_end ("endclassdef", $1->line (), $1->column ()); + $$ = parser.make_end ("endclassdef", false, + $1->line (), $1->column ()); else ABORT_PARSE; } @@ -1494,6 +1500,7 @@ curr_class_name = ""; function_scopes.clear (); primary_fcn_ptr = 0; + subfunction_names.clear (); delete stmt_list; stmt_list = 0; @@ -2598,15 +2605,17 @@ octave_comment_list *tc = octave_comment_buffer::get_comment (); fcn->stash_trailing_comment (tc); + fcn->stash_fcn_end_location (end_fcn_stmt->line (), + end_fcn_stmt->column ()); } return fcn; } tree_statement * -octave_base_parser::make_end (const std::string& type, int l, int c) +octave_base_parser::make_end (const std::string& type, bool eof, int l, int c) { - return make_statement (new tree_no_op_command (type, l, c)); + return make_statement (new tree_no_op_command (type, eof, l, c)); } // Do most of the work for defining a function. @@ -2695,8 +2704,6 @@ } fcn->stash_function_name (id_name); - fcn->stash_fcn_location (lexer.input_line_number, - lexer.current_input_column); if (! lexer.help_text.empty () && curr_fcn_depth == 1 && ! parsing_subfunctions) @@ -2716,7 +2723,8 @@ tree_function_def * octave_base_parser::finish_function (tree_parameter_list *ret_list, octave_user_function *fcn, - octave_comment_list *lc) + octave_comment_list *lc, + int l, int c) { tree_function_def *retval = 0; @@ -2742,6 +2750,9 @@ if (curr_fcn_depth > 1 || parsing_subfunctions) { fcn->mark_as_subfunction (); + fcn->stash_fcn_location (l, c); + + subfunction_names.push_back (nm); if (endfunction_found && function_scopes.size () > 1) { @@ -3301,6 +3312,19 @@ fcn_ptr = parser.primary_fcn_ptr; + if (fcn_ptr) + { + fcn_ptr->maybe_relocate_end (); + + if (parser.parsing_subfunctions) + { + if (! parser.endfunction_found) + parser.subfunction_names.reverse (); + + fcn_ptr->stash_subfunction_names (parser.subfunction_names); + } + } + if (status != 0) error ("parse error while reading file %s", full_file.c_str ()); }
--- a/libinterp/parse-tree/parse.h +++ b/libinterp/parse-tree/parse.h @@ -136,7 +136,7 @@ parsing_subfunctions (false), max_fcn_depth (0), curr_fcn_depth (0), primary_fcn_scope (-1), curr_class_name (), function_scopes (), primary_fcn_ptr (0), - stmt_list (0), + subfunction_names (), stmt_list (0), lexer (lxr) { init (); @@ -270,7 +270,7 @@ tree_statement *end_function); // Create a no-op statement for end_function. - tree_statement *make_end (const std::string& type, int l, int c); + tree_statement *make_end (const std::string& type, bool eof, int l, int c); // Do most of the work for defining a function. octave_user_function * @@ -279,7 +279,8 @@ // Finish defining a function. tree_function_def * finish_function (tree_parameter_list *ret_list, - octave_user_function *fcn, octave_comment_list *lc); + octave_user_function *fcn, octave_comment_list *lc, + int l, int c); // Reset state after parsing function. void @@ -377,6 +378,11 @@ // Pointer to the primary user function or user script function. octave_function *primary_fcn_ptr; + // List of subfunction names, initially in the order they are + // installed in the symbol table, then ordered as they appear in the + // file. Eventually stashed in the primary function object. + std::list<std::string> subfunction_names; + // Result of parsing input. tree_statement_list *stmt_list;
--- a/libinterp/parse-tree/pt-cmd.cc +++ b/libinterp/parse-tree/pt-cmd.cc @@ -33,7 +33,8 @@ tree_no_op_command::dup (symbol_table::scope_id, symbol_table::context_id) const { - return new tree_no_op_command (orig_cmd, line (), column ()); + return new tree_no_op_command (orig_cmd, is_end_of_file (), + line (), column ()); } void
--- a/libinterp/parse-tree/pt-cmd.h +++ b/libinterp/parse-tree/pt-cmd.h @@ -63,9 +63,9 @@ { public: - tree_no_op_command (const std::string& cmd = "no_op", int l = -1, int c = -1) - : tree_command (l, c), eof (cmd == "endfunction" || cmd == "endscript"), - orig_cmd (cmd) { } + tree_no_op_command (const std::string& cmd = "no_op", bool e = false, + int l = -1, int c = -1) + : tree_command (l, c), eof (e), orig_cmd (cmd) { } ~tree_no_op_command (void) { } @@ -74,7 +74,12 @@ void accept (tree_walker& tw); - bool is_end_of_fcn_or_script (void) const { return eof; } + bool is_end_of_fcn_or_script (void) const + { + return (orig_cmd == "endfunction" || orig_cmd == "endscript"); + } + + bool is_end_of_file (void) const { return eof; } std::string original_command (void) { return orig_cmd; }
--- a/libinterp/parse-tree/pt-stmt.cc +++ b/libinterp/parse-tree/pt-stmt.cc @@ -107,6 +107,15 @@ } void +tree_statement::set_location (int l, int c) +{ + if (cmd) + cmd->set_location (l, c); + else if (expr) + expr->set_location (l, c); +} + +void tree_statement::echo_code (void) { tree_print_code tpc (octave_stdout, VPS4); @@ -131,6 +140,23 @@ return retval; } +bool +tree_statement::is_end_of_file (void) const +{ + bool retval = false; + + if (cmd) + { + tree_no_op_command *no_op_cmd + = dynamic_cast<tree_no_op_command *> (cmd); + + if (no_op_cmd) + retval = no_op_cmd->is_end_of_file (); + } + + return retval; +} + tree_statement * tree_statement::dup (symbol_table::scope_id scope, symbol_table::context_id context) const
--- a/libinterp/parse-tree/pt-stmt.h +++ b/libinterp/parse-tree/pt-stmt.h @@ -74,6 +74,8 @@ int line (void) const; int column (void) const; + void set_location (int l, int c); + void echo_code (void); tree_command *command (void) { return cmd; } @@ -86,6 +88,8 @@ bool is_end_of_fcn_or_script (void) const; + bool is_end_of_file (void) const; + // Allow modification of this statement. Note that there is no // checking. If you use these, are you sure you knwo what you are // doing?
--- a/libinterp/parse-tree/pt.h +++ b/libinterp/parse-tree/pt.h @@ -50,6 +50,12 @@ void column (int c) { column_num = c; } + void set_location (int l, int c) + { + line_num = l; + column_num = c; + } + virtual void set_breakpoint (void) { bp = true; } virtual void delete_breakpoint (void) { bp = false; }
--- a/liboctave/util/base-list.h +++ b/liboctave/util/base-list.h @@ -36,6 +36,9 @@ typedef typename std::list<elt_type>::iterator iterator; typedef typename std::list<elt_type>::const_iterator const_iterator; + typedef typename std::list<elt_type>::reverse_iterator reverse_iterator; + typedef typename std::list<elt_type>::const_reverse_iterator const_reverse_iterator; + bool empty (void) const { return lst.empty (); } size_t size (void) const { return lst.size (); } @@ -74,6 +77,12 @@ iterator end (void) { return iterator (lst.end ()); } const_iterator end (void) const { return const_iterator (lst.end ()); } + reverse_iterator rbegin (void) { return reverse_iterator (lst.rbegin ()); } + const_reverse_iterator rbegin (void) const { return const_reverse_iterator (lst.rbegin ()); } + + reverse_iterator rend (void) { return reverse_iterator (lst.rend ()); } + const_reverse_iterator rend (void) const { return const_reverse_iterator (lst.rend ()); } + elt_type& front (void) { return lst.front (); } elt_type& back (void) { return lst.back (); }
--- a/src/mkoctfile.in.cc +++ b/src/mkoctfile.in.cc @@ -396,6 +396,13 @@ return system (cmd.c_str ()); } +bool +is_true (const std::string& s) +{ + return (s == "yes" + || s == "true"); +} + int main (int argc, char **argv) { @@ -414,7 +421,7 @@ string ldflags = ""; string pass_on_options = ""; bool strip = false; - bool no_oct_file_strip_on_this_platform = %NO_OCT_FILE_STRIP%; + bool no_oct_file_strip_on_this_platform = is_true ("%NO_OCT_FILE_STRIP%"); bool link = true; bool link_stand_alone = false; string output_ext = ".oct";