-- GENERATED by C->Haskell Compiler, version 0.16.0 Crystal Seed, 24 Jan 2009 (Haskell)-- Edit the ORIGNAL .chs file instead!{-# LINE 1 "./UI/NCurses.chs" #-}{-# LANGUAGE ForeignFunctionInterface #-}------------------------------------------------------------------------------- Copyright (C) 2010 John Millikin <jmillikin@gmail.com>---- This program is free software: you can redistribute it and/or modify-- it under the terms of the GNU General Public License as published by-- the Free Software Foundation, either version 3 of the License, or-- any later version.---- This program is distributed in the hope that it will be useful,-- but WITHOUT ANY WARRANTY; without even the implied warranty of-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the-- GNU General Public License for more details.---- You should have received a copy of the GNU General Public License-- along with this program. If not, see <http://www.gnu.org/licenses/>.------------------------------------------------------------------------------- |-- Module: UI.NCurses-- Copyright: 2010 John Millikin-- License: GPL-3---- Maintainer: jmillikin@gmail.com-- Portability: portable (requires FFI)-------------------------------------------------------------------------------moduleUI.NCurses(-- * Primary typesCurses,Update,Window-- * Initialization,runCurses,defaultWindow-- * Window management,newWindow,closeWindow,cloneWindow-- * Drawing to the screen,updateWindow,render,moveCursor,setColor,drawText,drawBorder,drawBox,drawLineH,drawLineV,setBackground-- * Attributes,Attribute(..),setAttribute,setAttributes-- * Colors,Color(..),ColorID,supportsColor,canDefineColor,defineColor,queryColor,defaultColorID,newColorID,setColorID,maxColorID-- * Glyphs,Glyph(..)-- ** VT100 drawing glyphs,glyphCornerUL,glyphCornerLL,glyphCornerUR,glyphCornerLR,glyphTeeL,glyphTeeR,glyphTeeB,glyphTeeT,glyphLineH,glyphLineV,glyphPlus,glyphScan1,glyphScan9,glyphDiamond,glyphStipple,glyphDegree,glyphPlusMinus,glyphBullet-- ** Teletype 5410v1 symbols,glyphArrowL,glyphArrowR,glyphArrowD,glyphArrowU,glyphBoard,glyphLantern,glyphBlock-- ** Other glyphs,glyphS3,glyphS7,glyphNE,glyphLTE,glyphGTE,glyphPi,glyphSterling-- * Event handling,Event(..),getEvent-- ** Keyboard events,Key(..)-- ** Mouse events,ButtonState(..),MouseState(..)-- * misc,setRaw,setCBreak,setEcho,baudrate,beep,flash,hasMouse,enclosed,screenSize,setTouched,setRowsTouched,setKeypad,getCursor)where-- Imports {{{importControl.Exception(bracket_)importControl.Monad(when,unless)importqualifiedControl.Monad.Trans.ReaderasRimportData.Char(chr,ord)importData.List(foldl')importData.Maybe(catMaybes)importqualifiedData.MapasMimportqualifiedData.TextasTimportUI.NCurses.TypesimportqualifiedUI.NCurses.EnumsasE-- }}}-- c2hs setup {{{importForeignhiding(shift)importForeign.C{-# LINE 162 "./UI/NCurses.chs" #-}newtypeCCharT=CCharT(Ptr(CCharT)){-# LINE 163 "./UI/NCurses.chs" #-}{-# LINE 164 "./UI/NCurses.chs" #-}typeAttrT=(CULong){-# LINE 166 "./UI/NCurses.chs" #-}typeMMaskT=(CULong){-# LINE 167 "./UI/NCurses.chs" #-}-- }}}-- Initialization {{{-- | Put the terminal in graphical mode, including enabling special keys,-- colors, and mouse events (if supported).---- After the 'Curses' block has finished running, the terminal is reset-- to text mode.runCurses::Cursesa->IOarunCurses=bracket_initCursesendwin.unCurseswhereallEvents=fromInteger(E.fromEnumE.ALL_MOUSE_EVENTS)initCurses=doinitscr{-# LINE 181 "./UI/NCurses.chs" #-}mousemaskallEventsnullPtrhasColor<-has_colors{-# LINE 183 "./UI/NCurses.chs" #-}when(hasColor==1)$dostart_color{-# LINE 185 "./UI/NCurses.chs" #-}use_default_colors{-# LINE 186 "./UI/NCurses.chs" #-}return()stdscr<-peekc_stdscrkeypad(Windowstdscr)1meta(Windowstdscr)1-- | The default window created when @ncurses@ is initialized, also known-- as @stdscr@.defaultWindow::CursesWindowdefaultWindow=Curses(Window`fmap`peekc_stdscr)foreignimportccall"static &stdscr"c_stdscr::Ptr(PtrWindow)-- }}}-- Window management {{{-- | Create a new 'Window', with the given dimensions. To create a-- fullscreen window, use @'newWindow' 0 0 0 0@.---- When the window is no longer needed, call 'closeWindow'. Windows are not-- garbage&#x2013;collected, because there&#x2019;s no way to know if-- they&#x2019;re still in use (as a background, or event source, etc).newWindow::Integer-- ^ Rows->Integer-- ^ Columns->Integer-- ^ Begin Y->Integer-- ^ Begin X->CursesWindownewWindowrowscolsxy=Curses$dowin<-newwin{-# LINE 216 "./UI/NCurses.chs" #-}(fromIntegerrows)(fromIntegercols)(fromIntegerx)(fromIntegery)ifwindowPtrwin==nullPtrthenerror"newWindow: newwin() returned NULL"elsedokeypadwin1metawin1returnwin-- | Close a window, and free all resources associated with it. Once a-- window has been closed, it is no longer safe to use.---- Note: this computation will not automatically clear the window from the-- screen.closeWindow::Window->Curses()closeWindowwin=Curses(delwinwin>>=checkRC"closeWindow")-- | Create a separate window, initialised with the state of an existing-- window.cloneWindow::Window->CursesWindowcloneWindowold=Curses$dowin<-dupwinoldifwindowPtrwin==nullPtrthenerror"cloneWindow: dupwin() returned NULL"elsereturnwin-- }}}-- Drawing to the screen {{{-- | Apply a window update to the window. After all of an-- application&#x2019;s windows have been updated, call 'render' to update-- the terminal&#x2019;s contents.updateWindow::Window->Updatea->CursesaupdateWindowwin(Updatereader)=doa<-R.runReaderTreaderwinCurses(wnoutrefreshwin>>=checkRC"updateWindow")returna-- | Re&#x2013;draw any portions of the screen which have changed since the-- last render.render::Curses()render=Curses(doupdate>>=checkRC"render")-- | Set the current foreground and background colors. See 'newColorID'-- for how to create color IDs.setColor::ColorID->Update()setColor(ColorIDpair)=withWindow_"setColor"$\win->wcolor_setwinpairnullPtr-- | Move the window&#x2019;s cursor position to the given row and column.moveCursor::Integer-- ^ Row->Integer-- ^ Column->Update()moveCursoryx=withWindow_"moveCursor"$\win->wmovewin(fromIntegery)(fromIntegerx)-- | Add some text to the window, at the current cursor position.drawText::T.Text->Update()drawTexttxt=withWindow_"drawText"$\win->withCWString(T.unpacktxt)(waddwstrwin)-- | Draw a border around the edge of the window. For any edge, passing-- 'Nothing' means to use the default glyph.drawBorder::MaybeGlyph-- ^ Left edge->MaybeGlyph-- ^ Right edge->MaybeGlyph-- ^ Top edge->MaybeGlyph-- ^ Bottom edge->MaybeGlyph-- ^ Top left corner->MaybeGlyph-- ^ Top right corner->MaybeGlyph-- ^ Bottom left corner->MaybeGlyph-- ^ Bottom right corner->Update()drawBorderleretebetltrblbr=withWindow_"drawBorder"$\win->withGlyphle$\pLE->withGlyphre$\pRE->withGlyphte$\pTE->withGlyphbe$\pBE->withGlyphtl$\pTL->withGlyphtr$\pTR->withGlyphbl$\pBL->withGlyphbr$\pBR->wborder_setwinpLEpREpTEpBEpTLpTRpBLpBR-- | @drawBox v h = drawBorder v v h h Nothing Nothing Nothing Nothing@drawBox::MaybeGlyph->MaybeGlyph->Update()drawBoxvh=drawBordervvhhNothingNothingNothingNothing-- | Draw a horizontal line from left to right, using the given glyph and-- maximum character count. The cursor position is not changed.drawLineH::MaybeGlyph->Integer->Update()drawLineHgn=withWindow_"drawLineH"$\win->withGlyphg$\pChar->whline_setwinpChar(fromIntegern)-- | Draw a vertical line from top to bottom, using the given glyph and-- maximum character count. The cursor position is not changed.drawLineV::MaybeGlyph->Integer->Update()drawLineVgn=withWindow_"drawLineV"$\win->withGlyphg$\pChar->wvline_setwinpChar(fromIntegern)-- | Set the window&#x2019;s background glyph. The glyph will be drawn in-- place of any blank characters, and the glyph&#x2019;s attributes will be-- combined with those of every character.setBackground::Glyph->Update()setBackgroundg=withWindow_"setBackground"$\win->withGlyph(Justg)$\pChar->wbkgrndsetwinpChar>>return0-- }}}-- Attributes {{{dataAttribute=AttributeStandout|AttributeUnderline|AttributeReverse|AttributeBlink|AttributeDim|AttributeBold|AttributeAltCharset|AttributeInvisible|AttributeProtectderiving(Show,Eq)attrEnum::E.Attribute->AttrTattrEnum=fromInteger.E.fromEnumattrToInt::Attribute->AttrTattrToIntx=casexofAttributeStandout->attrEnumE.WA_STANDOUTAttributeUnderline->attrEnumE.WA_UNDERLINEAttributeReverse->attrEnumE.WA_REVERSEAttributeBlink->attrEnumE.WA_BLINKAttributeDim->attrEnumE.WA_DIMAttributeBold->attrEnumE.WA_BOLDAttributeAltCharset->attrEnumE.WA_ALTCHARSETAttributeInvisible->attrEnumE.WA_INVISAttributeProtect->attrEnumE.WA_PROTECT-- | Set a single 'Attribute' on the current window. No other attributes-- are modified.setAttribute::Attribute->Bool->Update()setAttributeattron=withWindow_"setAttribute"$\win->letc=ifonthenwattr_onelsewattr_offincwin(attrToIntattr)nullPtr-- | Set all 'Attribute's at once on the current window. Any attributes not-- included in the list will be unset.setAttributes::[Attribute]->Update()setAttributesattrs=withWindow_"setAttributes"$\win->letcint=foldl'(\acca->acc.|.attrToInta)0attrsinalloca$\pPair->dowattr_getwinnullPtrpPairnullPtr>>=checkRC"setAttributes"colorPair<-peekpPairwattr_setwincintcolorPairnullPtr-- }}}-- Colors {{{dataColor=ColorBlack|ColorRed|ColorGreen|ColorYellow|ColorBlue|ColorMagenta|ColorCyan|ColorWhitederiving(Show,Eq)-- | A wrapper around 'Integer' to ensure clients don&#x2019;t use an-- uninitialized color in an attribute.newtypeColorID=ColorIDCShortderiving(Show,Eq)colorEnum::E.Color->CShortcolorEnum=fromInteger.E.fromEnumcolorToShort::Color->CShortcolorToShortx=casexofColorBlack->colorEnumE.COLOR_BLACKColorRed->colorEnumE.COLOR_REDColorGreen->colorEnumE.COLOR_GREENColorYellow->colorEnumE.COLOR_YELLOWColorBlue->colorEnumE.COLOR_BLUEColorMagenta->colorEnumE.COLOR_MAGENTAColorCyan->colorEnumE.COLOR_CYANColorWhite->colorEnumE.COLOR_WHITE-- | Check if the terminal supports color. If it doesn&#x2019;t,-- alternative indicators (such as underlines or bold) should be used.supportsColor::CursesBoolsupportsColor=Curses(fmapcToBoolhas_colors)-- | Check if the terminal supports changing color defintiions.canDefineColor::CursesBoolcanDefineColor=Curses(fmapcToBoolcan_change_color)-- | Change the definition of an existing color. Use 'canDefineColor' to-- determine whether changing color values is possible.defineColor::Color->Integer-- ^ Red (0 &#x2013; 1000)->Integer-- ^ Green (0 &#x2013; 1000)->Integer-- ^ Blue (0 &#x2013; 1000)->Curses()defineColorcrgb=Curses$dorc<-init_color{-# LINE 429 "./UI/NCurses.chs" #-}(colorToShortc)(fromIntegerr)(fromIntegerg)(fromIntegerb)checkRC"defineColor"rc-- | Query the current definition of the given color (see 'defineColor').-- The returned tuple is (red, green, blue), with values 0 &#x2013; 1000.queryColor::Color->Curses(Integer,Integer,Integer)queryColorc=Curses$alloca$\pRed->alloca$\pGreen->alloca$\pBlue->dorc<-color_content(colorToShortc)pRedpGreenpBluecheckRC"queryColor"rcred<-fmaptoInteger(peekpRed)green<-fmaptoInteger(peekpGreen)blue<-fmaptoInteger(peekpBlue)return(red,green,blue)-- | The default color IDdefaultColorID::ColorIDdefaultColorID=ColorID0-- | Assign a new 'ColorID' to some (foreground, background) color pair.-- The user may pick which color ID is assigned, but it must be valid. Use-- 'maxColorID' to determine how many colors the current terminal supports.newColorID::Color-- ^ Foreground->Color-- ^ Background->Integer-- ^ A value /n/, such that-- (0 < /n/ &#x2264; 'maxColorID')->CursesColorIDnewColorIDfgbgn=Curses$dounless(n>0)$error"newColorID: n must be > 0"maxColor<-unCursesmaxColorIDunless(n<=maxColor)$error"newColorID: n must be <= maxColorID"checkRC"newColorID"=<<init_pair{-# LINE 466 "./UI/NCurses.chs" #-}(fromIntegern)(colorToShortfg)(colorToShortbg)return(ColorID(fromIntegern))-- Change the definition of an existing 'ColorID'setColorID::Color-- ^ Foreground->Color-- ^ Background->ColorID-- ^ The 'ColorID' to change->Curses()setColorIDfgbg(ColorIDn)=Curses$checkRC"setColorID"=<<init_pairn(colorToShortfg)(colorToShortbg)-- | Get the maximum color ID supported by the current terminalmaxColorID::CursesIntegermaxColorID=Curses$dopairs<-toInteger`fmap`peekc_COLOR_PAIRSreturn(pairs-1)foreignimportccall"static &COLOR_PAIRS"c_COLOR_PAIRS::PtrCInt-- }}}-- Glyphs {{{-- | A glyph is a character, typically spacing, combined with a set of-- attributes.dataGlyph=Glyph{glyphCharacter::Char,glyphAttributes::[Attribute]}deriving(Show,Eq)withGlyph::MaybeGlyph->(CCharT->IOa)->IOawithGlyphNothingio=io(CCharTnullPtr)withGlyph(Just(Glyphcharattrs))io=letcAttrs=foldl'(\acca->acc.|.attrToInta)0attrsinallocaBytes24$\pBuf->domemset(castPtrpBuf)024{-# LINE 509 "./UI/NCurses.chs" #-}(\ptrval->do{pokeByteOffptr0(val::CULong)})pBufcAttrs(\ptrval->do{pokeByteOffptr4(val::(CWString))})pBuf(wordPtrToPtr(fromIntegral(ordchar)))io(CCharTpBuf)-- VT100 drawing glyphs {{{-- | Upper left cornerglyphCornerUL::GlyphglyphCornerUL=Glyph'\x250C'[]-- | Lower left cornerglyphCornerLL::GlyphglyphCornerLL=Glyph'\x2514'[]-- | Upper right cornerglyphCornerUR::GlyphglyphCornerUR=Glyph'\x2510'[]-- | Lower right cornerglyphCornerLR::GlyphglyphCornerLR=Glyph'\x2518'[]-- | Tee pointing rightglyphTeeL::GlyphglyphTeeL=Glyph'\x251C'[]-- | Tee pointing leftglyphTeeR::GlyphglyphTeeR=Glyph'\x2524'[]-- | Tee pointing upglyphTeeB::GlyphglyphTeeB=Glyph'\x2534'[]-- | Tee pointing downglyphTeeT::GlyphglyphTeeT=Glyph'\x252C'[]-- | Horizontal lineglyphLineH::GlyphglyphLineH=Glyph'\x2500'[]-- | Vertical lineglyphLineV::GlyphglyphLineV=Glyph'\x2502'[]-- | Large plus or crossoverglyphPlus::GlyphglyphPlus=Glyph'\x253C'[]-- | Scan line 1glyphScan1::GlyphglyphScan1=Glyph'\x23BA'[]-- | Scan line 9glyphScan9::GlyphglyphScan9=Glyph'\x23BD'[]-- | DiamondglyphDiamond::GlyphglyphDiamond=Glyph'\x25C6'[]-- | Stipple, or checker boardglyphStipple::GlyphglyphStipple=Glyph'\x2592'[]-- | Degree symbolglyphDegree::GlyphglyphDegree=Glyph'\xb0'[]-- | Plus/minusglyphPlusMinus::GlyphglyphPlusMinus=Glyph'\xb1'[]-- | BulletglyphBullet::GlyphglyphBullet=Glyph'\xb7'[]-- }}}-- Teletype 5410v1 symbols {{{-- | Arrow pointing leftglyphArrowL::GlyphglyphArrowL=Glyph'\x2190'[]-- | Arrow pointing rightglyphArrowR::GlyphglyphArrowR=Glyph'\x2192'[]-- | Arrow pointing downglyphArrowD::GlyphglyphArrowD=Glyph'\x2193'[]-- | Arrow pointing upglyphArrowU::GlyphglyphArrowU=Glyph'\x2191'[]-- | Board of squaresglyphBoard::GlyphglyphBoard=Glyph'\x2592'[]-- | Lantern symbolglyphLantern::GlyphglyphLantern=Glyph'\x2603'[]-- | Solid square blockglyphBlock::GlyphglyphBlock=Glyph'\x25AE'[]-- }}}-- Other glyphs {{{-- | Scan line 3glyphS3::GlyphglyphS3=Glyph'\x23BB'[]-- | Scan line 7glyphS7::GlyphglyphS7=Glyph'\x23BC'[]-- | Not equalglyphNE::GlyphglyphNE=Glyph'\x2260'[]-- | Less than or equalglyphLTE::GlyphglyphLTE=Glyph'\x2264'[]-- | Greater than or equalglyphGTE::GlyphglyphGTE=Glyph'\x2265'[]-- | PiglyphPi::GlyphglyphPi=Glyph'\x3c0'[]-- | UK pounds sterling symbolglyphSterling::GlyphglyphSterling=Glyph'\xa3'[]-- }}}-- }}}-- Event handling {{{dataEvent=EventCharacterChar|EventSpecialKeyKey|EventMouseIntegerMouseState|EventResized|EventUnknownIntegerderiving(Show,Eq)-- | Get the next 'Event' from a given window. This blocks until an event-- is received.getEvent::Window->CursesEventgetEventwin=Cursesiowhereio=alloca$\ptr->dorc<-wget_wchwinptrcheckRC"getEvent"rccode<-toInteger`fmap`peekptrifrc==0thenreturn(charEventcode)elseifcode==E.fromEnumE.KEY_MOUSEthenmouseEventelseifcode==E.fromEnumE.KEY_RESIZEthenreturnEventResizedelsekeyEventcodecharEvent=EventCharacter.chr.fromIntegermouseEvent=allocaBytes20$\pEv->dogetmousepEv>>=checkRC"getEvent"evID<-fmaptoInteger((\ptr->do{peekByteOffptr0::IOCShort})pEv)x<-fmaptoInteger((\ptr->do{peekByteOffptr4::IOCInt})pEv)y<-fmaptoInteger((\ptr->do{peekByteOffptr8::IOCInt})pEv)z<-fmaptoInteger((\ptr->do{peekByteOffptr12::IOCInt})pEv)mask<-(\ptr->do{peekByteOffptr16::IOCULong})pEvletstate=parseMouseStatemaskreturn(EventMouseevID(state{mouseCoordinates=(x,y,z)}))codeF0=E.fromEnumE.KEY_F0codeF64=codeF0+64keyEventcode=return$ifcode>=codeF0&&code<=codeF64thenEventSpecialKey(KeyFunction(code-codeF0))elsecaseM.lookupcodekeyMapofJustkey->EventSpecialKeykeyNothing->EventUnknowncode-- Keyboard events {{{dataKey=KeyUpArrow|KeyDownArrow|KeyLeftArrow|KeyRightArrow|KeyHome|KeyBackspace|KeyFunctionInteger-- ^ Function keys, F0 &#x2013; F64|KeyDeleteLine|KeyInsertLine|KeyDeleteCharacter|KeyInsertCharacter|KeyEIC-- ^ Sent by rmir or smir in insert mode|KeyClear-- ^ Clear screen|KeyEOS-- ^ Clear to end of screen|KeyEOL-- ^ Clear to end of line|KeyScrollForward|KeyScrollBackward|KeyNextPage|KeyPreviousPage|KeySetTab|KeyClearTab|KeyClearAllTabs|KeyEnter|KeyPrint|KeyHomeDown|KeyA1-- ^ Upper left of keypad|KeyA3-- ^ Upper right of keypad|KeyB2-- ^ Center of keypad|KeyC1-- ^ Lower left of keypad|KeyC3-- ^ Lower right of keypad|KeyBackTab|KeyBegin|KeyCancel|KeyClose|KeyCommand|KeyCopy|KeyCreate|KeyEnd|KeyExit|KeyFind|KeyHelp|KeyMark|KeyMessage|KeyMove|KeyNext|KeyOpen|KeyOptions|KeyPrevious|KeyRedo|KeyReference|KeyRefresh|KeyReplace|KeyRestart|KeyResume|KeySave|KeyShiftedBegin|KeyShiftedCancel|KeyShiftedCommand|KeyShiftedCopy|KeyShiftedCreate|KeyShiftedDeleteCharacter|KeyShiftedDeleteLine|KeySelect|KeyShiftedEnd|KeyShiftedEOL|KeyShiftedExit|KeyShiftedFind|KeyShiftedHelp|KeyShiftedHome|KeyShiftedInsertCharacter|KeyShiftedLeftArrow|KeyShiftedMessage|KeyShiftedMove|KeyShiftedNext|KeyShiftedOptions|KeyShiftedPrevious|KeyShiftedPrint|KeyShiftedRedo|KeyShiftedReplace|KeyShiftedRightArrow|KeyShiftedResume|KeyShiftedSave|KeyShiftedSuspend|KeyShiftedUndo|KeySuspend|KeyUndoderiving(Show,Eq)keyMap::M.MapIntegerKeykeyMap=M.fromList$map(\(enum,key)->(E.fromEnumenum,key))[(E.KEY_DOWN,KeyDownArrow),(E.KEY_UP,KeyUpArrow),(E.KEY_LEFT,KeyLeftArrow),(E.KEY_RIGHT,KeyRightArrow),(E.KEY_HOME,KeyHome),(E.KEY_BACKSPACE,KeyBackspace),(E.KEY_DL,KeyDeleteLine),(E.KEY_IL,KeyInsertLine),(E.KEY_DC,KeyDeleteCharacter),(E.KEY_IC,KeyInsertCharacter),(E.KEY_EIC,KeyEIC),(E.KEY_CLEAR,KeyClear),(E.KEY_EOS,KeyEOS),(E.KEY_EOL,KeyEOL),(E.KEY_SF,KeyScrollForward),(E.KEY_SR,KeyScrollBackward),(E.KEY_NPAGE,KeyNextPage),(E.KEY_PPAGE,KeyPreviousPage),(E.KEY_STAB,KeySetTab),(E.KEY_CTAB,KeyClearTab),(E.KEY_CATAB,KeyClearAllTabs),(E.KEY_ENTER,KeyEnter),(E.KEY_PRINT,KeyPrint),(E.KEY_LL,KeyHomeDown),(E.KEY_A1,KeyA1),(E.KEY_A3,KeyA3),(E.KEY_B2,KeyB2),(E.KEY_C1,KeyC1),(E.KEY_C3,KeyC3),(E.KEY_BTAB,KeyBackTab),(E.KEY_BEG,KeyBegin),(E.KEY_CANCEL,KeyCancel),(E.KEY_CLOSE,KeyClose),(E.KEY_COMMAND,KeyCommand),(E.KEY_COPY,KeyCopy),(E.KEY_CREATE,KeyCreate),(E.KEY_END,KeyEnd),(E.KEY_EXIT,KeyExit),(E.KEY_FIND,KeyFind),(E.KEY_HELP,KeyHelp),(E.KEY_MARK,KeyMark),(E.KEY_MESSAGE,KeyMessage),(E.KEY_MOVE,KeyMove),(E.KEY_NEXT,KeyNext),(E.KEY_OPEN,KeyOpen),(E.KEY_OPTIONS,KeyOptions),(E.KEY_PREVIOUS,KeyPrevious),(E.KEY_REDO,KeyRedo),(E.KEY_REFERENCE,KeyReference),(E.KEY_REFRESH,KeyRefresh),(E.KEY_REPLACE,KeyReplace),(E.KEY_RESTART,KeyRestart),(E.KEY_RESUME,KeyResume),(E.KEY_SAVE,KeySave),(E.KEY_SBEG,KeyShiftedBegin),(E.KEY_SCANCEL,KeyShiftedCancel),(E.KEY_SCOMMAND,KeyShiftedCommand),(E.KEY_SCOPY,KeyShiftedCopy),(E.KEY_SCREATE,KeyShiftedCreate),(E.KEY_SDC,KeyShiftedDeleteCharacter),(E.KEY_SDL,KeyShiftedDeleteLine),(E.KEY_SELECT,KeySelect),(E.KEY_SEND,KeyShiftedEnd),(E.KEY_SEOL,KeyShiftedEOL),(E.KEY_SEXIT,KeyShiftedExit),(E.KEY_SFIND,KeyShiftedFind),(E.KEY_SHELP,KeyShiftedHelp),(E.KEY_SHOME,KeyShiftedHome),(E.KEY_SIC,KeyShiftedInsertCharacter),(E.KEY_SLEFT,KeyShiftedLeftArrow),(E.KEY_SMESSAGE,KeyShiftedMessage),(E.KEY_SMOVE,KeyShiftedMove),(E.KEY_SNEXT,KeyShiftedNext),(E.KEY_SOPTIONS,KeyShiftedOptions),(E.KEY_SPREVIOUS,KeyShiftedPrevious),(E.KEY_SPRINT,KeyShiftedPrint),(E.KEY_SREDO,KeyShiftedRedo),(E.KEY_SREPLACE,KeyShiftedReplace),(E.KEY_SRIGHT,KeyShiftedRightArrow),(E.KEY_SRSUME,KeyShiftedResume),(E.KEY_SSAVE,KeyShiftedSave),(E.KEY_SSUSPEND,KeyShiftedSuspend),(E.KEY_SUNDO,KeyShiftedUndo),(E.KEY_SUSPEND,KeySuspend),(E.KEY_UNDO,KeyUndo)]-- }}}-- Mouse events {{{dataButtonState=ButtonPressed|ButtonReleased|ButtonClicked|ButtonDoubleClicked|ButtonTripleClickedderiving(Show,Eq)dataMouseState=MouseState{mouseCoordinates::(Integer,Integer,Integer)-- ^ (X, Y, Z)-- | If the mouse event was caused by a change in button state,-- the buttons and their new state will be listed here.,mouseButtons::[(Integer,ButtonState)],mouseAlt::Bool,mouseShift::Bool,mouseControl::Bool}deriving(Show,Eq)parseMouseState::MMaskT->MouseStateparseMouseStatemask=MouseState(0,0,0)buttonsaltshiftctrlwheremaskI=toIntegermaskteste=(maskI.&.(E.fromEnume))>0alt=testE.BUTTON_ALTshift=testE.BUTTON_SHIFTctrl=testE.BUTTON_CTRLbuttons=catMaybes[button1,button2,button3,button4,button5]testButtonidxrpcdctc|testr=Just(idx,ButtonReleased)|testp=Just(idx,ButtonPressed)|testc=Just(idx,ButtonClicked)|testdc=Just(idx,ButtonDoubleClicked)|testtc=Just(idx,ButtonTripleClicked)|otherwise=Nothingbutton1=testButton1E.BUTTON1_RELEASEDE.BUTTON1_PRESSEDE.BUTTON1_CLICKEDE.BUTTON1_DOUBLE_CLICKEDE.BUTTON1_TRIPLE_CLICKEDbutton2=testButton2E.BUTTON2_RELEASEDE.BUTTON2_PRESSEDE.BUTTON2_CLICKEDE.BUTTON2_DOUBLE_CLICKEDE.BUTTON2_TRIPLE_CLICKEDbutton3=testButton3E.BUTTON3_RELEASEDE.BUTTON3_PRESSEDE.BUTTON3_CLICKEDE.BUTTON3_DOUBLE_CLICKEDE.BUTTON3_TRIPLE_CLICKEDbutton4=testButton4E.BUTTON4_RELEASEDE.BUTTON4_PRESSEDE.BUTTON4_CLICKEDE.BUTTON4_DOUBLE_CLICKEDE.BUTTON4_TRIPLE_CLICKEDbutton5=Nothing-- }}}-- }}}-- misc {{{-- | Runs @raw()@ or @noraw()@setRaw::Bool->Curses()setRawset=Curses(io>>=checkRC"setRaw")whereio=ifsetthenrawelsenoraw{-# LINE 972 "./UI/NCurses.chs" #-}-- | Runs @cbreak()@ or @nocbreak()@setCBreak::Bool->Curses()setCBreakset=Curses(io>>=checkRC"setCBreak")whereio=ifsetthencbreakelsenocbreak{-# LINE 977 "./UI/NCurses.chs" #-}-- | Runs @echo()@ or @noecho()@setEcho::Bool->Curses()setEchoset=Curses(io>>=checkRC"setEcho")whereio=ifsetthenechoelsenoecho{-# LINE 982 "./UI/NCurses.chs" #-}-- | Get the output speed of the current terminal, in bits per second.baudrate::CursesIntegerbaudrate=Curses$dorc<-c_baudrate{-# LINE 987 "./UI/NCurses.chs" #-}checkRC"baudrate"rcreturn(toIntegerrc)beep::Curses()beep=Curses(c_beep>>=checkRC"beep")flash::Curses()flash=Curses(c_flash>>=checkRC"flash")-- | Check if the terminal has a mousehasMouse::CursesBoolhasMouse=Curses(fmapcToBoolhas_mouse)-- | Check if some position is contained within the given 'Window'.enclosed::Window->Integer-- ^ Row->Integer-- ^ Column->CursesBoolenclosedwinyx=Curses.fmapcToBool$wenclosewin(fromIntegery)(fromIntegerx)-- | Return (rows, columns) of current screenscreenSize::Curses(Integer,Integer)screenSize=Curses$dorows<-peekc_LINEScols<-peekc_COLSreturn(toIntegerrows,toIntegercols)foreignimportccall"static &LINES"c_LINES::PtrCIntforeignimportccall"static &COLS"c_COLS::PtrCInt-- | Set whether the entire window has been &#x201C;touched&#x201D;;-- touched characters are redrawn on the next refresh.setTouched::Bool->Update()setTouchedtouched=withWindow_"setTouched"$iftouchedthentouchwin{-# LINE 1026 "./UI/NCurses.chs" #-}elseuntouchwin{-# LINE 1027 "./UI/NCurses.chs" #-}-- | Set whether particular rows in the window have been-- &#x201C;touched&#x201D;.setRowsTouched::Bool->Integer-- ^ Start->Integer-- ^ Count->Update()setRowsTouchedtouchedstartcount=withWindow_"setRowsTouched"$\win->wtouchlnwin(fromIntegerstart)(fromIntegercount)(cFromBooltouched)-- | Enable/disable support for special keys.setKeypad::Window->Bool->Curses()setKeypadwinset=Curses(io>>=checkRC"setKeypad")whereio=keypadwin(cFromBoolset)getCursor::Window->Curses(Integer,Integer)getCursorwin=Curses$dorow<-getcurywincol<-getcurxwinreturn(toIntegerrow,toIntegercol)-- }}}-- Utility {{{withWindow::(Window->IOa)->UpdateawithWindowio=Update(R.ReaderT(\win->Curses(iowin)))withWindow_::String->(Window->IOCInt)->Update()withWindow_nameio=withWindow$\win->iowin>>=checkRCname-- }}}foreignimportccallsafe"UI/NCurses.chs.h endwin"endwin::(IOCInt)foreignimportccallsafe"UI/NCurses.chs.h initscr"initscr::(IO(Window))foreignimportccallsafe"UI/NCurses.chs.h mousemask"mousemask::(CULong->((PtrCULong)->(IOCULong)))foreignimportccallsafe"UI/NCurses.chs.h has_colors"has_colors::(IOCUChar)foreignimportccallsafe"UI/NCurses.chs.h start_color"start_color::(IOCInt)foreignimportccallsafe"UI/NCurses.chs.h use_default_colors"use_default_colors::(IOCInt)foreignimportccallsafe"UI/NCurses.chs.h keypad"keypad::((Window)->(CUChar->(IOCInt)))foreignimportccallsafe"UI/NCurses.chs.h meta"meta::((Window)->(CUChar->(IOCInt)))foreignimportccallsafe"UI/NCurses.chs.h newwin"newwin::(CInt->(CInt->(CInt->(CInt->(IO(Window))))))foreignimportccallsafe"UI/NCurses.chs.h delwin"delwin::((Window)->(IOCInt))foreignimportccallsafe"UI/NCurses.chs.h dupwin"dupwin::((Window)->(IO(Window)))foreignimportccallsafe"UI/NCurses.chs.h wnoutrefresh"wnoutrefresh::((Window)->(IOCInt))foreignimportccallsafe"UI/NCurses.chs.h doupdate"doupdate::(IOCInt)foreignimportccallsafe"UI/NCurses.chs.h wcolor_set"wcolor_set::((Window)->(CShort->((Ptr())->(IOCInt))))foreignimportccallsafe"UI/NCurses.chs.h wmove"wmove::((Window)->(CInt->(CInt->(IOCInt))))foreignimportccallsafe"UI/NCurses.chs.h waddwstr"waddwstr::((Window)->((CWString)->(IOCInt)))foreignimportccallsafe"UI/NCurses.chs.h wborder_set"wborder_set::((Window)->((CCharT)->((CCharT)->((CCharT)->((CCharT)->((CCharT)->((CCharT)->((CCharT)->((CCharT)->(IOCInt))))))))))foreignimportccallsafe"UI/NCurses.chs.h whline_set"whline_set::((Window)->((CCharT)->(CInt->(IOCInt))))foreignimportccallsafe"UI/NCurses.chs.h wvline_set"wvline_set::((Window)->((CCharT)->(CInt->(IOCInt))))foreignimportccallsafe"UI/NCurses.chs.h wbkgrndset"wbkgrndset::((Window)->((CCharT)->(IO())))foreignimportccallsafe"UI/NCurses.chs.h wattr_on"wattr_on::((Window)->(CULong->((Ptr())->(IOCInt))))foreignimportccallsafe"UI/NCurses.chs.h wattr_off"wattr_off::((Window)->(CULong->((Ptr())->(IOCInt))))foreignimportccallsafe"UI/NCurses.chs.h wattr_get"wattr_get::((Window)->((PtrCULong)->((PtrCShort)->((Ptr())->(IOCInt)))))foreignimportccallsafe"UI/NCurses.chs.h wattr_set"wattr_set::((Window)->(CULong->(CShort->((Ptr())->(IOCInt)))))foreignimportccallsafe"UI/NCurses.chs.h can_change_color"can_change_color::(IOCUChar)foreignimportccallsafe"UI/NCurses.chs.h init_color"init_color::(CShort->(CShort->(CShort->(CShort->(IOCInt)))))foreignimportccallsafe"UI/NCurses.chs.h color_content"color_content::(CShort->((PtrCShort)->((PtrCShort)->((PtrCShort)->(IOCInt)))))foreignimportccallsafe"UI/NCurses.chs.h init_pair"init_pair::(CShort->(CShort->(CShort->(IOCInt))))foreignimportccallsafe"UI/NCurses.chs.h memset"memset::((Ptr())->(CInt->(CUInt->(IO(Ptr())))))foreignimportccallsafe"UI/NCurses.chs.h wget_wch"wget_wch::((Window)->((PtrCUInt)->(IOCInt)))foreignimportccallsafe"UI/NCurses.chs.h getmouse"getmouse::((Ptr())->(IOCInt))foreignimportccallsafe"UI/NCurses.chs.h raw"raw::(IOCInt)foreignimportccallsafe"UI/NCurses.chs.h noraw"noraw::(IOCInt)foreignimportccallsafe"UI/NCurses.chs.h cbreak"cbreak::(IOCInt)foreignimportccallsafe"UI/NCurses.chs.h nocbreak"nocbreak::(IOCInt)foreignimportccallsafe"UI/NCurses.chs.h echo"echo::(IOCInt)foreignimportccallsafe"UI/NCurses.chs.h noecho"noecho::(IOCInt)foreignimportccallsafe"UI/NCurses.chs.h baudrate"c_baudrate::(IOCInt)foreignimportccallsafe"UI/NCurses.chs.h beep"c_beep::(IOCInt)foreignimportccallsafe"UI/NCurses.chs.h flash"c_flash::(IOCInt)foreignimportccallsafe"UI/NCurses.chs.h has_mouse"has_mouse::(IOCUChar)foreignimportccallsafe"UI/NCurses.chs.h wenclose"wenclose::((Window)->(CInt->(CInt->(IOCUChar))))foreignimportccallsafe"UI/NCurses.chs.h touchwin"touchwin::((Window)->(IOCInt))foreignimportccallsafe"UI/NCurses.chs.h untouchwin"untouchwin::((Window)->(IOCInt))foreignimportccallsafe"UI/NCurses.chs.h wtouchln"wtouchln::((Window)->(CInt->(CInt->(CInt->(IOCInt)))))foreignimportccallsafe"UI/NCurses.chs.h getcury"getcury::((Window)->(IOCInt))foreignimportccallsafe"UI/NCurses.chs.h getcurx"getcurx::((Window)->(IOCInt))