add more spacing
[personal-kdebase.git] / apps / konsole / src / TerminalDisplay.h
blobde9fc8f207c72fdd002c49c31390f99e52acb730
1 /*
2 Copyright 2007-2008 by Robert Knight <robertknight@gmail.com>
3 Copyright 1997,1998 by Lars Doelle <lars.doelle@on-line.de>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 02110-1301 USA.
21 #ifndef TERMINALDISPLAY_H
22 #define TERMINALDISPLAY_H
24 // Qt
25 #include <QtGui/QColor>
26 #include <QtCore/QPointer>
27 #include <QtGui/QWidget>
29 // Konsole
30 #include "Filter.h"
31 #include "Character.h"
33 class QDrag;
34 class QDragEnterEvent;
35 class QDropEvent;
36 class QLabel;
37 class QTimer;
38 class QEvent;
39 class QFrame;
40 class QGridLayout;
41 class QKeyEvent;
42 class QScrollBar;
43 class QShowEvent;
44 class QHideEvent;
45 class QTimerEvent;
46 class QWidget;
48 class KMenu;
50 namespace Konsole
53 extern unsigned short vt100_graphics[32];
55 class ScreenWindow;
57 /**
58 * A widget which displays output from a terminal emulation and sends input keypresses and mouse activity
59 * to the terminal.
61 * When the terminal emulation receives new output from the program running in the terminal,
62 * it will update the display by calling updateImage().
64 * TODO More documentation
66 class TerminalDisplay : public QWidget
68 Q_OBJECT
70 public:
71 /** Constructs a new terminal display widget with the specified parent. */
72 TerminalDisplay(QWidget *parent=0);
73 virtual ~TerminalDisplay();
75 /** Returns the terminal color palette used by the display. */
76 const ColorEntry* colorTable() const;
77 /** Sets the terminal color palette used by the display. */
78 void setColorTable(const ColorEntry table[]);
79 /**
80 * Sets the seed used to generate random colors for the display
81 * (in color schemes that support them).
83 void setRandomSeed(uint seed);
84 /**
85 * Returns the seed used to generate random colors for the display
86 * (in color schemes that support them).
88 uint randomSeed() const;
90 /** Sets the opacity of the terminal display. */
91 void setOpacity(qreal opacity);
93 /**
94 * This enum describes the location where the scroll bar is positioned in the display widget.
96 enum ScrollBarPosition
98 /** Do not show the scroll bar. */
99 NoScrollBar=0,
100 /** Show the scroll bar on the left side of the display. */
101 ScrollBarLeft=1,
102 /** Show the scroll bar on the right side of the display. */
103 ScrollBarRight=2
105 /**
106 * Specifies whether the terminal display has a vertical scroll bar, and if so whether it
107 * is shown on the left or right side of the display.
109 void setScrollBarPosition(ScrollBarPosition position);
111 /**
112 * Sets the current position and range of the display's scroll bar.
114 * @param cursor The position of the scroll bar's thumb.
115 * @param lines The maximum value of the scroll bar.
117 void setScroll(int cursor, int lines);
119 /**
120 * Returns the display's filter chain. When the image for the display is updated,
121 * the text is passed through each filter in the chain. Each filter can define
122 * hotspots which correspond to certain strings (such as URLs or particular words).
123 * Depending on the type of the hotspots created by the filter ( returned by Filter::Hotspot::type() )
124 * the view will draw visual cues such as underlines on mouse-over for links or translucent
125 * rectangles for markers.
127 * To add a new filter to the view, call:
128 * viewWidget->filterChain()->addFilter( filterObject );
130 FilterChain* filterChain() const;
132 /**
133 * Updates the filters in the display's filter chain. This will cause
134 * the hotspots to be updated to match the current image.
136 * WARNING: This function can be expensive depending on the
137 * image size and number of filters in the filterChain()
139 * TODO - This API does not really allow efficient usage. Revise it so
140 * that the processing can be done in a better way.
142 * eg:
143 * - Area of interest may be known ( eg. mouse cursor hovering
144 * over an area )
146 void processFilters();
148 /**
149 * Returns a list of menu actions created by the filters for the content
150 * at the given @p position.
152 QList<QAction*> filterActions(const QPoint& position);
154 /** Returns true if the cursor is set to blink or false otherwise. */
155 bool blinkingCursor() { return _hasBlinkingCursor; }
156 /** Specifies whether or not the cursor blinks. */
157 void setBlinkingCursor(bool blink);
159 void setCtrlDrag(bool enable) { _ctrlDrag=enable; }
160 bool ctrlDrag() { return _ctrlDrag; }
162 /**
163 * This enum describes the methods for selecting text when
164 * the user triple-clicks within the display.
166 enum TripleClickMode
168 /** Select the whole line underneath the cursor. */
169 SelectWholeLine,
170 /** Select from the current cursor position to the end of the line. */
171 SelectForwardsFromCursor
173 /** Sets how the text is selected when the user triple clicks within the display. */
174 void setTripleClickMode(TripleClickMode mode) { _tripleClickMode = mode; }
175 /** See setTripleClickSelectionMode() */
176 TripleClickMode tripleClickMode() { return _tripleClickMode; }
178 void setLineSpacing(uint);
179 uint lineSpacing() const;
181 void emitSelection(bool useXselection,bool appendReturn);
184 * This enum describes the available shapes for the keyboard cursor.
185 * See setKeyboardCursorShape()
187 enum KeyboardCursorShape
189 /** A rectangular block which covers the entire area of the cursor character. */
190 BlockCursor,
191 /**
192 * A single flat line which occupies the space at the bottom of the cursor
193 * character's area.
195 UnderlineCursor,
196 /**
197 * An cursor shaped like the capital letter 'I', similar to the IBeam
198 * cursor used in Qt/KDE text editors.
200 IBeamCursor
202 /**
203 * Sets the shape of the keyboard cursor. This is the cursor drawn
204 * at the position in the terminal where keyboard input will appear.
206 * In addition the terminal display widget also has a cursor for
207 * the mouse pointer, which can be set using the QWidget::setCursor()
208 * method.
210 * Defaults to BlockCursor
212 void setKeyboardCursorShape(KeyboardCursorShape shape);
214 * Returns the shape of the keyboard cursor. See setKeyboardCursorShape()
216 KeyboardCursorShape keyboardCursorShape() const;
219 * Sets the color used to draw the keyboard cursor.
221 * The keyboard cursor defaults to using the foreground color of the character
222 * underneath it.
224 * @param useForegroundColor If true, the cursor color will change to match
225 * the foreground color of the character underneath it as it is moved, in this
226 * case, the @p color parameter is ignored and the color of the character
227 * under the cursor is inverted to ensure that it is still readable.
228 * @param color The color to use to draw the cursor. This is only taken into
229 * account if @p useForegroundColor is false.
231 void setKeyboardCursorColor(bool useForegroundColor , const QColor& color);
233 /**
234 * Returns the color of the keyboard cursor, or an invalid color if the keyboard
235 * cursor color is set to change according to the foreground color of the character
236 * underneath it.
238 QColor keyboardCursorColor() const;
241 * Returns the number of lines of text which can be displayed in the widget.
243 * This will depend upon the height of the widget and the current font.
244 * See fontHeight()
246 int lines() { return _lines; }
248 * Returns the number of characters of text which can be displayed on
249 * each line in the widget.
251 * This will depend upon the width of the widget and the current font.
252 * See fontWidth()
254 int columns() { return _columns; }
257 * Returns the height of the characters in the font used to draw the text in the display.
259 int fontHeight() { return _fontHeight; }
261 * Returns the width of the characters in the display.
262 * This assumes the use of a fixed-width font.
264 int fontWidth() { return _fontWidth; }
266 void setSize(int cols, int lins);
267 void setFixedSize(int cols, int lins);
269 // reimplemented
270 QSize sizeHint() const;
273 * Sets which characters, in addition to letters and numbers,
274 * are regarded as being part of a word for the purposes
275 * of selecting words in the display by double clicking on them.
277 * The word boundaries occur at the first and last characters which
278 * are either a letter, number, or a character in @p wc
280 * @param wc An array of characters which are to be considered parts
281 * of a word ( in addition to letters and numbers ).
283 void setWordCharacters(const QString& wc);
284 /**
285 * Returns the characters which are considered part of a word for the
286 * purpose of selecting words in the display with the mouse.
288 * @see setWordCharacters()
290 QString wordCharacters() { return _wordCharacters; }
292 /**
293 * Sets the type of effect used to alert the user when a 'bell' occurs in the
294 * terminal session.
296 * The terminal session can trigger the bell effect by calling bell() with
297 * the alert message.
299 void setBellMode(int mode);
300 /**
301 * Returns the type of effect used to alert the user when a 'bell' occurs in
302 * the terminal session.
304 * See setBellMode()
306 int bellMode() { return _bellMode; }
309 * This enum describes the different types of sounds and visual effects which
310 * can be used to alert the user when a 'bell' occurs in the terminal
311 * session.
313 enum BellMode
315 /** A system beep. */
316 SystemBeepBell=0,
317 /**
318 * KDE notification. This may play a sound, show a passive popup
319 * or perform some other action depending on the user's settings.
321 NotifyBell=1,
322 /** A silent, visual bell (eg. inverting the display's colors briefly) */
323 VisualBell=2,
324 /** No bell effects */
325 NoBell=3
328 void setSelection(const QString &t);
330 /**
331 * Reimplemented. Has no effect. Use setVTFont() to change the font
332 * used to draw characters in the display.
334 virtual void setFont(const QFont &);
336 /** Returns the font used to draw characters in the display */
337 QFont getVTFont() { return font(); }
339 /**
340 * Sets the font used to draw the display. Has no effect if @p font
341 * is larger than the size of the display itself.
343 void setVTFont(const QFont& font);
346 * Specified whether anti-aliasing of text in the terminal display
347 * is enabled or not. Defaults to enabled.
349 static void setAntialias( bool antialias ) { _antialiasText = antialias; }
350 /**
351 * Returns true if anti-aliasing of text in the terminal is enabled.
353 static bool antialias() { return _antialiasText; }
356 * Sets whether or not the current height and width of the
357 * terminal in lines and columns is displayed whilst the widget
358 * is being resized.
360 void setTerminalSizeHint(bool on) { _terminalSizeHint=on; }
361 /**
362 * Returns whether or not the current height and width of
363 * the terminal in lines and columns is displayed whilst the widget
364 * is being resized.
366 bool terminalSizeHint() { return _terminalSizeHint; }
367 /**
368 * Sets whether the terminal size display is shown briefly
369 * after the widget is first shown.
371 * See setTerminalSizeHint() , isTerminalSizeHint()
373 void setTerminalSizeStartup(bool on) { _terminalSizeStartup=on; }
376 * Sets the status of the BiDi rendering inside the terminal display.
377 * Defaults to disabled.
379 void setBidiEnabled(bool set) { _bidiEnabled=set; }
381 * Returns the status of the BiDi rendering in this widget.
383 bool isBidiEnabled() { return _bidiEnabled; }
386 * Sets the terminal screen section which is displayed in this widget.
387 * When updateImage() is called, the display fetches the latest character image from the
388 * the associated terminal screen window.
390 * In terms of the model-view paradigm, the ScreenWindow is the model which is rendered
391 * by the TerminalDisplay.
393 void setScreenWindow( ScreenWindow* window );
394 /** Returns the terminal screen section which is displayed in this widget. See setScreenWindow() */
395 ScreenWindow* screenWindow() const;
397 static bool HAVE_TRANSPARENCY;
399 public slots:
401 /**
402 * Causes the terminal display to fetch the latest character image from the associated
403 * terminal screen ( see setScreenWindow() ) and redraw the display.
405 void updateImage();
407 * Causes the terminal display to fetch the latest line status flags from the
408 * associated terminal screen ( see setScreenWindow() ).
410 void updateLineProperties();
412 /** Copies the selected text to the clipboard. */
413 void copyClipboard();
414 /**
415 * Pastes the content of the clipboard into the
416 * display.
418 void pasteClipboard();
420 * Pastes the content of the selection into the
421 * display.
423 void pasteSelection();
425 /**
426 * Changes whether the flow control warning box should be shown when the flow control
427 * stop key (Ctrl+S) are pressed.
429 void setFlowControlWarningEnabled(bool enabled);
430 /**
431 * Returns true if the flow control warning box is enabled.
432 * See outputSuspended() and setFlowControlWarningEnabled()
434 bool flowControlWarningEnabled() const
435 { return _flowControlWarningEnabled; }
437 /**
438 * Causes the widget to display or hide a message informing the user that terminal
439 * output has been suspended (by using the flow control key combination Ctrl+S)
441 * @param suspended True if terminal output has been suspended and the warning message should
442 * be shown or false to indicate that terminal output has been resumed and that
443 * the warning message should disappear.
445 void outputSuspended(bool suspended);
448 * Sets whether the program whoose output is being displayed in the view
449 * is interested in mouse events.
451 * If this is set to true, mouse signals will be emitted by the view when the user clicks, drags
452 * or otherwise moves the mouse inside the view.
453 * The user interaction needed to create selections will also change, and the user will be required
454 * to hold down the shift key to create a selection or perform other mouse activities inside the
455 * view area - since the program running in the terminal is being allowed to handle normal mouse
456 * events itself.
458 * @param usesMouse Set to true if the program running in the terminal is interested in mouse events
459 * or false otherwise.
461 void setUsesMouse(bool usesMouse);
463 /** See setUsesMouse() */
464 bool usesMouse() const;
466 /**
467 * Shows a notification that a bell event has occurred in the terminal.
468 * TODO: More documentation here
470 void bell(const QString& message);
472 /**
473 * Sets the background of the display to the specified color.
474 * @see setColorTable(), setForegroundColor()
476 void setBackgroundColor(const QColor& color);
478 /**
479 * Sets the text of the display to the specified color.
480 * @see setColorTable(), setBackgroundColor()
482 void setForegroundColor(const QColor& color);
484 signals:
487 * Emitted when the user presses a key whilst the terminal widget has focus.
489 void keyPressedSignal(QKeyEvent *e);
491 /**
492 * A mouse event occurred.
493 * @param button The mouse button (0 for left button, 1 for middle button, 2 for right button, 3 for release)
494 * @param column The character column where the event occurred
495 * @param line The character row where the event occurred
496 * @param eventType The type of event. 0 for a mouse press / release or 1 for mouse motion
498 void mouseSignal(int button, int column, int line, int eventType);
499 void changedFontMetricSignal(int height, int width);
500 void changedContentSizeSignal(int height, int width);
502 /**
503 * Emitted when the user right clicks on the display, or right-clicks with the Shift
504 * key held down if usesMouse() is true.
506 * This can be used to display a context menu.
508 void configureRequest(const QPoint& position);
511 * When a shortcut which is also a valid terminal key sequence is pressed while
512 * the terminal widget has focus, this signal is emitted to allow the host to decide
513 * whether the shortcut should be overridden.
514 * When the shortcut is overridden, the key sequence will be sent to the terminal emulation instead
515 * and the action associated with the shortcut will not be triggered.
517 * @p override is set to false by default and the shortcut will be triggered as normal.
519 void overrideShortcutCheck(QKeyEvent* keyEvent,bool& override);
521 void isBusySelecting(bool);
522 void sendStringToEmu(const char*);
524 protected:
525 virtual bool event( QEvent * );
527 virtual void paintEvent( QPaintEvent * );
529 virtual void showEvent(QShowEvent*);
530 virtual void hideEvent(QHideEvent*);
531 virtual void resizeEvent(QResizeEvent*);
533 virtual void fontChange(const QFont &font);
534 virtual void focusInEvent(QFocusEvent* event);
535 virtual void focusOutEvent(QFocusEvent* event);
536 virtual void keyPressEvent(QKeyEvent* event);
537 virtual void mouseDoubleClickEvent(QMouseEvent* ev);
538 virtual void mousePressEvent( QMouseEvent* );
539 virtual void mouseReleaseEvent( QMouseEvent* );
540 virtual void mouseMoveEvent( QMouseEvent* );
541 virtual void extendSelection( const QPoint& pos );
542 virtual void wheelEvent( QWheelEvent* );
544 virtual bool focusNextPrevChild( bool next );
546 // drag and drop
547 virtual void dragEnterEvent(QDragEnterEvent* event);
548 virtual void dropEvent(QDropEvent* event);
549 void doDrag();
550 enum DragState { diNone, diPending, diDragging };
552 struct _dragInfo {
553 DragState state;
554 QPoint start;
555 QDrag *dragObject;
556 } dragInfo;
558 // classifies the 'ch' into one of three categories
559 // and returns a character to indicate which category it is in
561 // - A space (returns ' ')
562 // - Part of a word (returns 'a')
563 // - Other characters (returns the input character)
564 QChar charClass(QChar ch) const;
566 void clearImage();
568 void mouseTripleClickEvent(QMouseEvent* ev);
570 // reimplemented
571 virtual void inputMethodEvent ( QInputMethodEvent* event );
572 virtual QVariant inputMethodQuery( Qt::InputMethodQuery query ) const;
574 protected slots:
576 void scrollBarPositionChanged(int value);
577 void blinkEvent();
578 void blinkCursorEvent();
580 //Renables bell noises and visuals. Used to disable further bells for a short period of time
581 //after emitting the first in a sequence of bell events.
582 void enableBell();
584 private slots:
586 void swapColorTable();
587 void tripleClickTimeout(); // resets possibleTripleClick
589 private:
591 // -- Drawing helpers --
593 // divides the part of the display specified by 'rect' into
594 // fragments according to their colors and styles and calls
595 // drawTextFragment() to draw the fragments
596 void drawContents(QPainter &paint, const QRect &rect);
597 // draws a section of text, all the text in this section
598 // has a common color and style
599 void drawTextFragment(QPainter& painter, const QRect& rect,
600 const QString& text, const Character* style);
601 // draws the background for a text fragment
602 // if useOpacitySetting is true then the color's alpha value will be set to
603 // the display's transparency (set with setOpacity()), otherwise the background
604 // will be drawn fully opaque
605 void drawBackground(QPainter& painter, const QRect& rect, const QColor& color,
606 bool useOpacitySetting);
607 // draws the cursor character
608 void drawCursor(QPainter& painter, const QRect& rect , const QColor& foregroundColor,
609 const QColor& backgroundColor , bool& invertColors);
610 // draws the characters or line graphics in a text fragment
611 void drawCharacters(QPainter& painter, const QRect& rect, const QString& text,
612 const Character* style, bool invertCharacterColor);
613 // draws a string of line graphics
614 void drawLineCharString(QPainter& painter, int x, int y,
615 const QString& str, const Character* attributes);
617 // draws the preedit string for input methods
618 void drawInputMethodPreeditString(QPainter& painter , const QRect& rect);
620 // --
622 // maps an area in the character image to an area on the widget
623 QRect imageToWidget(const QRect& imageArea) const;
625 // maps a point on the widget to the position ( ie. line and column )
626 // of the character at that point.
627 void getCharacterPosition(const QPoint& widgetPoint,int& line,int& column) const;
629 // the area where the preedit string for input methods will be draw
630 QRect preeditRect() const;
632 // shows a notification window in the middle of the widget indicating the terminal's
633 // current size in columns and lines
634 void showResizeNotification();
636 // scrolls the image by a number of lines.
637 // 'lines' may be positive ( to scroll the image down )
638 // or negative ( to scroll the image up )
639 // 'region' is the part of the image to scroll - currently only
640 // the top, bottom and height of 'region' are taken into account,
641 // the left and right are ignored.
642 void scrollImage(int lines , const QRect& region);
644 void calcGeometry();
645 void propagateSize();
646 void updateImageSize();
647 void makeImage();
649 void paintFilters(QPainter& painter);
651 // returns a region covering all of the areas of the widget which contain
652 // a hotspot
653 QRegion hotSpotRegion() const;
655 // returns the position of the cursor in columns and lines
656 QPoint cursorPosition() const;
658 // redraws the cursor
659 void updateCursor();
661 bool handleShortcutOverrideEvent(QKeyEvent* event);
663 // the window onto the terminal screen which this display
664 // is currently showing.
665 QPointer<ScreenWindow> _screenWindow;
667 bool _allowBell;
669 QGridLayout* _gridLayout;
671 bool _fixedFont; // has fixed pitch
672 int _fontHeight; // height
673 int _fontWidth; // width
674 int _fontAscent; // ascend
676 int _leftMargin; // offset
677 int _topMargin; // offset
679 int _lines; // the number of lines that can be displayed in the widget
680 int _columns; // the number of columns that can be displayed in the widget
682 int _usedLines; // the number of lines that are actually being used, this will be less
683 // than 'lines' if the character image provided with setImage() is smaller
684 // than the maximum image size which can be displayed
686 int _usedColumns; // the number of columns that are actually being used, this will be less
687 // than 'columns' if the character image provided with setImage() is smaller
688 // than the maximum image size which can be displayed
690 int _contentHeight;
691 int _contentWidth;
692 Character* _image; // [lines][columns]
693 // only the area [usedLines][usedColumns] in the image contains valid data
695 int _imageSize;
696 QVector<LineProperty> _lineProperties;
698 ColorEntry _colorTable[TABLE_COLORS];
699 uint _randomSeed;
701 bool _resizing;
702 bool _terminalSizeHint;
703 bool _terminalSizeStartup;
704 bool _bidiEnabled;
705 bool _mouseMarks;
707 QPoint _iPntSel; // initial selection point
708 QPoint _pntSel; // current selection point
709 QPoint _tripleSelBegin; // help avoid flicker
710 int _actSel; // selection state
711 bool _wordSelectionMode;
712 bool _lineSelectionMode;
713 bool _preserveLineBreaks;
714 bool _columnSelectionMode;
716 QClipboard* _clipboard;
717 QScrollBar* _scrollBar;
718 ScrollBarPosition _scrollbarLocation;
719 QString _wordCharacters;
720 int _bellMode;
722 bool _blinking; // hide text in paintEvent
723 bool _hasBlinker; // has characters to blink
724 bool _cursorBlinking; // hide cursor in paintEvent
725 bool _hasBlinkingCursor; // has blinking cursor enabled
726 bool _ctrlDrag; // require Ctrl key for drag
727 TripleClickMode _tripleClickMode;
728 bool _isFixedSize; //Columns / lines are locked.
729 QTimer* _blinkTimer; // active when hasBlinker
730 QTimer* _blinkCursorTimer; // active when hasBlinkingCursor
732 KMenu* _drop;
733 QString _dropText;
734 int _dndFileCount;
736 bool _possibleTripleClick; // is set in mouseDoubleClickEvent and deleted
737 // after QApplication::doubleClickInterval() delay
740 QLabel* _resizeWidget;
741 QTimer* _resizeTimer;
743 bool _flowControlWarningEnabled;
745 //widgets related to the warning message that appears when the user presses Ctrl+S to suspend
746 //terminal output - informing them what has happened and how to resume output
747 QLabel* _outputSuspendedLabel;
749 uint _lineSpacing;
751 bool _colorsInverted; // true during visual bell
753 QSize _size;
755 QRgb _blendColor;
757 // list of filters currently applied to the display. used for links and
758 // search highlight
759 TerminalImageFilterChain* _filterChain;
760 QRegion _mouseOverHotspotArea;
762 KeyboardCursorShape _cursorShape;
764 // custom cursor color. if this is invalid then the foreground
765 // color of the character under the cursor is used
766 QColor _cursorColor;
769 struct InputMethodData
771 QString preeditString;
772 QRect previousPreeditRect;
774 InputMethodData _inputMethodData;
776 static bool _antialiasText; // do we antialias or not
778 //the delay in milliseconds between redrawing blinking text
779 static const int BLINK_DELAY = 500;
780 static const int DEFAULT_LEFT_MARGIN = 1;
781 static const int DEFAULT_TOP_MARGIN = 1;
783 public:
784 static void setTransparencyEnabled(bool enable)
786 HAVE_TRANSPARENCY = enable;
790 class AutoScrollHandler : public QObject
792 Q_OBJECT
794 public:
795 AutoScrollHandler(QWidget* parent);
796 protected:
797 virtual void timerEvent(QTimerEvent* event);
798 virtual bool eventFilter(QObject* watched,QEvent* event);
799 private:
800 QWidget* widget() const { return static_cast<QWidget*>(parent()); }
801 int _timerId;
806 #endif // TERMINALDISPLAY_H