[Haskell-cafe] Re: Read Instance code.
Andy Stewart
lazycat.manatee at gmail.com
Sat Jul 3 07:39:01 EDT 2010
Ivan Lazar Miljenovic <ivan.miljenovic at gmail.com> writes:
> Andy Stewart <lazycat.manatee at gmail.com> writes:
>
>> Hi all,
>>
>> I have some incorrect "Read instance" make i got error "Prelude.read: no
>> parse", and i don't know how to fix it.
>>
>>
>> newtype SerializedWindow = SerializedWindow (Maybe DrawWindow)
>>
>> instance Show SerializedWindow where
>> show _ = "SerializedWindow Nothing"
>>
>> instance Read SerializedWindow where
>> readsPrec _ str = [(SerializedWindow Nothing, idStr)
>> | (val :: String, idStr) <- reads str]
>
> Try using Derive or DrIFT to generate a proto-typical instance for you,
> and then hack that and make it neater. If you don't care about
> cross-compiler compatability, using ReadP rather than ReadS also results
> in nicer parsing code.
Sorry, i haven't explain my situation.
I'm try to serialized/derserialized Gtk+ Event C struct over the network.
Since DrawWindow is ForeignPtr to point C structure, and "deriving Read"
nothing help.
So i want build a "bogus value" -- "SerializedWindow Nothing" to fill
DrawWindow pointer field.
I just want got "SerializedWindow Nothing" and don't care the value
that return by *reads*.
Below are C struct that i want to serialized with Haskell data-type:
typedef struct {
GdkEventType type;
GdkWindow *window;
gint8 send_event;
guint32 time;
guint state;
guint keyval;
gint length;
gchar *string;
guint16 hardware_keycode;
guint8 group;
guint is_modifier : 1;
} GdkEventKey;
Below are my C binding that explain my purpose:
------------------------------> C binding start <------------------------------
{-# LANGUAGE ScopedTypeVariables #-}
-- -*-haskell-*-
#include <gtk/gtk.h>
#include "template-hsc-gtk2hs.h"
-- GIMP Toolkit (GTK) GDK Serializabled Event
--
-- Author : Andy Stewart
--
-- Created: 01 Jul 2010
--
-- Copyright (C) 2010 Andy Stewart
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2.1 of the License, or (at your option) any later version.
--
-- This library 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
-- Lesser General Public License for more details.
--
-- |
-- Maintainer : gtk2hs-users\@lists.sourceforge.net
-- Stability : deprecated
-- Portability : portable (depends on GHC)
--
module Graphics.UI.Gtk.Gdk.SerializedEvent (
-- * Types
SerializedEventKey (..),
-- * Methods
serializedEvent,
deserializeEventKey,
) where
import Control.Monad.Reader (ReaderT, ask, runReaderT )
import Control.Monad.Trans (liftIO)
import Data.Maybe
import Data.Ord
import Graphics.UI.Gtk.Gdk.DrawWindow
import Graphics.UI.Gtk.Gdk.EventM
import Graphics.UI.Gtk.Gdk.Keys (KeyVal)
import Graphics.UI.GtkInternals
import System.Glib.FFI
import System.Glib.Flags
data SerializedEventKey =
SerializedEventKey {sEventType :: Int
,sEventWindow :: SerializedWindow
,sEventSent :: Bool
,sEventTime :: Word32
,sEventState :: Int
,sEventKeyval :: KeyVal
,sEventLength :: Int
,sEventString :: String
,sEventKeycode :: Word16
,sEventGroup :: Word8
,sEventIsModifier:: Int}
deriving (Show, Eq, Ord, Read)
newtype SerializedWindow = SerializedWindow (Maybe DrawWindow)
instance Eq SerializedWindow where
(==) _ _ = True
instance Ord SerializedWindow where
compare _ _ = EQ
instance Show SerializedWindow where
show _ = "SerializedWindow Nothing"
instance Read SerializedWindow where
readsPrec _ str = [(SerializedWindow Nothing, idStr)
| (val :: String, idStr) <- reads str]
instance Storable SerializedEventKey where
sizeOf _ = #{const sizeof (GdkEventKey)}
alignment _ = alignment (undefined:: #gtk2hs_type gint)
peek ptr = peekSerializedKey ptr
poke ptr event = pokeSerializedKey ptr event
serializedEvent :: EventM t SerializedEventKey
serializedEvent = do
ptr <- ask
eType <- liftIO $ do
(typ::#gtk2hs_type GdkEventType) <- #{peek GdkEventAny,type} ptr
return typ
case eType of
#{const GDK_KEY_PRESS} -> serializedKey
#{const GDK_KEY_RELEASE} -> serializedKey
ty -> error ("serializedEvent: haven't handle event type " ++ show ty)
serializedKey :: EventM t SerializedEventKey
serializedKey = do
ptr <- ask
liftIO $ peekSerializedKey ptr
peekSerializedKey ptr = do
(typ_ ::#gtk2hs_type GdkEventType) <- #{peek GdkEventKey, type} ptr
(sent_ ::#gtk2hs_type gint8) <- #{peek GdkEventKey, send_event} ptr
(time_ ::#gtk2hs_type guint32) <- #{peek GdkEventKey, time} ptr
(state_ ::#gtk2hs_type guint) <- #{peek GdkEventKey, state} ptr
(keyval_ ::#gtk2hs_type guint) <- #{peek GdkEventKey, keyval} ptr
(length_ ::#gtk2hs_type gint) <- #{peek GdkEventKey, length} ptr
(keycode_ ::#gtk2hs_type guint16) <- #{peek GdkEventKey, hardware_keycode} ptr
(group_ ::#gtk2hs_type guint8) <- #{peek GdkEventKey, group} ptr
-- (isModifier_ ::#gtk2hs_type guint) <- #{peek GdkEventKey, is_modifier} ptr
return $ SerializedEventKey
{sEventType = fromIntegral typ_
,sEventWindow = SerializedWindow Nothing -- this field need synthesize at client side
,sEventSent = toBool sent_
,sEventTime = fromIntegral time_ -- this field need synthesize at client side
,sEventState = fromIntegral state_
,sEventKeyval = keyval_
,sEventLength = fromIntegral length_
,sEventString = "" -- this filed has deprecated and should never be used
,sEventKeycode = keycode_
,sEventGroup = group_
-- ,sEventIsModifier = isModifier_
,sEventIsModifier = 0
}
pokeSerializedKey ptr (SerializedEventKey
{sEventType = typ_
,sEventWindow = SerializedWindow window_
,sEventSent = sent_
,sEventTime = time_
,sEventState = state_
,sEventKeyval = keyval_
,sEventLength = length_
,sEventString = string_
,sEventKeycode = keycode_
,sEventGroup = group_
,sEventIsModifier = isModifier_
}) = do
#{poke GdkEventKey, type} ptr ((fromIntegral typ_) ::#gtk2hs_type GdkEventType)
case (fromMaybe (DrawWindow nullForeignPtr) window_) of
win_ -> withForeignPtr (unDrawWindow win_) $ \winPtr ->
#{poke GdkEventKey, window} ptr winPtr
#{poke GdkEventKey, send_event} ptr ((fromBool sent_) ::#gtk2hs_type gint8)
#{poke GdkEventKey, time} ptr ((fromIntegral time_) ::#gtk2hs_type guint32)
#{poke GdkEventKey, state} ptr ((fromIntegral state_) ::#gtk2hs_type guint)
#{poke GdkEventKey, keyval} ptr (keyval_ ::#gtk2hs_type guint)
#{poke GdkEventKey, length} ptr ((fromIntegral length_) ::#gtk2hs_type gint)
#{poke GdkEventKey, hardware_keycode} ptr (keycode_ ::#gtk2hs_type guint16)
#{poke GdkEventKey, group} ptr (group_ ::#gtk2hs_type guint8)
-- | Insert DrawWindow and TimeStamp field when deserialized SerializedEventKey.
deserializeEventKey :: SerializedEventKey -> DrawWindow -> (EventM t a) -> IO a
deserializeEventKey event drawWindow fun = do
-- We need use *client* value replace field of event.
let newEvent = event {sEventWindow = SerializedWindow $ Just drawWindow
,sEventTime = currentTime}
with newEvent $ \eventPtr -> runReaderT fun (castPtr eventPtr)
------------------------------> C binding end <------------------------------
-- Andy
More information about the Haskell-Cafe
mailing list