diff --git a/CHANGES b/CHANGES
deleted file mode 100644
--- a/CHANGES
+++ /dev/null
@@ -1,42 +0,0 @@
-0.5: 12 Dec 2011
-   * First public release. basic pen operation, eraser operation, rectangular selection and file operations are implemented
-
-0.5.1: 16 Dec 2011 
-   * Use of configuration file '.hxournal'. Enable Use X Input menu. Dependency on xournal-parser and xournal-render is restricted to 0.2.0.* only
-   * checking gtk+-2.0 using pkg-config
-
-0.6: 18 Dec 2011 
-   * pdf background support. Annotate PDF menu is activated. preloading pdf background images
-
-0.6.0: 19 Dec 2011 
-   * some bug fixes (temporary yet) related to automatic scrollbar disappearing. Check when new, open, annotate pdf if xournal file is not saved yet. 
- 
-0.6.1: 25 Dec 2011
-   * undo/redo support, double buffer rendering while scrolling
-
-0.6.2: 15 Jan 2012
-   * layer support
-
-0.6.3: 24 Jan 2012 
-   * refine rendering while selection and scrolling. highlighter is implemented. Resizing selected strokes implemented
-
-0.6.4: 6 Feb 2012
-   * lasso selection, continuous page view. 
-
-0.6.5: 12 Feb 2012
-   * pen button support, pen pressure support, using faster xoj parser 
-
-0.6.6: 28 Feb 2012 
-   * scripting support, zoom in/out implemented. page functions are implemented
-
-==================
-
-0.7: 29 Nov 2012
-   * change to Hoodle
-   * new hoodle format   
-   * simplify namespace to Hoodle
-   * inter-process clipboard support using GtkClipboard
-   * Image embedding support 
-   * pdf export support 
-
-
diff --git a/Config.hs b/Config.hs
--- a/Config.hs
+++ b/Config.hs
@@ -54,12 +54,21 @@
 
 config :: LocalBuildInfo -> IO (Maybe HookedBuildInfo)
 config bInfo = do 
-  (excode,out,err) <- readProcessWithExitCode "pkg-config" ["--cflags", "gtk+-2.0"] "" 
-  incdirs <- case excode of 
-    ExitSuccess -> return . extractIncDir $ out
-    _ -> error $ ("failure when running pkg-config --cflags gtk+-2.0 :\n" ++ err) 
-    
-  
+  let cflags = (configConfigurationsFlags . configFlags) bInfo
+      b = maybe False id (lookup (FlagName "gtk3") cflags)
+  incdirs <- if b 
+               then do 
+                 (excode,out,err) <- readProcessWithExitCode "pkg-config" ["--cflags", "gtk+-3.0"] "" 
+                 case excode of 
+                   ExitSuccess -> return . extractIncDir $ out
+                   _ -> error $ ("failure when running pkg-config --cflags gtk+-3.0 :\n" ++ err) 
+               else do 
+                 (excode,out,err) <- readProcessWithExitCode "pkg-config" ["--cflags", "gtk+-2.0"] "" 
+                 case excode of 
+                   ExitSuccess -> return . extractIncDir $ out
+                   _ -> error $ ("failure when running pkg-config --cflags gtk+-2.0 :\n" ++ err) 
+
+ 
   let Just lib = library . localPkgDescr $ bInfo
       buildinfo = libBuildInfo lib
   let hbi = emptyBuildInfo { extraLibs = extraLibs buildinfo 
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,686 +1,25 @@
-Copyright (C) 2011-2014 Ian-Woo Kim
-
-Hoodle 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
-(at your option) any later version.
-
-Hoodle 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.
-
-                    GNU GENERAL PUBLIC LICENSE
-                       Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                            Preamble
-
-  The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
-  The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works.  By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.  We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors.  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
-  To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights.  Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received.  You must make sure that they, too, receive
-or can get the source code.  And you must show them these terms so they
-know their rights.
-
-  Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
-  For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software.  For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
-  Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so.  This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software.  The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable.  Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products.  If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
-  Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary.  To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                       TERMS AND CONDITIONS
-
-  0. Definitions.
-
-  "This License" refers to version 3 of the GNU General Public License.
-
-  "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
-  "The Program" refers to any copyrightable work licensed under this
-License.  Each licensee is addressed as "you".  "Licensees" and
-"recipients" may be individuals or organizations.
-
-  To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy.  The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
-  A "covered work" means either the unmodified Program or a work based
-on the Program.
-
-  To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy.  Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
-  To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies.  Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
-  An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License.  If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
-  1. Source Code.
-
-  The "source code" for a work means the preferred form of the work
-for making modifications to it.  "Object code" means any non-source
-form of a work.
-
-  A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
-  The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form.  A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
-  The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities.  However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work.  For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
-  The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
-  The Corresponding Source for a work in source code form is that
-same work.
-
-  2. Basic Permissions.
-
-  All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met.  This License explicitly affirms your unlimited
-permission to run the unmodified Program.  The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work.  This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
-  You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force.  You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright.  Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
-  Conveying under any other circumstances is permitted solely under
-the conditions stated below.  Sublicensing is not allowed; section 10
-makes it unnecessary.
-
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
-  No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
-  When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
-  4. Conveying Verbatim Copies.
-
-  You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
-  You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
-  5. Conveying Modified Source Versions.
-
-  You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
-    a) The work must carry prominent notices stating that you modified
-    it, and giving a relevant date.
-
-    b) The work must carry prominent notices stating that it is
-    released under this License and any conditions added under section
-    7.  This requirement modifies the requirement in section 4 to
-    "keep intact all notices".
-
-    c) You must license the entire work, as a whole, under this
-    License to anyone who comes into possession of a copy.  This
-    License will therefore apply, along with any applicable section 7
-    additional terms, to the whole of the work, and all its parts,
-    regardless of how they are packaged.  This License gives no
-    permission to license the work in any other way, but it does not
-    invalidate such permission if you have separately received it.
-
-    d) If the work has interactive user interfaces, each must display
-    Appropriate Legal Notices; however, if the Program has interactive
-    interfaces that do not display Appropriate Legal Notices, your
-    work need not make them do so.
-
-  A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit.  Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
-  6. Conveying Non-Source Forms.
-
-  You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
-    a) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by the
-    Corresponding Source fixed on a durable physical medium
-    customarily used for software interchange.
-
-    b) Convey the object code in, or embodied in, a physical product
-    (including a physical distribution medium), accompanied by a
-    written offer, valid for at least three years and valid for as
-    long as you offer spare parts or customer support for that product
-    model, to give anyone who possesses the object code either (1) a
-    copy of the Corresponding Source for all the software in the
-    product that is covered by this License, on a durable physical
-    medium customarily used for software interchange, for a price no
-    more than your reasonable cost of physically performing this
-    conveying of source, or (2) access to copy the
-    Corresponding Source from a network server at no charge.
-
-    c) Convey individual copies of the object code with a copy of the
-    written offer to provide the Corresponding Source.  This
-    alternative is allowed only occasionally and noncommercially, and
-    only if you received the object code with such an offer, in accord
-    with subsection 6b.
-
-    d) Convey the object code by offering access from a designated
-    place (gratis or for a charge), and offer equivalent access to the
-    Corresponding Source in the same way through the same place at no
-    further charge.  You need not require recipients to copy the
-    Corresponding Source along with the object code.  If the place to
-    copy the object code is a network server, the Corresponding Source
-    may be on a different server (operated by you or a third party)
-    that supports equivalent copying facilities, provided you maintain
-    clear directions next to the object code saying where to find the
-    Corresponding Source.  Regardless of what server hosts the
-    Corresponding Source, you remain obligated to ensure that it is
-    available for as long as needed to satisfy these requirements.
-
-    e) Convey the object code using peer-to-peer transmission, provided
-    you inform other peers where the object code and Corresponding
-    Source of the work are being offered to the general public at no
-    charge under subsection 6d.
-
-  A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
-  A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling.  In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage.  For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product.  A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
-  "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source.  The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
-  If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information.  But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
-  The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed.  Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
-  Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
-  7. Additional Terms.
-
-  "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law.  If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
-  When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it.  (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.)  You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
-  Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
-    a) Disclaiming warranty or limiting liability differently from the
-    terms of sections 15 and 16 of this License; or
-
-    b) Requiring preservation of specified reasonable legal notices or
-    author attributions in that material or in the Appropriate Legal
-    Notices displayed by works containing it; or
-
-    c) Prohibiting misrepresentation of the origin of that material, or
-    requiring that modified versions of such material be marked in
-    reasonable ways as different from the original version; or
-
-    d) Limiting the use for publicity purposes of names of licensors or
-    authors of the material; or
-
-    e) Declining to grant rights under trademark law for use of some
-    trade names, trademarks, or service marks; or
-
-    f) Requiring indemnification of licensors and authors of that
-    material by anyone who conveys the material (or modified versions of
-    it) with contractual assumptions of liability to the recipient, for
-    any liability that these contractual assumptions directly impose on
-    those licensors and authors.
-
-  All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10.  If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term.  If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
-  If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
-  Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
-  8. Termination.
-
-  You may not propagate or modify a covered work except as expressly
-provided under this License.  Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
-  However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
-  Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-  Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License.  If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
-  9. Acceptance Not Required for Having Copies.
-
-  You are not required to accept this License in order to receive or
-run a copy of the Program.  Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance.  However,
-nothing other than this License grants you permission to propagate or
-modify any covered work.  These actions infringe copyright if you do
-not accept this License.  Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
-  10. Automatic Licensing of Downstream Recipients.
-
-  Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License.  You are not responsible
-for enforcing compliance by third parties with this License.
-
-  An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations.  If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
-  You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License.  For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
-  11. Patents.
-
-  A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based.  The
-work thus licensed is called the contributor's "contributor version".
-
-  A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version.  For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
-  Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
-  In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement).  To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
-  If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients.  "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
-  If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
-  A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License.  You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
-  Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
-  12. No Surrender of Others' Freedom.
-
-  If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all.  For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
-  13. Use with the GNU Affero General Public License.
-
-  Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work.  The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
-  14. Revised Versions of this License.
-
-  The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-  Each version is given a distinguishing version number.  If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation.  If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
-  If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
-  Later license versions may give you additional or different
-permissions.  However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
-  15. Disclaimer of Warranty.
-
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. Limitation of Liability.
-
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
-  17. Interpretation of Sections 15 and 16.
-
-  If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
-                     END OF TERMS AND CONDITIONS
-
-            How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    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
-    (at your option) 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/>.
-
-Also add information on how to contact you by electronic and paper mail.
+The following license covers this documentation, and the source code, except
+where otherwise indicated.
 
-  If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
+Copyright 2011-2014, Ian-Woo Kim. All rights reserved.
 
-    <program>  Copyright (C) <year>  <name of author>
-    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
 
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
 
-  You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-<http://www.gnu.org/licenses/>.
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
 
-  The GNU General Public License does not permit incorporating your program
-into proprietary programs.  If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library.  If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.  But first, please read
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS "AS IS" AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.lhs b/Setup.lhs
--- a/Setup.lhs
+++ b/Setup.lhs
@@ -6,4 +6,4 @@
 > 
 > main :: IO ()
 > main = defaultMainWithHooks myConfigHook
-> 
+> -- main = defaultMain
diff --git a/csrc/c_initdevice.c b/csrc/c_initdevice.c
--- a/csrc/c_initdevice.c
+++ b/csrc/c_initdevice.c
@@ -2,9 +2,11 @@
 #include <stdio.h>
 #include <string.h>
 
-
+#ifndef GTK3
 #include "XInput.h"
+#endif // GTK3
 
+#ifndef GTK3
 //
 // Globals.
 //
@@ -115,6 +117,7 @@
 }
 
 
+
 void find_wacom( char* stylus_name, char* eraser_name) 
 {
   Display *display = XOpenDisplay(NULL); 
@@ -136,8 +139,7 @@
   }
   return ; 
 }
-
-
+#endif // not GTK3
 
 void initdevice ( int* core
                 , int* stylus
@@ -149,53 +151,54 @@
 		, char* touchname
                 )
 {
-  // xinput_start(); 
-
   printf("initdevice : stylusname = %s\n", stylusname );
   printf("initdevice : erasername = %s\n", erasername ); 
   printf("initdevice : touchname = %s\n", touchname );                      
 
   GList* dev_list;
   GdkDevice* device;
+#ifdef GTK3
+  GdkDisplay* disp = gdk_display_get_default();
+  GdkDeviceManager *devman = gdk_display_get_device_manager(disp);
+
+  dev_list = gdk_device_manager_list_devices(devman, GDK_DEVICE_TYPE_SLAVE );
+#else // GTK3
   dev_list = gdk_devices_list();
+#endif // GTK3
   (*stylus) = 0;
   while (dev_list != NULL) {
-    // printf ("one device\n"); 
     device = (GdkDevice *)dev_list->data;
-    // printf(" %d : %s \n", device, device->name );
-    if (device != gdk_device_get_core_pointer()) {
-      // #ifdef ENABLE_XINPUT_BUGFIX
+    // device = GPOINTER_TO_INT(dev_list->data);
+    if ( gdk_device_get_source(device) != GDK_SOURCE_MOUSE ) {
       gdk_device_set_axis_use(device, 0, GDK_AXIS_IGNORE);
       gdk_device_set_axis_use(device, 1, GDK_AXIS_IGNORE);
-      // #endif
       gdk_device_set_mode(device, GDK_MODE_SCREEN);
 
-      // printf("This is xinput device %s \n", device -> name);
-      if( !strcmp (device->name, stylusname) ) {
-        // printf("got stylus\n");   
+      if( !strcmp (gdk_device_get_name(device), stylusname) ) {
         (*stylus) = (int) device; 
       } 
-      if( !strcmp (device->name, erasername) ) { 
-        // printf("got eraser\n");
+      if( !strcmp (gdk_device_get_name(device), erasername) ) { 
         (*eraser) = (int) device;
       } 
-      if( !strcmp (device->name, touchname) ) { 
-        // printf("got eraser\n");
+      if( !strcmp (gdk_device_get_name(device), touchname) ) { 
         (*touch) = (int) device;
       } 
     } 
     else { 
-      if( !strcmp (device->name, corepointername) ) { 
-        // printf("got Core Pointer\n"); 
+      if( !strcmp (gdk_device_get_name(device), corepointername) ) { 
         (*core) = (int) device; 
       } 
     } 
-    dev_list = dev_list->next; 
+#ifdef GTK3
+    dev_list = g_list_next(dev_list); 
+#else // GTK3
+    dev_list = dev_list->next;
+#endif // GTK3
   }
 
 }
 
-
+#ifndef GTK3
 void enable_touch( char* touch_name ) 
 {
   printf("enable touch: %s\n", touch_name ) ; 
@@ -204,18 +207,6 @@
 void disable_touch( GdkDrawable *gdkwin, char* touch_name ) 
 {
   printf("disable touch: %s\n", touch_name ); 
-  /* Display *dpy = XOpenDisplay(NULL); 
-  XIEventMask eventmask ; 
-  Window win = GDK_DRAWABLE_XID(gdkwin) ; 
-  unsigned char mask[1] = { 0 } ; 
-
-  eventmask.deviceid = 12 ; 
-  eventmask.make_len = sizeof(mask); 
-  eventmask.mask = mask ; 
- 
-  XISelectEvents (dpy,win,&eventmask,1); 
-
-  XCloseDisplay(dpy); */ 
   
 }
-
+#endif // GTK3
diff --git a/csrc/c_initdevice.h b/csrc/c_initdevice.h
--- a/csrc/c_initdevice.h
+++ b/csrc/c_initdevice.h
@@ -1,11 +1,11 @@
 #include <gtk/gtk.h>
 #include <stdio.h>
 
-void find_wacom( char* stylus_name, char* eraser_name ) ; 
+// void find_wacom( char* stylus_name, char* eraser_name ) ; 
 
 void initdevice( int* core, int* stylus, int* eraser, 
                  char* corepointername, char* stylusname, char* erasername ); 
 
-void enable_touch( char* touch_name ) ;
+// void enable_touch( char* touch_name ) ;
 
-void disable_touch( char* touch_name ); 
+// void disable_touch( char* touch_name ); 
diff --git a/hoodle-core.cabal b/hoodle-core.cabal
--- a/hoodle-core.cabal
+++ b/hoodle-core.cabal
@@ -1,11 +1,11 @@
 Name:		hoodle-core
-Version:	0.14
+Version:	0.15
 Synopsis:	Core library for hoodle
 Description: 	Hoodle is a pen notetaking program written in haskell. 
                 hoodle-core is the core library written in haskell and 
                 using gtk2hs
 Homepage:       http://ianwookim.org/hoodle
-License: 	GPL-3
+License: 	BSD3
 License-file:	LICENSE
 Author:		Ian-Woo Kim
 Maintainer: 	Ian-Woo Kim <ianwookim@gmail.com>
@@ -16,15 +16,27 @@
 data-files:     template/*.html.st
                 resource/*.png
                 resource/*.xml
-                CHANGES
                 Config.hs
 Source-repository head
   type: git
   location: http://www.github.com/wavewave/hoodle-core
 
+
+Flag Dyre
+  Description:     dynamic reconfiguration support
+  Default:         False
+
+Flag Gtk3
+  Description:     compile with gtk3
+  Default:         False 
+
+Flag Hub
+  Description:     communication with Hub
+  Default:         False
+
 Library
   hs-source-dirs: src
-  ghc-options: 	-Wall  -funbox-strict-fields -fno-warn-unused-do-bind -fno-warn-orphans 
+  ghc-options: 	-Wall -funbox-strict-fields -fno-warn-unused-do-bind -fno-warn-orphans 
   ghc-prof-options: -caf-all -auto-all
 
   Build-Depends:   aeson>=0.7,
@@ -35,31 +47,30 @@
                    base64-bytestring >= 0.1,
                    binary,
                    bytestring >= 0.9, 
-                   cairo > 0.12,
+                   cairo > 0.13,
+                   case-insensitive, 
                    cereal >= 0.3.5,
                    containers >= 0.4,
                    configurator >= 0.2,
                    coroutine-object >= 0.2, 
-                   dbus >= 0.10, 
                    Diff >= 0.3,
                    directory > 1,
-                   dyre >= 0.8.11, 
                    either >= 3.1, 
                    errors >= 1.3, 
                    filepath > 1, 
                    fsnotify >= 0.0.7, 
                    gd >= 3000.7,               
-                   gtk > 0.12, 
-                   hoodle-builder >= 0.3,
-                   hoodle-parser >= 0.3,
-                   hoodle-render >= 0.4,
-                   hoodle-types >= 0.3,
+                   handa-gdata >= 0.6.9.3, 
+                   hoodle-builder >= 0.3.0,
+                   hoodle-parser >= 0.3.0,
+                   hoodle-publish >= 0.2,
+                   hoodle-render == 0.5.*,
+                   hoodle-types >= 0.3.0,
+                   http-types,
                    lens >= 2.5,
                    monad-loops >= 0.3, 
                    mtl > 2,
-                   network, 
-                   network-info, 
-                   network-simple >= 0.3,
+                   network-uri > 2.6,
                    old-locale >= 1.0, 
                    pango > 0.12,
                    poppler >= 0.12.2.2, 
@@ -77,7 +88,29 @@
                    unordered-containers >= 0.2,
                    uuid >= 1.2.7, 
                    vector >= 0.10,
+                   websockets, 
                    xournal-parser >= 0.5.0.2
+  --
+  if flag(dyre)
+    Build-depends: dyre >= 0.8.11
+  -- 
+  if flag(gtk3) 
+    Build-depends: gtk3 > 0.13 
+  else 
+    Build-depends: gtk > 0.13
+  -- 
+  if flag(hub)
+    Build-depends: 
+                   dbus >= 0.10, 
+                   http-client,
+                   http-conduit,
+                   network > 2.6, 
+                   network-info, 
+                   network-simple >= 0.3,
+                   persistent,
+                   persistent-sqlite,
+                   persistent-template,
+                   resourcet
 
   Exposed-Modules: 
                    Hoodle.Accessor
@@ -86,6 +119,7 @@
                    Hoodle.Coroutine.Commit
                    Hoodle.Coroutine.ContextMenu
                    Hoodle.Coroutine.Default
+                   Hoodle.Coroutine.Default.Menu
                    Hoodle.Coroutine.Dialog
                    Hoodle.Coroutine.Draw
                    Hoodle.Coroutine.Eraser
@@ -96,7 +130,6 @@
                    Hoodle.Coroutine.Link
                    Hoodle.Coroutine.Minibuffer
                    Hoodle.Coroutine.Mode
-                   Hoodle.Coroutine.Network
                    Hoodle.Coroutine.Page
                    Hoodle.Coroutine.Pen
                    Hoodle.Coroutine.Scroll
@@ -104,6 +137,7 @@
                    Hoodle.Coroutine.Select.Clipboard
                    Hoodle.Coroutine.Select.ManipulateImage
                    Hoodle.Coroutine.TextInput
+                   Hoodle.Coroutine.LaTeX
                    Hoodle.Coroutine.VerticalSpace 
                    Hoodle.Coroutine.Window
                    Hoodle.Device
@@ -145,6 +179,15 @@
                    Hoodle.Widget.Dispatch
                    Hoodle.Widget.Layer 
                    Hoodle.Widget.PanZoom
+                   Hoodle.Widget.Scroll
+  if flag(hub)
+    Exposed-Modules: Hoodle.Coroutine.Hub
+                     Hoodle.Coroutine.Hub.Common
+                     Hoodle.Coroutine.HubInternal
+                     Hoodle.Coroutine.Network
+                     Hoodle.Coroutine.Socket
+                     Hoodle.Type.Hub
+                     Hoodle.Type.Synchronization
   Other-Modules: 
                    Paths_hoodle_core
   c-sources: 
@@ -154,5 +197,11 @@
                    csrc/c_initdevice.h
                    csrc/template-hsc-gtk2hs.h
                    csrc/XInput.h
-  cc-options:      -Wno-pointer-to-int-cast -std=gnu99 -DDEBUG 
+  cc-options:      -fPIC -Wno-pointer-to-int-cast -std=gnu99 -DDEBUG 
   extra-libraries: X11 Xi dl pthread
+  if flag(dyre)
+    cpp-options: -DDYRE
+  if flag(gtk3)
+    cpp-options: -DGTK3
+  if flag(hub)
+    cpp-options: -DHUB
diff --git a/resource/menu.xml b/resource/menu.xml
--- a/resource/menu.xml
+++ b/resource/menu.xml
@@ -28,6 +28,7 @@
     </menu>
     <menu action="VMA">
        <menuitem action="TOGPANZOOMA" />
+       <menuitem action="TOGSCRA" />
        <menu action="ZOOMA" >
          <menuitem action="ZMINA" />
          <menuitem action="ZMOUTA" />                          
@@ -64,6 +65,7 @@
     <menu action="IMA">
        <menuitem action="LDIMGA" />
        <menuitem action="LDSVGA" />
+       <menuitem action="LDIMGBKGA" />
        <menuitem action="LDPREIMGA" />   
        <menuitem action="LDPREIMG2A" />
        <menuitem action="LDPREIMG3A" />
@@ -73,11 +75,13 @@
        <menuitem action="EDITSRCA" />
        <menuitem action="EDITNETSRCA" />
        <menuitem action="TEXTFROMSRCA" />
+       <menuitem action="TOGGLENETSRCA" />
        <separator /> 
        <menuitem action="LATEXA" />
        <menuitem action="LATEXNETA" />
        <menuitem action="COMBINELATEXA" />
        <menuitem action="LATEXFROMSRCA" />
+       <menuitem action="UPDATELATEXA" />
        <separator />
     </menu>
     <menu action="PMA">
@@ -157,7 +161,7 @@
     <menu action="OMA">
        <menuitem action="UXINPUTA" />
        <menuitem action="HANDA" />
-       <menuitem action="SMTHSCRA" />
+       <!-- <menuitem action="SMTHSCRA" /> -->
        <menuitem action="POPMENUA" /> 
        <menuitem action="EBDIMGA" />
        <menuitem action="EBDPDFA" />
@@ -165,24 +169,18 @@
        <menuitem action="KEEPRATIOA" />
        <menuitem action="VCURSORA" />
        <menuitem action="TOGCLOCKA" />
-       <menuitem action="DCRDCOREA" />                        
-       <menuitem action="ERSRTIPA" />                        
-       <menuitem action="PRESSRSENSA" />                        
-       <menuitem action="PGHILTA" />                        
-       <menuitem action="MLTPGVWA" />                        
-       <menuitem action="MLTPGA" />                        
-       <menuitem action="BTN2MAPA" />                        
-       <menuitem action="BTN3MAPA" />                        
-       <separator />
-       <menuitem action="ANTIALIASBMPA" />
-       <menuitem action="PRGRSBKGA" />                        
-       <menuitem action="PRNTPPRULEA" />                        
-       <menuitem action="LFTHNDSCRBRA" />                        
-       <menuitem action="SHRTNMENUA" />   
-       <separator />
-       <menuitem action="AUTOSAVEPREFA" />
-       <menuitem action="SAVEPREFA" />
+       <menuitem action="PRESSRSENSA" />
+       <menu action="NEWPAGEMODEA">
+         <menuitem action="NEWPAGEPLAINA" />
+         <menuitem action="NEWPAGELASTA" />
+         <menuitem action="NEWPAGECYCLEA" />
+       </menu>
        <menuitem action="RELAUNCHA" />
+       <menuitem action="HUBA" />
+    </menu>
+    <menu action="WMA">
+       <menuitem action="ADDTABA" />
+       <menuitem action="CLOSETABA" />
     </menu>
     <menu action="HMA">
        <menuitem action="ABOUTA" />
diff --git a/src/Hoodle/Accessor.hs b/src/Hoodle/Accessor.hs
--- a/src/Hoodle/Accessor.hs
+++ b/src/Hoodle/Accessor.hs
@@ -1,11 +1,15 @@
-{-# LANGUAGE TypeOperators, GADTs, ScopedTypeVariables, Rank2Types  #-}
+-- {-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE Rank2Types  #-}
 
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Accessor 
 -- Copyright   : (c) 2011-2014 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -15,20 +19,21 @@
 module Hoodle.Accessor where
 
 import           Control.Applicative
-import           Control.Lens (Simple,Lens,view,set)
+import           Control.Concurrent.STM (readTVarIO)
+import           Control.Lens (Simple,Lens,view,set,(.~))
 import           Control.Monad hiding (mapM_, forM_)
+import           Control.Monad.IO.Class
 import qualified Control.Monad.State as St hiding (mapM_, forM_)
-import           Control.Monad.Trans
 import           Data.Foldable
 import qualified Data.IntMap as M
-import           Graphics.UI.Gtk hiding (get,set)
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as TE
+import qualified Graphics.UI.Gtk as Gtk
 -- from hoodle-platform 
 import           Data.Hoodle.Generic
 import           Data.Hoodle.Select
 import           Graphics.Hoodle.Render.Type
 -- from this package
--- import           Hoodle.GUI.Menu
--- import           Hoodle.GUI.Reflect
 import           Hoodle.ModelAction.Layer 
 import           Hoodle.Type
 import           Hoodle.Type.Alias
@@ -41,6 +46,20 @@
 updateXState :: (HoodleState -> MainCoroutine HoodleState) -> MainCoroutine ()
 updateXState action = St.put =<< action =<< St.get 
 
+-- | update unitHoodle
+updateUhdl :: (UnitHoodle -> MainCoroutine UnitHoodle) -> MainCoroutine ()
+updateUhdl action = do xst <- St.get
+                       let uhdl = view (unitHoodles.currentUnit) xst
+                       uhdl' <- action uhdl
+                       St.put (set (unitHoodles.currentUnit) uhdl' xst)
+
+-- | update unitHoodle
+pureUpdateUhdl :: (UnitHoodle -> UnitHoodle) -> MainCoroutine ()
+pureUpdateUhdl func = do xst <- St.get
+                         let uhdl = (func . view (unitHoodles.currentUnit)) xst
+                         St.put ((unitHoodles.currentUnit .~ uhdl) xst)
+
+
 -- | 
 getPenType :: MainCoroutine PenType 
 getPenType = view (penInfo.penType) <$> St.get
@@ -49,16 +68,18 @@
 getCurrentPageCurr :: MainCoroutine (Page EditMode) 
 getCurrentPageCurr = do 
   xstate <- St.get 
-  let hdlmodst = view hoodleModeState xstate
-      cinfobox = view currentCanvasInfo xstate 
+  let uhdl = view (unitHoodles.currentUnit) xstate
+      hdlmodst = view hoodleModeState uhdl
+      cinfobox = view currentCanvasInfo uhdl
   return $ forBoth' unboxBiAct (flip getCurrentPageFromHoodleModeState hdlmodst) cinfobox
 
 -- | 
 getCurrentPageCvsId :: CanvasId -> MainCoroutine (Page EditMode) 
 getCurrentPageCvsId cid = do 
   xstate <- St.get 
-  let hdlmodst = view hoodleModeState xstate
-      cinfobox = getCanvasInfo cid xstate 
+  let uhdl = view (unitHoodles.currentUnit) xstate
+      hdlmodst = view hoodleModeState uhdl
+      cinfobox = getCanvasInfo cid uhdl
   return $ forBoth' unboxBiAct (flip getCurrentPageFromHoodleModeState hdlmodst) cinfobox
 
 
@@ -82,22 +103,22 @@
 rItmsInCurrLyr = return . view gitems . getCurrentLayer =<< getCurrentPageCurr
       
 -- |
-otherCanvas :: HoodleState -> [Int] 
-otherCanvas = M.keys . getCanvasInfoMap 
+otherCanvas :: UnitHoodle -> [Int] 
+otherCanvas = M.keys . view cvsInfoMap 
 
 
 -- | apply an action to all canvases 
 applyActionToAllCVS :: (CanvasId -> MainCoroutine ()) -> MainCoroutine () 
 applyActionToAllCVS action = do 
   xstate <- St.get 
-  let cinfoMap  = getCanvasInfoMap xstate
+  let cinfoMap = view (unitHoodles.currentUnit.cvsInfoMap) xstate
       keys = M.keys cinfoMap 
   forM_ keys action
 
 -- | 
-getCanvasGeometryCvsId :: CanvasId -> HoodleState -> IO CanvasGeometry 
-getCanvasGeometryCvsId cid xstate = do 
-  let cinfobox = getCanvasInfo cid xstate
+getCanvasGeometryCvsId :: CanvasId -> UnitHoodle -> IO CanvasGeometry 
+getCanvasGeometryCvsId cid uhdl = do 
+  let cinfobox = getCanvasInfo cid uhdl
       cpn = PageNum . view (unboxLens currentPageNum) $ cinfobox 
       canvas = view (unboxLens drawArea) cinfobox
       fsingle :: CanvasInfo a -> IO CanvasGeometry 
@@ -106,9 +127,9 @@
   forBoth' unboxBiAct fsingle cinfobox
 
 -- |
-getGeometry4CurrCvs :: HoodleState -> IO CanvasGeometry 
-getGeometry4CurrCvs xstate = do 
-  let cinfobox = view currentCanvasInfo xstate
+getGeometry4CurrCvs :: UnitHoodle -> IO CanvasGeometry 
+getGeometry4CurrCvs uhdl = do 
+  let cinfobox = view currentCanvasInfo uhdl
       cpn = PageNum . view (unboxLens currentPageNum) $ cinfobox 
       canvas = view (unboxLens drawArea) cinfobox
       fsingle :: CanvasInfo a -> IO CanvasGeometry 
@@ -116,41 +137,45 @@
                 . view (viewInfo.pageArrangement) 
   forBoth' unboxBiAct fsingle cinfobox
 
-  
--- | update flag in HoodleState when corresponding toggle UI changed 
-updateFlagFromToggleUI :: String  -- ^ UI toggle button id
-                       -> Simple Lens HoodleState Bool -- ^ lens for flag 
-                       -> MainCoroutine Bool
-updateFlagFromToggleUI toggleid lensforflag = do 
-  xstate <- St.get 
-  let ui = view gtkUIManager xstate 
-  agr <- liftIO ( uiManagerGetActionGroups ui >>= \x ->
-                    case x of 
-                      [] -> error "No action group? "
-                      y:_ -> return y )
-  togglea <- liftIO (actionGroupGetAction agr toggleid) 
-             >>= maybe (error "updateFlagFromToggleUI") 
-                       (return . castToToggleAction)
-  b <- liftIO $ toggleActionGetActive togglea
-  St.modify (set lensforflag b) 
-  return b 
 
+ 
+
 -- | set toggle UI button to the corresponding HoodleState 
-setToggleUIForFlag :: String 
-                   -> Simple Lens HoodleState Bool -- ^ lens for flag
-                   -> HoodleState 
-                   -> IO Bool 
-setToggleUIForFlag toggleid lensforflag xstate = do 
+lensSetToggleUIForFlag :: String 
+                       -> Simple Lens HoodleState Bool -- ^ lens for flag
+                       -> HoodleState 
+                       -> IO Bool 
+lensSetToggleUIForFlag toggleid lensforflag xstate =
+  let b = view lensforflag xstate in setToggleUIForFlag toggleid b xstate
+
+-- | set toggle UI button to the corresponding HoodleState 
+setToggleUIForFlag :: String -> Bool -> HoodleState -> IO Bool 
+setToggleUIForFlag toggleid b xstate = do 
   let ui = view gtkUIManager xstate 
-      b = view lensforflag xstate 
-  agr <- uiManagerGetActionGroups ui >>= \x ->
+  agr <- Gtk.uiManagerGetActionGroups ui >>= \x ->
            case x of 
              [] -> error "No action group? "
              y:_ -> return y 
-  togglea <- actionGroupGetAction agr toggleid >>= \(Just x) -> 
-                return (castToToggleAction x) 
-  toggleActionSetActive togglea b
+  togglea <- Gtk.actionGroupGetAction agr toggleid >>= \(Just x) -> 
+                return (Gtk.castToToggleAction x) 
+  Gtk.toggleActionSetActive togglea b
   return b 
 
 
+-- |
+renderCache :: MainCoroutine RenderCache
+renderCache = (view renderCacheVar <$> St.get) >>= liftIO . readTVarIO
 
+-- |
+getHoodleFilePath :: UnitHoodle -> Maybe FilePath 
+getHoodleFilePath = fileStore2Maybe . view (hoodleFileControl.hoodleFileName) 
+
+-- |
+fileStore2Maybe :: FileStore -> Maybe FilePath 
+fileStore2Maybe (LocalDir Nothing)         = Nothing
+fileStore2Maybe (LocalDir (Just filename)) = Just filename
+fileStore2Maybe (TempDir filename)         = Just filename
+
+-- |
+getHoodleID :: UnitHoodle -> T.Text
+getHoodleID = TE.decodeUtf8 . view ghoodleID . getHoodle
diff --git a/src/Hoodle/Config.hs b/src/Hoodle/Config.hs
--- a/src/Hoodle/Config.hs
+++ b/src/Hoodle/Config.hs
@@ -3,7 +3,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Config 
--- Copyright   : (c) 2011-2013 Ian-Woo Kim
+-- Copyright   : (c) 2011-2014 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
@@ -62,17 +62,25 @@
     (mpanzoom :: Maybe String) <- C.lookup c "PanZoomWidget"
     (mlayer :: Maybe String) <- C.lookup c "LayerWidget"
 
-    let panzoom = maybe True (parse "PanZoomWidget") mpanzoom 
-        layer = maybe True (parse "LayerWidget") mlayer
+    let panzoom = maybe True (parseBool "PanZoomWidget") mpanzoom 
+        layer = maybe True (parseBool "LayerWidget") mlayer
         
     print ("WidgetConfig =" ++ show (panzoom,layer) )
     return (panzoom,layer)
-  where parse msg str = case str of
-                          "true" -> True
-                          "false" -> False 
-                          _ -> error ("cannot understand " ++ msg ++ " in configfile")
 
+parseBool :: String -> String -> Bool
+parseBool msg str = case str of
+                      "true" -> True
+                      "false" -> False 
+                      _ -> error ("cannot understand " ++ msg ++ " in configfile")
+
          
+getPenConfig :: Config -> IO Bool
+getPenConfig c = do
+    (mvcursor :: Maybe String) <- C.lookup c "variablecursor"
+    let vcursor = maybe False (parseBool "variablecursor") mvcursor
+    return vcursor
+     
 
 {-
 getNetworkInfo :: Config -> IO (Maybe HoodleClipClientConfiguration)
diff --git a/src/Hoodle/Coroutine/Commit.hs b/src/Hoodle/Coroutine/Commit.hs
--- a/src/Hoodle/Coroutine/Commit.hs
+++ b/src/Hoodle/Coroutine/Commit.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.Commit 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
@@ -12,74 +12,73 @@
 
 module Hoodle.Coroutine.Commit where
 
-import Control.Lens (view,set)
+import Control.Lens (view,set,(.~))
 import Control.Monad.Trans
 import Control.Monad.State
 -- from this package
+import Hoodle.Accessor
 import Hoodle.Coroutine.Draw 
-import Hoodle.ModelAction.File
+import Hoodle.GUI.Reflect
 import Hoodle.ModelAction.Page
 import Hoodle.Type.Coroutine
 import Hoodle.Type.HoodleState 
-import Hoodle.Type.Undo 
+import Hoodle.Type.Undo
+import Hoodle.Util
 
 -- | save state and add the current status in undo history 
-
 commit :: HoodleState -> MainCoroutine () 
 commit xstate = do 
+  put xstate
   let ui = view gtkUIManager xstate
-  liftIO $ toggleSave ui True
-  let hdlmodst = view hoodleModeState xstate
-      undotable = view undoTable xstate 
-      undotable' = addToUndo undotable hdlmodst
-      xstate' = set isSaved False 
-                . set undoTable undotable'
-                $ xstate
-  put xstate' 
+  liftIO $ reflectUIToggle ui "SAVEA" True
+  pureUpdateUhdl $ \uhdl -> 
+    let hdlmodst = view hoodleModeState uhdl
+        undotable = view undoTable uhdl
+        undotable' = addToUndo undotable hdlmodst
+    in ((isSaved .~ False) . (undoTable .~ undotable')) uhdl
 
 -- | 
-  
 commit_ :: MainCoroutine ()
 commit_ = get >>= commit 
 
 -- | 
-
 undo :: MainCoroutine () 
 undo = do 
     xstate <- get
-    let utable = view undoTable xstate
-        cache = view renderCache xstate
+    let uhdl = view (unitHoodles.currentUnit) xstate
+    let utable = view undoTable uhdl
     case getPrevUndo utable of 
-      Nothing -> liftIO $ putStrLn "no undo item yet"
-      Just (hdlmodst1,newtable) -> do 
-        hdlmodst <- liftIO $ resetHoodleModeStateBuffers cache hdlmodst1 
-        put . set hoodleModeState hdlmodst
-            . set undoTable newtable 
-            =<< (liftIO (updatePageAll hdlmodst xstate))
+      Nothing -> msgShout "no undo item yet"
+      Just (hdlmodst,newtable) -> do 
+        let cid = getCurrentCanvasId uhdl
+        callRenderer_ $ resetHoodleModeStateBuffers cid hdlmodst
+        updateUhdl $ \uhdl' -> do
+          uhdl'' <- liftIO (updatePageAll hdlmodst uhdl')
+          return $ ( (hoodleModeState .~ hdlmodst) . (undoTable .~ newtable)) uhdl''
         invalidateAll 
       
 -- |       
-  
 redo :: MainCoroutine () 
 redo = do 
     xstate <- get
-    let utable = view undoTable xstate
-        cache = view renderCache xstate
+    let uhdl = view (unitHoodles.currentUnit) xstate
+        utable = view undoTable uhdl
+        cid = getCurrentCanvasId uhdl
     case getNextUndo utable of 
-      Nothing -> liftIO $ putStrLn "no redo item"
-      Just (hdlmodst1,newtable) -> do 
-        hdlmodst <- liftIO $ resetHoodleModeStateBuffers cache hdlmodst1
-        put . set hoodleModeState hdlmodst
-            . set undoTable newtable 
-            =<< (liftIO (updatePageAll hdlmodst xstate))
+      Nothing -> msgShout "no redo item"
+      Just (hdlmodst,newtable) -> do 
+        callRenderer_ $ resetHoodleModeStateBuffers cid hdlmodst
+        updateUhdl $ \uhdl' -> do 
+          uhdl'' <- liftIO (updatePageAll hdlmodst uhdl')
+          let uhdl''' = ( set hoodleModeState hdlmodst
+                       . set undoTable newtable ) uhdl'' 
+          return uhdl''' 
         invalidateAll 
 
 -- | 
         
 clearUndoHistory :: MainCoroutine () 
-clearUndoHistory = do 
-    xstate <- get
-    put . set undoTable (emptyUndo 1) $ xstate
+clearUndoHistory = pureUpdateUhdl (undoTable .~ (emptyUndo 1))
     
 
 
diff --git a/src/Hoodle/Coroutine/ContextMenu.hs b/src/Hoodle/Coroutine/ContextMenu.hs
--- a/src/Hoodle/Coroutine/ContextMenu.hs
+++ b/src/Hoodle/Coroutine/ContextMenu.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -5,9 +6,9 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.ContextMenu
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -18,7 +19,8 @@
 
 -- from other packages
 import           Control.Applicative
-import           Control.Lens (view,set,(%~),(^.))
+import           Control.Concurrent.STM (readTVarIO)
+import           Control.Lens (view,set,(^.),(.~))
 import           Control.Monad.State hiding (mapM_,forM_)
 import           Control.Monad.Trans.Maybe
 import qualified Data.ByteString.Char8 as B
@@ -31,14 +33,11 @@
 import qualified Data.Text as T (unpack, splitAt)
 import qualified Data.Text.Encoding as TE
 import qualified Graphics.Rendering.Cairo as Cairo
--- import qualified Graphics.Rendering.Cairo.SVG as RSVG
-import           Graphics.UI.Gtk hiding (get,set)
+import qualified Graphics.UI.Gtk as Gtk
 import           System.Directory 
 import           System.FilePath
 import           System.Process
 -- from hoodle-platform
-import           Control.Monad.Trans.Crtn.Event
-import           Control.Monad.Trans.Crtn.Queue 
 import           Data.Hoodle.BBox
 import           Data.Hoodle.Generic
 import           Data.Hoodle.Select
@@ -79,29 +78,27 @@
 
 processContextMenu :: ContextMenuEvent -> MainCoroutine () 
 processContextMenu (CMenuSaveSelectionAs ityp) = do 
-  xst <- get
-  forM_ (getSelectedItmsFromHoodleState xst) 
-        (\hititms->  
-           let ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) hititms 
-           in case ulbbox of 
-                Middle bbox -> 
-                  case ityp of 
-                    TypSVG -> exportCurrentSelectionAsSVG hititms bbox
-                    TypPDF -> exportCurrentSelectionAsPDF hititms bbox
-                _ -> return () 
-        )
+    mhititms <- getSelectedItmsFromUnitHoodle . view (unitHoodles.currentUnit) <$> get
+    forM_ mhititms $ \hititms->  
+      let ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) hititms 
+      in case ulbbox of 
+           Middle bbox -> 
+             case ityp of 
+               TypSVG -> exportCurrentSelectionAsSVG hititms bbox
+               TypPDF -> exportCurrentSelectionAsPDF hititms bbox
+           _ -> return ()
 processContextMenu CMenuCut = cutSelection
 processContextMenu CMenuCopy = copySelection
 processContextMenu CMenuDelete = deleteSelection
 processContextMenu (CMenuCanvasView cid pnum _x _y) = do 
-    xstate <- get 
-    let cmap =  xstate ^. cvsInfoMap 
-    let mcinfobox = IM.lookup cid cmap 
+    uhdl <- view (unitHoodles.currentUnit) <$> get 
+    let cmap =  uhdl ^. cvsInfoMap 
+        mcinfobox = IM.lookup cid cmap 
     case mcinfobox of 
-      Nothing -> liftIO $ putStrLn "error in processContextMenu"
+      Nothing -> msgShout "error in processContextMenu"
       Just _cinfobox -> do 
-        cinfobox' <- liftIO (setPage xstate pnum cid)
-        put $ set cvsInfoMap (IM.adjust (const cinfobox') cid cmap) xstate 
+        cinfobox' <- liftIO (setPage uhdl pnum cid)
+        pureUpdateUhdl (cvsInfoMap .~ IM.adjust (const cinfobox') cid cmap)
         adjustScrollbarWithGeometryCvsId cid 
         invalidateAll 
 processContextMenu (CMenuRotate dir imgbbx) = rotateImage dir imgbbx
@@ -113,12 +110,11 @@
       hset <- xst ^. hookSet 
       customAutosavePage hset <*> pure pg 
 processContextMenu (CMenuLinkConvert nlnk) = 
-    either (const (return ())) action 
-      . hoodleModeStateEither 
-      . (^. hoodleModeState) =<< get 
+    either_ action . hoodleModeStateEither . (^. hoodleModeState) . view (unitHoodles.currentUnit)  =<< get 
   where action thdl = do 
           xst <- get 
-          let cache = xst ^. renderCache
+          let uhdl = view (unitHoodles.currentUnit) xst
+              cid = getCurrentCanvasId uhdl
           case thdl ^. gselSelected of 
             Nothing -> return () 
             Just (n,tpg) -> do 
@@ -135,48 +131,51 @@
                       layer' = GLayer buf . TEitherAlterHitted . Right $ alist'
                   return (set (glayers.selectedLayer) layer' tpg)
                 Right _ -> error "processContextMenu: activelayer"
-              nthdl <- liftIO $ updateTempHoodleSelectIO cache thdl ntpg n
-              commit . set hoodleModeState (SelectState nthdl)
-                =<< (liftIO (updatePageAll (SelectState nthdl) xst))
+              nthdl <- updateTempHoodleSelectM cid thdl ntpg n
+              uhdl' <- liftIO $ updatePageAll (SelectState nthdl) uhdl
+              commit $ (unitHoodles.currentUnit .~ uhdl') xst
               invalidateAll 
 processContextMenu CMenuCreateALink = 
-  fileChooser FileChooserActionOpen Nothing >>= mapM_ linkSelectionWithFile
+  fileChooser Gtk.FileChooserActionOpen Nothing >>= mapM_ linkSelectionWithFile
 processContextMenu CMenuAssocWithNewFile = do
   xst <- get 
   let msuggestedact = xst ^. hookSet >>= fileNameSuggestionHook 
   (msuggested :: Maybe String) <- maybe (return Nothing) (liftM Just . liftIO) msuggestedact 
   
-  fileChooser FileChooserActionSave msuggested >>=   
+  fileChooser Gtk.FileChooserActionSave msuggested >>=   
     mapM_ (\fp -> do 
               b <- liftIO (doesFileExist fp)
               if b 
                 then okMessageBox "The file already exist!"
                 else do 
-                  let action = mkIOaction $ \_ -> do                      
-                        nhdl <- liftIO $ defaultHoodle   
-                        (L.writeFile fp . builder) nhdl 
-                        createProcess (proc "hoodle" [fp]) 
-                        return (UsrEv ActionOrdered)
-                  modify (tempQueue %~ enqueue action) 
-                  waitSomeEvent (\x -> case x of ActionOrdered -> True ; _ -> False)
+                  doIOaction_ $ do                      
+                    nhdl <- liftIO $ defaultHoodle   
+                    (L.writeFile fp . builder) nhdl 
+                    createProcess (proc "hoodle" [fp]) 
                   linkSelectionWithFile fp 
                   return ()
           ) 
 processContextMenu (CMenuMakeLinkToAnchor anc) = do 
     xst <- get
     uuidbstr <- liftIO $ B.pack . show <$> nextRandom
-    docidbstr <- view ghoodleID . getHoodle <$> get
-    let mloc = view (hoodleFileControl.hoodleFileName) xst
+    let uhdl = view (unitHoodles.currentUnit) xst 
+        docidbstr = (view ghoodleID . getHoodle) uhdl
+        mloc = case view (hoodleFileControl.hoodleFileName) uhdl of
+                 LocalDir Nothing -> Nothing
+                 LocalDir (Just fp) -> Just fp
+                 TempDir _ -> Nothing
         loc = maybe "" B.pack mloc
-    let lnk = LinkAnchor uuidbstr docidbstr loc (anchor_id anc) "" (0,0) (Dim 50 50)
+        lnk = LinkAnchor uuidbstr docidbstr loc (anchor_id anc) "" (0,0) (Dim 50 50)
     callRenderer $ cnstrctRItem (ItemLink lnk) >>= return . GotRItem
     RenderEv (GotRItem newitem) <-
       waitSomeEvent (\case RenderEv (GotRItem _) -> True; _ -> False)
     insertItemAt Nothing newitem 
 processContextMenu (CMenuPangoConvert (x0,y0) txt) = textInput (Just (x0,y0)) txt
 processContextMenu (CMenuLaTeXConvert (x0,y0) txt) = laTeXInput (Just (x0,y0)) txt
+#ifdef HUB
 processContextMenu (CMenuLaTeXConvertNetwork (x0,y0) txt) = laTeXInputNetwork (Just (x0,y0)) txt
-processContextMenu (CMenuLaTeXUpdate (x0,y0) key) = runMaybeT (laTeXInputKeyword (x0,y0) key) >> return ()
+#endif
+processContextMenu (CMenuLaTeXUpdate (x0,y0) dim key) = runMaybeT (laTeXInputKeyword (x0,y0) (Just dim) key) >> return ()
 processContextMenu (CMenuCropImage imgbbox) = cropImage imgbbox
 processContextMenu (CMenuExportHoodlet itm) = do
     res <- handwritingRecognitionDialog
@@ -192,15 +191,15 @@
         let fp = hoodletdir </> str <.> "hdlt"
         L.writeFile fp (Hoodlet.builder itm) 
 processContextMenu (CMenuConvertSelection itm) = do
-    xstate <- get 
-    let pgnum = view (currentCanvasInfo . unboxLens currentPageNum) xstate 
+    uhdl <- view (unitHoodles.currentUnit) <$> get 
+    let pgnum = view (currentCanvasInfo . unboxLens currentPageNum) uhdl
     deleteSelection
     callRenderer $ return . GotRItem =<< cnstrctRItem itm
     RenderEv (GotRItem newitem) <- waitSomeEvent (\case RenderEv (GotRItem _) -> True; _ -> False) 
     let BBox (x0,y0) _ = getBBox newitem
     insertItemAt (Just (PageNum pgnum, PageCoord (x0,y0))) newitem
 processContextMenu CMenuCustom =  do
-    either (const (return ())) action . hoodleModeStateEither . view hoodleModeState =<< get 
+    either_ action . hoodleModeStateEither . view hoodleModeState . view (unitHoodles.currentUnit) =<< get 
   where action thdl = do    
           xst <- get 
           forM_ (view gselSelected thdl) 
@@ -213,27 +212,28 @@
 --  | 
 linkSelectionWithFile :: FilePath -> MainCoroutine ()  
 linkSelectionWithFile fname = do
-  liftM getSelectedItmsFromHoodleState get >>=  
-    mapM_ (\hititms -> 
-            let ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) hititms 
-            in case ulbbox of 
-              Middle bbox -> do 
-                cache <- view renderCache <$> get 
-                svg <- liftIO $ makeSVGFromSelection cache hititms bbox
-                uuid <- liftIO $ nextRandom
-                let uuidbstr = B.pack (show uuid) 
-                deleteSelection 
-                linkInsert "simple" (uuidbstr,fname) fname (svg_render svg,bbox)  
-              _ -> return () )
+  uhdl <- view (unitHoodles.currentUnit) <$> get
+  let cid = getCurrentCanvasId uhdl
+  forM_ (getSelectedItmsFromUnitHoodle uhdl) $ \hititms -> 
+    let ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) hititms 
+    in case ulbbox of 
+         Middle bbox -> do 
+           cache <- renderCache
+           svg <- liftIO $ makeSVGFromSelection cache cid hititms bbox
+           uuid <- liftIO $ nextRandom
+           let uuidbstr = B.pack (show uuid) 
+           deleteSelection 
+           linkInsert "simple" (uuidbstr,fname) fname (svg_render svg,bbox)
+         _ -> return () 
 
           
 -- | 
 exportCurrentSelectionAsSVG :: [RItem] -> BBox -> MainCoroutine () 
 exportCurrentSelectionAsSVG hititms bbox@(BBox (ulx,uly) (lrx,lry)) = 
-    fileChooser FileChooserActionSave Nothing >>= maybe (return ()) action 
+    fileChooser Gtk.FileChooserActionSave Nothing >>= mapM_ action 
   where 
     action filename = do
-      cache <- view renderCache <$> get
+      (cache,cid) <- (,) <$> renderCache <*> (getCurrentCanvasId . view (unitHoodles.currentUnit) <$> get)
       -- this is rather temporary not to make mistake 
       if takeExtension filename /= ".svg" 
         then fileExtensionInvalid (".svg","export") 
@@ -242,15 +242,15 @@
           liftIO $ Cairo.withSVGSurface filename (lrx-ulx) (lry-uly) $ \s -> 
             Cairo.renderWith s $ do 
               Cairo.translate (-ulx) (-uly)
-              mapM_ (renderRItem cache) hititms
+              mapM_ (renderRItem cache cid) hititms
 
 
 exportCurrentSelectionAsPDF :: [RItem] -> BBox -> MainCoroutine () 
 exportCurrentSelectionAsPDF hititms bbox@(BBox (ulx,uly) (lrx,lry)) = 
-    fileChooser FileChooserActionSave Nothing >>= maybe (return ()) action 
+    fileChooser Gtk.FileChooserActionSave Nothing >>= mapM_ action 
   where 
     action filename = do
-      cache <- view renderCache <$> get
+      (cache,cid) <- (,) <$> renderCache <*> (getCurrentCanvasId . view (unitHoodles.currentUnit) <$> get)
       -- this is rather temporary not to make mistake 
       if takeExtension filename /= ".pdf" 
         then fileExtensionInvalid (".svg","export") 
@@ -259,7 +259,7 @@
           liftIO $ Cairo.withPDFSurface filename (lrx-ulx) (lry-uly) $ \s -> 
             Cairo.renderWith s $ do 
               Cairo.translate (-ulx) (-uly)
-              mapM_ (renderRItem cache) hititms
+              mapM_ (renderRItem cache cid) hititms
 
 -- |
 exportImage :: S.Image -> MainCoroutine ()
@@ -267,7 +267,7 @@
   
   runMaybeT $ do 
     pngbstr <- (MaybeT . return . getByteStringIfEmbeddedPNG . S.img_src) img
-    fp <- MaybeT (fileChooser FileChooserActionSave Nothing)  
+    fp <- MaybeT (fileChooser Gtk.FileChooserActionSave Nothing)  
     liftIO $ B.writeFile fp pngbstr
   return ()
 
@@ -276,216 +276,218 @@
 showContextMenu (pnum,(x,y)) = do 
     xstate <- get
     when (view (settings.doesUsePopUpMenu) xstate) $ do 
-      let cids = IM.keys . view cvsInfoMap $ xstate
-          cid = fst . view currentCanvas $ xstate 
-          mselitms = do lst <- getSelectedItmsFromHoodleState xstate
+      let uhdl = view (unitHoodles.currentUnit) xstate
+          cids = IM.keys . view cvsInfoMap $ uhdl
+          cid = fst . view currentCanvas $ uhdl 
+          mselitms = do lst <- getSelectedItmsFromUnitHoodle uhdl
                         if null lst then Nothing else Just lst 
-      modify (tempQueue %~ enqueue (action xstate mselitms cid cids)) 
+      doIOaction (action xstate mselitms cid cids)
       >> waitSomeEvent (\e->case e of ContextMenuCreated -> True ; _ -> False) 
       >> return () 
   where 
-    action xstate msitms cid cids  
-      = Left . ActionOrder $ \evhandler -> do 
-          menu <- menuNew 
-          menuSetTitle menu "MyMenu"
-          case msitms of 
-            Nothing -> return ()
-            Just sitms -> do 
-              menuitem1 <- menuItemNewWithLabel "Make SVG"
-              menuitem2 <- menuItemNewWithLabel "Make PDF"
-              menuitem3 <- menuItemNewWithLabel "Cut"
-              menuitem4 <- menuItemNewWithLabel "Copy"
-              menuitem5 <- menuItemNewWithLabel "Delete"
-              menuitem6 <- menuItemNewWithLabel "New File Linked Here"
-              menuitem1 `on` menuItemActivate $   
-                evhandler (UsrEv (GotContextMenuSignal (CMenuSaveSelectionAs TypSVG)))
-              menuitem2 `on` menuItemActivate $ 
-                evhandler (UsrEv (GotContextMenuSignal (CMenuSaveSelectionAs TypPDF)))
-              menuitem3 `on` menuItemActivate $ 
-                evhandler (UsrEv (GotContextMenuSignal (CMenuCut)))
-              menuitem4 `on` menuItemActivate $    
-                evhandler (UsrEv (GotContextMenuSignal (CMenuCopy)))
-              menuitem5 `on` menuItemActivate $    
-                evhandler (UsrEv (GotContextMenuSignal (CMenuDelete)))
-              menuitem6 `on` menuItemActivate $ 
-                evhandler (UsrEv (GotContextMenuSignal (CMenuAssocWithNewFile)))
-              menuAttach menu menuitem1 0 1 1 2 
-              menuAttach menu menuitem2 0 1 2 3
-              menuAttach menu menuitem3 1 2 0 1                     
-              menuAttach menu menuitem4 1 2 1 2                     
-              menuAttach menu menuitem5 1 2 2 3    
-              menuAttach menu menuitem6 1 2 3 4 
-              mapM_ (\mi -> menuAttach menu mi 1 2 5 6) =<< menuCreateALink evhandler sitms 
-              case sitms of 
-                sitm : [] -> do 
-                  menuhdlt <- menuItemNewWithLabel "Make Hoodlet"
-                  menuhdlt `on` menuItemActivate $ 
-                    ( evhandler . UsrEv . GotContextMenuSignal 
-                    . CMenuExportHoodlet . rItem2Item ) sitm
-                  menuAttach menu menuhdlt 0 1 8 9
-                  
-                  case sitm of 
-                    RItemLink lnkbbx _msfc -> do 
-                      let lnk = bbxed_content lnkbbx
-                      forM_ ((urlParse . B.unpack . link_location) lnk)
-                            (\urlpath -> do milnk <- menuOpenALink urlpath
-                                            menuAttach menu milnk 0 1 3 4 )
-                      case lnk of 
-                        Link _i _typ _lstr _txt _cmd _rdr _pos _dim ->  
-                          convertLinkFromSimpleToDocID lnk >>=  
-                            mapM_ (\link -> do 
-                              let LinkDocID _ uuid _ _ _ _ _ _ = link 
-                              menuitemcvt <- menuItemNewWithLabel ("Convert Link With ID" ++ show uuid) 
-                              menuitemcvt `on` menuItemActivate $
-                                ( evhandler 
-                                  . UsrEv 
-                                  . GotContextMenuSignal 
-                                  . CMenuLinkConvert ) link
-                              menuAttach menu menuitemcvt 0 1 4 5 
-                            ) 
-                        LinkDocID i lid file txt cmd rdr pos dim -> do 
-                          runMaybeT $ do  
-                            hset <- (MaybeT . return . view hookSet) xstate
-                            f <- (MaybeT . return . lookupPathFromId) hset
-                            file' <- MaybeT (f (B.unpack lid))
-                            guard ((B.unpack file) /= file')
-                            let link = LinkDocID 
-                                         i lid (B.pack file') txt cmd rdr pos dim
-                            menuitemcvt <- liftIO $ menuItemNewWithLabel 
-                              ("Correct Path to " ++ show file') 
-                            liftIO (menuitemcvt `on` menuItemActivate $ 
-                              ( evhandler 
-                                . UsrEv 
-                                . GotContextMenuSignal 
-                                . CMenuLinkConvert ) link)
-                            liftIO $ menuAttach menu menuitemcvt 0 1 4 5 
-                          return ()
-                        LinkAnchor i lid file aid bstr pos dim -> do 
-                          runMaybeT $ do  
-                            hset <- (MaybeT . return . view hookSet) xstate
-                            f <- (MaybeT . return . lookupPathFromId) hset
-                            file' <- MaybeT (f (B.unpack lid))
-                            guard ((B.unpack file) /= file')
-                            let link = LinkAnchor i lid (B.pack file') aid bstr pos dim
-                            menuitemcvt <- liftIO $ menuItemNewWithLabel 
-                              ("Correct Path to " ++ show file') 
-                            liftIO (menuitemcvt `on` menuItemActivate $ 
-                              ( evhandler 
-                                . UsrEv 
-                                . GotContextMenuSignal 
-                                . CMenuLinkConvert) link)
-                            liftIO $ menuAttach menu menuitemcvt 0 1 4 5 
-                          return ()
-
-                    RItemSVG svgbbx _msfc -> do
-                      let svg = bbxed_content svgbbx
-                          BBox (x0,y0) _ = getBBox svgbbx
-                      forM_ ((,) <$> svg_text svg <*> svg_command svg) $ \(btxt,cmd) -> do
-                        let txt = TE.decodeUtf8 btxt
-                        case cmd of 
-                          "pango" -> do 
-                            menuitemedt <- menuItemNewWithLabel ("Edit Text") 
-                            menuitemedt `on` menuItemActivate $ do 
-                              evhandler (UsrEv (GotContextMenuSignal (CMenuPangoConvert (x0,y0) txt)))
-                            menuAttach menu menuitemedt 0 1 4 5
-                            return ()
-                          "latex" -> do 
-                            menuitemedt <- menuItemNewWithLabel ("Edit LaTeX")
-                            menuitemedt `on` menuItemActivate $ do
-                              evhandler (UsrEv (GotContextMenuSignal (CMenuLaTeXConvert (x0,y0) txt)))
-                            menuAttach menu menuitemedt 0 1 4 5 
-                            --
-                            menuitemnet <- menuItemNewWithLabel ("Edit LaTeX Network")
-                            menuitemnet `on` menuItemActivate $ do
-                              evhandler (UsrEv (GotContextMenuSignal (CMenuLaTeXConvertNetwork (x0,y0) txt)))
-                            menuAttach menu menuitemnet 0 1 5 6
-                            return ()
-                            -- 
-                            let (txth,txtt) = T.splitAt 19 txt 
-                            when ( txth == "embedlatex:keyword:" ) $ do
-                              menuitemup <- menuItemNewWithLabel ("Update LaTeX")
-                              menuitemup `on` menuItemActivate $ do
-                                evhandler (UsrEv (GotContextMenuSignal (CMenuLaTeXUpdate (x0,y0) txtt)))
-                              menuAttach menu menuitemup 0 1 6 7
-                              return ()
+    action xstate msitms cid cids evhandler = do 
+      menu <- Gtk.menuNew 
+      Gtk.menuSetTitle menu ("MyMenu" :: String)
+      case msitms of 
+        Nothing -> return ()
+        Just sitms -> do 
+          menuitem1 <- Gtk.menuItemNewWithLabel ("Make SVG" :: String)
+          menuitem2 <- Gtk.menuItemNewWithLabel ("Make PDF" :: String)
+          menuitem3 <- Gtk.menuItemNewWithLabel ("Cut" :: String)
+          menuitem4 <- Gtk.menuItemNewWithLabel ("Copy" :: String)
+          menuitem5 <- Gtk.menuItemNewWithLabel ("Delete" :: String)
+          menuitem6 <- Gtk.menuItemNewWithLabel ("New File Linked Here" :: String)
+          menuitem1 `Gtk.on` Gtk.menuItemActivate $   
+            evhandler (UsrEv (GotContextMenuSignal (CMenuSaveSelectionAs TypSVG)))
+          menuitem2 `Gtk.on` Gtk.menuItemActivate $ 
+            evhandler (UsrEv (GotContextMenuSignal (CMenuSaveSelectionAs TypPDF)))
+          menuitem3 `Gtk.on` Gtk.menuItemActivate $ 
+            evhandler (UsrEv (GotContextMenuSignal (CMenuCut)))
+          menuitem4 `Gtk.on` Gtk.menuItemActivate $    
+            evhandler (UsrEv (GotContextMenuSignal (CMenuCopy)))
+          menuitem5 `Gtk.on` Gtk.menuItemActivate $    
+            evhandler (UsrEv (GotContextMenuSignal (CMenuDelete)))
+          menuitem6 `Gtk.on` Gtk.menuItemActivate $ 
+            evhandler (UsrEv (GotContextMenuSignal (CMenuAssocWithNewFile)))
+          Gtk.menuAttach menu menuitem1 0 1 1 2 
+          Gtk.menuAttach menu menuitem2 0 1 2 3
+          Gtk.menuAttach menu menuitem3 1 2 0 1                     
+          Gtk.menuAttach menu menuitem4 1 2 1 2                     
+          Gtk.menuAttach menu menuitem5 1 2 2 3    
+          Gtk.menuAttach menu menuitem6 1 2 3 4 
+          mapM_ (\mi -> Gtk.menuAttach menu mi 1 2 5 6) =<< menuCreateALink evhandler sitms 
+          case sitms of 
+            sitm : [] -> do 
+              menuhdlt <- Gtk.menuItemNewWithLabel ("Make Hoodlet" :: String)
+              menuhdlt `Gtk.on` Gtk.menuItemActivate $ 
+                ( evhandler . UsrEv . GotContextMenuSignal 
+                . CMenuExportHoodlet . rItem2Item ) sitm
+              Gtk.menuAttach menu menuhdlt 0 1 8 9
 
-                          _ -> return ()
-                    RItemImage imgbbx _msfc -> do
-                      menuitemcrop <- menuItemNewWithLabel ("Crop Image") 
-                      menuitemcrop `on` menuItemActivate $ do 
-                        (evhandler . UsrEv . GotContextMenuSignal . CMenuCropImage) imgbbx
-                      menuitemrotcw <- menuItemNewWithLabel ("Rotate Image CW") 
-                      menuitemrotcw `on` menuItemActivate $ do 
-                        (evhandler . UsrEv . GotContextMenuSignal) (CMenuRotate CW imgbbx)
-                      menuitemrotccw <- menuItemNewWithLabel ("Rotate Image CCW") 
-                      menuitemrotccw `on` menuItemActivate $ do 
-                        (evhandler . UsrEv . GotContextMenuSignal) (CMenuRotate CCW imgbbx)
-                      menuitemexport <- menuItemNewWithLabel ("Export Image")
-                      menuitemexport `on` menuItemActivate $ do
-                        (evhandler . UsrEv . GotContextMenuSignal) (CMenuExport imgbbx)
-                      -- 
-                      menuAttach menu menuitemcrop 0 1 4 5
-                      menuAttach menu menuitemrotcw 0 1 5 6
-                      menuAttach menu menuitemrotccw 0 1 6 7
-                      menuAttach menu menuitemexport 0 1 7 8
-                      -- 
+              case sitm of 
+                RItemLink lnkbbx _msfc -> do 
+                  let lnk = bbxed_content lnkbbx
+                  forM_ ((urlParse . B.unpack . link_location) lnk)
+                        (\urlpath -> do milnk <- menuOpenALink evhandler urlpath
+                                        Gtk.menuAttach menu milnk 0 1 3 4 )
+                  case lnk of 
+                    Link _i _typ _lstr _txt _cmd _rdr _pos _dim ->  
+                      convertLinkFromSimpleToDocID lnk >>=  
+                        mapM_ (\link -> do 
+                          let LinkDocID _ uuid _ _ _ _ _ _ = link 
+                          menuitemcvt <- Gtk.menuItemNewWithLabel ("Convert Link With ID" ++ show uuid :: String) 
+                          menuitemcvt `Gtk.on` Gtk.menuItemActivate $
+                            ( evhandler 
+                              . UsrEv 
+                              . GotContextMenuSignal 
+                              . CMenuLinkConvert ) link
+                          Gtk.menuAttach menu menuitemcvt 0 1 4 5 
+                        ) 
+                    LinkDocID i lid file txt cmd rdr pos dim -> do 
+                      runMaybeT $ do  
+                        hset <- (MaybeT . return . view hookSet) xstate
+                        f <- (MaybeT . return . lookupPathFromId) hset
+                        file' <- MaybeT (f (B.unpack lid))
+                        guard ((B.unpack file) /= file')
+                        let link = LinkDocID 
+                                     i lid (B.pack file') txt cmd rdr pos dim
+                        menuitemcvt <- liftIO $ Gtk.menuItemNewWithLabel 
+                          ("Correct Path to " ++ show file' :: String) 
+                        liftIO (menuitemcvt `Gtk.on` Gtk.menuItemActivate $ 
+                          ( evhandler 
+                            . UsrEv 
+                            . GotContextMenuSignal 
+                            . CMenuLinkConvert ) link)
+                        liftIO $ Gtk.menuAttach menu menuitemcvt 0 1 4 5 
                       return ()
-                    RItemAnchor ancbbx _ -> do
-                      menuitemmklnk <- menuItemNewWithLabel ("Link to this anchor")
-                      menuitemmklnk `on` menuItemActivate $
-                        ( evhandler 
-                        . UsrEv 
-                        . GotContextMenuSignal 
-                        . CMenuMakeLinkToAnchor 
-                        . bbxed_content) ancbbx
-                      menuAttach menu menuitemmklnk 0 1 4 5 
-                    _ -> return ()
+                    LinkAnchor i lid file aid bstr pos dim -> do 
+                      runMaybeT $ do  
+                        hset <- (MaybeT . return . view hookSet) xstate
+                        f <- (MaybeT . return . lookupPathFromId) hset
+                        file' <- MaybeT (f (B.unpack lid))
+                        guard ((B.unpack file) /= file')
+                        let link = LinkAnchor i lid (B.pack file') aid bstr pos dim
+                        menuitemcvt <- liftIO $ Gtk.menuItemNewWithLabel 
+                          ("Correct Path to " ++ show file' :: String) 
+                        liftIO (menuitemcvt `Gtk.on` Gtk.menuItemActivate $ 
+                          ( evhandler 
+                            . UsrEv 
+                            . GotContextMenuSignal 
+                            . CMenuLinkConvert) link)
+                        liftIO $ Gtk.menuAttach menu menuitemcvt 0 1 4 5 
+                      return ()
 
-                _ -> do
-                  let (links,others) = partition ((||) <$> isLinkInRItem <*> isAnchorInRItem) sitms 
-                  case links of 
-                    l : [] -> do
-                      menuitemreplace <- menuItemNewWithLabel ("replace link/anchor render")
-                      menuitemreplace `on` menuItemActivate $ do
-                        let cache = xstate ^. renderCache
-                            ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) others
-                        case ulbbox of 
-                          Middle bbox -> do
-                            let BBox (x0,y0) (x1,y1) = bbox
-                                dim = Dim (x1-x0) (y1-y0)
-                            svg <- svg_render <$> makeSVGFromSelection cache others bbox
-                            let mitm = case l of 
-                                  RItemLink lnkbbx _   -> (Just . ItemLink) ((bbxed_content lnkbbx) { link_render = svg, link_dim = dim })
-                                  RItemAnchor ancbbx _ -> (Just . ItemAnchor) ((bbxed_content ancbbx) { anchor_render = svg, anchor_dim = dim })
-                                  _ -> Nothing 
-                            maybe (return ()) (evhandler . UsrEv . GotContextMenuSignal . CMenuConvertSelection ) mitm
-                          _ -> return ()
-                      menuAttach menu menuitemreplace 0 1 8 9
-                    _ -> return ()
+                RItemSVG svgbbx _msfc -> do
+                  let svg = bbxed_content svgbbx
+                      BBox (x0,y0) (x1,y1) = getBBox svgbbx
+                  forM_ ((,) <$> svg_text svg <*> svg_command svg) $ \(btxt,cmd) -> do
+                    let txt = TE.decodeUtf8 btxt
+                    case cmd of 
+                      "pango" -> do 
+                        menuitemedt <- Gtk.menuItemNewWithLabel ("Edit Text" :: String) 
+                        menuitemedt `Gtk.on` Gtk.menuItemActivate $ do 
+                          evhandler (UsrEv (GotContextMenuSignal (CMenuPangoConvert (x0,y0) txt)))
+                        Gtk.menuAttach menu menuitemedt 0 1 4 5
+                        return ()
+                      "latex" -> do 
+                        menuitemedt <- Gtk.menuItemNewWithLabel ("Edit LaTeX" :: String)
+                        menuitemedt `Gtk.on` Gtk.menuItemActivate $ do
+                          evhandler (UsrEv (GotContextMenuSignal (CMenuLaTeXConvert (x0,y0) txt)))
+                        Gtk.menuAttach menu menuitemedt 0 1 4 5 
+                        --
+#ifdef HUB
+                        menuitemnet <- Gtk.menuItemNewWithLabel ("Edit LaTeX Network" :: String)
+                        menuitemnet `Gtk.on` Gtk.menuItemActivate $ do
+                          evhandler (UsrEv (GotContextMenuSignal (CMenuLaTeXConvertNetwork (x0,y0) txt)))
+                        Gtk.menuAttach menu menuitemnet 0 1 5 6
+                        return ()
+#endif
+                        -- 
+                        let (txth,txtt) = T.splitAt 19 txt 
+                        when ( txth == "embedlatex:keyword:" ) $ do
+                          menuitemup <- Gtk.menuItemNewWithLabel ("Update LaTeX" :: String)
+                          menuitemup `Gtk.on` Gtk.menuItemActivate $ do
+                            evhandler (UsrEv (GotContextMenuSignal (CMenuLaTeXUpdate (x0,y0) (Dim (x1-x0) (y1-y0)) txtt)))
+                          Gtk.menuAttach menu menuitemup 0 1 6 7
+                          return ()
 
-          case (customContextMenuTitle =<< view hookSet xstate) of 
-            Nothing -> return () 
-            Just ttl -> do 
-              custommenu <- menuItemNewWithLabel ttl  
-              custommenu `on` menuItemActivate $ 
-                evhandler (UsrEv (GotContextMenuSignal (CMenuCustom)))
-              menuAttach menu custommenu 0 1 0 1 
+                      _ -> return ()
+                RItemImage imgbbx _msfc -> do
+                  menuitemcrop <- Gtk.menuItemNewWithLabel ("Crop Image" :: String) 
+                  menuitemcrop `Gtk.on` Gtk.menuItemActivate $ do 
+                    (evhandler . UsrEv . GotContextMenuSignal . CMenuCropImage) imgbbx
+                  menuitemrotcw <- Gtk.menuItemNewWithLabel ("Rotate Image CW" :: String) 
+                  menuitemrotcw `Gtk.on` Gtk.menuItemActivate $ do 
+                    (evhandler . UsrEv . GotContextMenuSignal) (CMenuRotate CW imgbbx)
+                  menuitemrotccw <- Gtk.menuItemNewWithLabel ("Rotate Image CCW" :: String) 
+                  menuitemrotccw `Gtk.on` Gtk.menuItemActivate $ do 
+                    (evhandler . UsrEv . GotContextMenuSignal) (CMenuRotate CCW imgbbx)
+                  menuitemexport <- Gtk.menuItemNewWithLabel ("Export Image" :: String)
+                  menuitemexport `Gtk.on` Gtk.menuItemActivate $ do
+                    (evhandler . UsrEv . GotContextMenuSignal) (CMenuExport imgbbx)
+                  -- 
+                  Gtk.menuAttach menu menuitemcrop 0 1 4 5
+                  Gtk.menuAttach menu menuitemrotcw 0 1 5 6
+                  Gtk.menuAttach menu menuitemrotccw 0 1 6 7
+                  Gtk.menuAttach menu menuitemexport 0 1 7 8
+                  -- 
+                  return ()
+                RItemAnchor ancbbx _ -> do
+                  menuitemmklnk <- Gtk.menuItemNewWithLabel ("Link to this anchor" :: String)
+                  menuitemmklnk `Gtk.on` Gtk.menuItemActivate $
+                    ( evhandler 
+                    . UsrEv 
+                    . GotContextMenuSignal 
+                    . CMenuMakeLinkToAnchor 
+                    . bbxed_content) ancbbx
+                  Gtk.menuAttach menu menuitemmklnk 0 1 4 5 
+                _ -> return ()
 
-          menuitem8 <- menuItemNewWithLabel "Autosave This Page Image"
-          menuitem8 `on` menuItemActivate $ 
-            evhandler (UsrEv (GotContextMenuSignal (CMenuAutosavePage)))
-          menuAttach menu menuitem8 1 2 4 5 
+            _ -> do
+              let (links,others) = partition ((||) <$> isLinkInRItem <*> isAnchorInRItem) sitms 
+              case links of 
+                l : [] -> do
+                  menuitemreplace <- Gtk.menuItemNewWithLabel ("replace link/anchor render" :: String)
+                  menuitemreplace `Gtk.on` Gtk.menuItemActivate $ do
+                    cache <- readTVarIO (xstate ^. renderCacheVar)
+                    let ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) others
+                    case ulbbox of 
+                      Middle bbox -> do
+                        let BBox (x0,y0) (x1,y1) = bbox
+                            dim = Dim (x1-x0) (y1-y0)
+                        svg <- svg_render <$> makeSVGFromSelection cache cid others bbox
+                        let mitm = case l of 
+                              RItemLink lnkbbx _   -> (Just . ItemLink) ((bbxed_content lnkbbx) { link_render = svg, link_dim = dim })
+                              RItemAnchor ancbbx _ -> (Just . ItemAnchor) ((bbxed_content ancbbx) { anchor_render = svg, anchor_dim = dim })
+                              _ -> Nothing 
+                        maybe (return ()) (evhandler . UsrEv . GotContextMenuSignal . CMenuConvertSelection ) mitm
+                      _ -> return ()
+                  Gtk.menuAttach menu menuitemreplace 0 1 8 9
+                _ -> return ()
 
-          runStateT (mapM_ (makeMenu evhandler menu cid) cids) 0 
-          widgetShowAll menu 
-          menuPopup menu Nothing 
-          return (UsrEv ContextMenuCreated)
+      case (customContextMenuTitle =<< view hookSet xstate) of 
+        Nothing -> return () 
+        Just ttl -> do 
+          custommenu <- Gtk.menuItemNewWithLabel ttl  
+          custommenu `Gtk.on` Gtk.menuItemActivate $ 
+            evhandler (UsrEv (GotContextMenuSignal (CMenuCustom)))
+          Gtk.menuAttach menu custommenu 0 1 0 1 
 
+      menuitem8 <- Gtk.menuItemNewWithLabel ("Autosave This Page Image" :: String)
+      menuitem8 `Gtk.on` Gtk.menuItemActivate $ 
+        evhandler (UsrEv (GotContextMenuSignal (CMenuAutosavePage)))
+      Gtk.menuAttach menu menuitem8 1 2 4 5 
+
+      runStateT (mapM_ (makeMenu evhandler menu cid) cids) 0 
+      Gtk.widgetShowAll menu 
+      Gtk.menuPopup menu Nothing 
+      return (UsrEv ContextMenuCreated)
+
     makeMenu evhdlr mn currcid cid = when (currcid /= cid) $ do 
       n <- get
-      mi <- liftIO $ menuItemNewWithLabel ("Show here in cvs" ++ show cid)
-      liftIO $ mi `on` menuItemActivate $ 
+      mi <- liftIO $ Gtk.menuItemNewWithLabel ("Show here in cvs" ++ show cid)
+      liftIO $ mi `Gtk.on` Gtk.menuItemActivate $ 
         evhdlr (UsrEv (GotContextMenuSignal (CMenuCanvasView cid pnum x y)))
-      liftIO $ menuAttach mn mi 2 3 n (n+1) 
+      liftIO $ Gtk.menuAttach mn mi 2 3 n (n+1) 
       put (n+1) 
     
diff --git a/src/Hoodle/Coroutine/Default.hs b/src/Hoodle/Coroutine/Default.hs
--- a/src/Hoodle/Coroutine/Default.hs
+++ b/src/Hoodle/Coroutine/Default.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE MultiWayIf #-}
@@ -7,9 +8,9 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.Default 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -20,67 +21,53 @@
 
 import           Control.Applicative hiding (empty)
 import           Control.Concurrent 
-import           Control.Concurrent.STM
-import           Control.Lens (_1,over,view,set,at,(.~),(%~),(^.))
--- import           Control.Monad.Reader hiding (mapM_)
+import qualified Control.Exception as E
+import           Control.Lens (over,view,set,at,(.~),(^.),_2)
 import           Control.Monad.State hiding (mapM_)
 import           Control.Monad.Trans.Reader (ReaderT(..))
 import qualified Data.ByteString.Char8 as B
 import           Data.Foldable (mapM_)
 import qualified Data.IntMap as M
 import           Data.IORef 
+import qualified Data.List as L
 import           Data.Maybe
-import           Data.Monoid ((<>))
-import           Data.Sequence (Seq, (<|),(|>), empty, singleton, viewl, ViewL(..))
-import qualified Data.Sequence as Seq (null)
-import qualified Data.Text as T (unpack)
-import           Data.Time.Clock
-import           Data.UUID
-import qualified Graphics.Rendering.Cairo as Cairo
 import qualified Graphics.UI.Gtk as Gtk hiding (get,set)
-import qualified Graphics.UI.Gtk.Poppler.Document as Poppler
-import qualified Graphics.UI.Gtk.Poppler.Page as Poppler
 import           System.Process 
+#ifdef HUB
+import           Data.Time.Clock
+import           System.Directory
+#endif
 -- from hoodle-platform
 import           Control.Monad.Trans.Crtn.Driver
 import           Control.Monad.Trans.Crtn.Object
 import           Control.Monad.Trans.Crtn.Logger.Simple
-import           Control.Monad.Trans.Crtn.Queue 
-import           Data.Hoodle.Select
-import           Data.Hoodle.Simple (Dimension(..), Background(..), defaultHoodle)
+import           Data.Hoodle.Simple (Dimension(..), Background(..))
 import           Data.Hoodle.Generic
 import           Graphics.Hoodle.Render
-import           Graphics.Hoodle.Render.Background
+import           Graphics.Hoodle.Render.Engine
 import           Graphics.Hoodle.Render.Type
 -- from this package
 import           Hoodle.Accessor
 import           Hoodle.Coroutine.Callback
-import           Hoodle.Coroutine.Commit
 import           Hoodle.Coroutine.ContextMenu
+import           Hoodle.Coroutine.Default.Menu
 import           Hoodle.Coroutine.Draw
 import           Hoodle.Coroutine.Eraser
 import           Hoodle.Coroutine.File
-import           Hoodle.Coroutine.HandwritingRecognition
 import           Hoodle.Coroutine.Highlighter
-import           Hoodle.Coroutine.Layer 
 import           Hoodle.Coroutine.Link
+import           Hoodle.Coroutine.Mode
 import           Hoodle.Coroutine.Page
 import           Hoodle.Coroutine.Pen
 import           Hoodle.Coroutine.Scroll
 import           Hoodle.Coroutine.Select
-import           Hoodle.Coroutine.Select.Clipboard
-import           Hoodle.Coroutine.TextInput 
-import           Hoodle.Coroutine.Mode
 import           Hoodle.Coroutine.VerticalSpace 
 import           Hoodle.Coroutine.Window
 import           Hoodle.Device
 import           Hoodle.GUI.Menu
 import           Hoodle.GUI.Reflect
-import           Hoodle.ModelAction.File
-
 import           Hoodle.ModelAction.Page
 import           Hoodle.ModelAction.Window 
-import           Hoodle.Script
 import           Hoodle.Script.Hook
 import           Hoodle.Type.Canvas
 import           Hoodle.Type.Coroutine
@@ -88,14 +75,19 @@
 import           Hoodle.Type.Event
 import           Hoodle.Type.HoodleState
 import           Hoodle.Type.PageArrangement
-import           Hoodle.Type.Predefined
 import           Hoodle.Type.Undo
 import           Hoodle.Type.Window 
 import           Hoodle.Type.Widget
-import           Hoodle.Widget.Clock
+import           Hoodle.Util
 import           Hoodle.Widget.Dispatch 
-import           Hoodle.Widget.Layer
 import           Hoodle.Widget.PanZoom
+#ifdef HUB
+import           Hoodle.Coroutine.Dialog
+import           Hoodle.Coroutine.HubInternal
+import           Hoodle.Coroutine.Socket
+import           Hoodle.Coroutine.TextInput 
+import           Hoodle.Type.Predefined
+#endif
 --
 import Prelude hiding (mapM_)
 
@@ -104,143 +96,169 @@
               -> Gtk.Window 
               -> Maybe Hook 
               -> Int -- ^ maxundo 
-              -> (Bool,Bool,Bool) -- ^ (xinputbool,usepz,uselyr)
-              -> Gtk.Statusbar -- ^ status bar 
+              -> (Bool,Bool,Bool,Bool) -- ^ (xinputbool,usepz,uselyr,varcsr)
               -> IO (EventVar,HoodleState,Gtk.UIManager,Gtk.VBox)
-initCoroutine devlst window mhook maxundo (xinputbool,usepz,uselyr) stbar = do 
+initCoroutine devlst window mhook maxundo (xinputbool,usepz,uselyr,varcsr) = do 
   evar <- newEmptyMVar  
   putMVar evar Nothing 
+  let callback = eventHandler evar
   st0new <- set deviceList devlst  
             . set rootOfRootWindow window 
-            . set callBack (eventHandler evar) 
+            . set callBack callback  
             <$> emptyHoodleState 
-  -- pdf rendering testing code
-  let tvar = st0new ^. pdfRenderQueue
-  --
   (ui,uicompsighdlr) <- getMenuUI evar    
   let st1 = set gtkUIManager ui st0new
       initcvs = set (canvasWidgets.widgetConfig.doesUsePanZoomWidget) usepz
               . set (canvasWidgets.widgetConfig.doesUseLayerWidget) uselyr
               $ defaultCvsInfoSinglePage { _canvasId = 1 } 
       initcvsbox = CanvasSinglePage initcvs
-      st2 = set frameState (Node 1) 
-            . updateFromCanvasInfoAsCurrentCanvas initcvsbox 
-            $ st1 { _cvsInfoMap = M.empty } 
-  (st3,cvs,_wconf) <- constructFrame st2 (view frameState st2)
-  (st4,wconf') <- eventConnect st3 (view frameState st3)
-  -- testing
-  -- let handler = const (putStrLn "In getFileContent, got call back")
-  -- newhdl <- flip runReaderT (undefined,undefined) . cnstrctRHoodle =<< defaultHoodle
-  -- let nhmodstate = ViewAppendState newhdl 
+      st2 = st1 # over (unitHoodles.currentUnit) ( set frameState (Node 1) 
+                                                 . updateFromCanvasInfoAsCurrentCanvas initcvsbox             
+                                                 . set cvsInfoMap M.empty )
+      uhdl2 = view (unitHoodles.currentUnit) st2
+  (uhdl3,cvs,_wconf) <- constructFrame st2 uhdl2 (view frameState uhdl2)
+  (uhdl4,wconf') <- eventConnect st2 uhdl3 (view frameState uhdl3)
+  notebook <- Gtk.notebookNew
+  statusbar <- Gtk.statusbarNew
+#ifdef HUB
+  let sqlinfo =  (join . fmap sqliteInfo) mhook 
+#endif
+  let st4 = (unitHoodles.currentUnit .~ uhdl4) st2
+      st5 = st4 # over (unitHoodles.currentUnit) 
+                       ( set undoTable (emptyUndo maxundo)  
+                       . set frameState wconf' 
+                       . set rootWindow cvs 
+                       . set (hoodleFileControl.hoodleFileName) (LocalDir Nothing))
+                . set (settings.doesUseXInput) xinputbool 
+                . set (settings.doesUseVariableCursor) varcsr
+#ifdef HUB
+                . set (settings.sqliteFileName) sqlinfo
+#endif
+                . set hookSet mhook 
+                . set rootNotebook notebook
+                . set uiComponentSignalHandler uicompsighdlr 
+                . set statusBar (Just statusbar)
 
-  let st5 = set (settings.doesUseXInput) xinputbool 
-          . set hookSet mhook 
-          . set undoTable (emptyUndo maxundo)  
-          . set frameState wconf' 
-          . set rootWindow cvs 
-          . set uiComponentSignalHandler uicompsighdlr 
-          . set statusBar (Just stbar)
-          . set (hoodleFileControl.hoodleFileName) Nothing 
-          -- . set hoodleModeState nhmodstate
-          $ st4     
   vbox <- Gtk.vBoxNew False 0 
-  -- 
-  let startingXstate = set rootContainer (Gtk.castToBox vbox) st5
-  let startworld = world startingXstate . ReaderT $ 
-                     (\(Arg DoEvent ev) -> guiProcess ev)  
+  Gtk.containerAdd window vbox
+  vboxcvs <- Gtk.vBoxNew False 0 
+  -- Gtk.notebookAppendPage notebook vboxcvs  ("untitled" :: T.Text)
+  (_,uuid,btn) <- createTab callback notebook vboxcvs
+  Gtk.containerAdd vboxcvs (view (unitHoodles.currentUnit.rootWindow) st5)
+
+  sigid <- notebook `Gtk.on` Gtk.switchPage $ \i -> callback (UsrEv (SwitchTab i)) 
+  let st6 = ( (unitHoodles.currentUnit.unitUUID .~ uuid) 
+            . (unitHoodles.currentUnit.unitButton .~ btn)
+            . (uiComponentSignalHandler.switchTabSignal .~ Just sigid)) st5
+      -- st6 = st5
+      startingXstate = (unitHoodles.currentUnit.rootContainer .~ Gtk.castToBox vboxcvs) st6
+      startworld = world startingXstate . ReaderT $ (\(Arg DoEvent ev) -> guiProcess ev)  
   putMVar evar . Just $ (driver simplelogger startworld)
   return (evar,startingXstate,ui,vbox)
 
-
 -- | initialization according to the setting 
-initialize :: AllEvent -> MainCoroutine ()
-initialize ev = do  
+initialize :: Maybe (CanvasId,CanvasDimension) -> Bool -> AllEvent -> MainCoroutine (CanvasId, CanvasDimension)
+initialize cvs isInitialized ev = do  
     case ev of 
-      UsrEv (Initialized mfname) -> do -- additional initialization goes here
-        xst1 <- get
-        let tvar = xst1 ^. pdfRenderQueue
-        doIOaction $ \evhandler -> do 
-          let handler = Gtk.postGUIAsync . evhandler . SysEv . RenderCacheUpdate
-          forkOn 2 $ pdfRendererMain handler tvar
-          return (UsrEv ActionOrdered)
-        waitSomeEvent (\case ActionOrdered -> True ; _ -> False ) 
-       
-        getFileContent mfname
-
-        xst2 <- get
-        let hdlst = xst2 ^. hoodleModeState 
-            cache = xst2 ^. renderCache
-        hdlst' <- liftIO $ resetHoodleModeStateBuffers cache hdlst
-        put (set hoodleModeState hdlst' xst2)
-
-
-        xst <- get 
-        let Just sbar = view statusBar xst 
-        cxtid <- liftIO $ Gtk.statusbarGetContextId sbar "test"
-        liftIO $ Gtk.statusbarPush sbar cxtid "Hello there" 
-        let ui = view gtkUIManager xst
-        liftIO $ toggleSave ui False
-        put (set isSaved True xst) 
- 
-      _ -> do ev' <- nextevent
-              initialize (UsrEv ev')
-
+      UsrEv (Initialized mfname) -> do 
+        if isInitialized 
+          then case cvs of
+                 Nothing -> nextevent >>= initialize Nothing True . UsrEv
+                 Just cvsi -> return cvsi
+          else do
+	    -- additional initialization goes here
+	    xst1 <- get
+	    let ui = xst1 ^. gtkUIManager
+		cachevar = xst1 ^. renderCacheVar
+		tvarpdf = xst1 ^. pdfRenderQueue
+		tvargen = xst1 ^. genRenderQueue
+	    doIOaction $ \evhandler -> do 
+	      -- let handler = Gtk.postGUIAsync . evhandler . SysEv . RenderCacheUpdate
+	      forkOn 2 $ pdfRendererMain (defaultHandler evhandler) tvarpdf
+	      forkIO $ E.catch (genRendererMain cachevar (defaultHandler evhandler) tvargen) (\e -> print (e :: E.SomeException)) 
+	      return (UsrEv ActionOrdered)
+	    waitSomeEvent (\case ActionOrdered -> True ; _ -> False ) 
+	    getFileContent (LocalDir mfname)
+	    -- 
+	    xst2 <- get
+	    let uhdl = view (unitHoodles.currentUnit) xst2
+		hdlst = uhdl ^. hoodleModeState 
+		cid = getCurrentCanvasId uhdl
+	    callRenderer_ $ resetHoodleModeStateBuffers cid hdlst
+	    pureUpdateUhdl (hoodleModeState .~ hdlst)
+	    -- liftIO $ toggleSave ui False
+	    liftIO $ reflectUIToggle ui "SAVEA" False
+	    pureUpdateUhdl (isSaved .~ True)
+            case cvs of
+              Just cvsi -> return cvsi
+              Nothing -> nextevent >>= initialize Nothing True . UsrEv
+      UsrEv (CanvasConfigure cid w h) -> do
+        nextevent >>= initialize (Just (cid,CanvasDimension (Dim w h))) isInitialized . UsrEv 
+      _ -> case (cvs,isInitialized) of
+             (Just cvsi,True) -> return cvsi
+             _ -> nextevent >>= initialize cvs isInitialized . UsrEv
 -- |
 guiProcess :: AllEvent -> MainCoroutine ()
 guiProcess ev = do 
-  initialize ev
-  changePage (const 0)
-  xstate <- get 
-  reflectViewModeUI
-  reflectPenModeUI
-  reflectPenColorUI  
-  reflectPenWidthUI
-  let cinfoMap  = getCanvasInfoMap xstate
-
-      assocs = M.toList cinfoMap 
-      f (cid,cinfobox) = do let canvas = getDrawAreaFromBox cinfobox
-                            (w',h') <- liftIO $ Gtk.widgetGetSize canvas
-                            liftIO $ print (w',h')
---                            defaultEventProcess (CanvasConfigure cid
---                                                (fromIntegral w') 
---                                                (fromIntegral h')) 
-  
-  mapM_ f assocs
-        
-  viewModeChange ToContSinglePage
-  pageZoomChange FitWidth
-
-  -- waitSomeEvent (\x -> case x of CanvasConfigure cid w h -> True ; _ -> False)
-  
-
-  startLinkReceiver
-  -- main loop 
-  sequence_ (repeat dispatchMode)
+    (cid,cdim) <- initialize Nothing False ev
+    liftIO $ print (cid,cdim)
+    changePage (const 0)
+    reflectViewModeUI
+    reflectPenModeUI
+    reflectPenColorUI  
+    reflectPenWidthUI
+    reflectNewPageModeUI
+    viewModeChange ToContSinglePage
+    pageZoomChange FitWidth
+#ifdef HUB
+    initSqliteDB
+    startLinkReceiver
+    socketConnect
+    syncFile
+#endif
+    doCanvasConfigure cid cdim
+    -- main loop 
+    sequence_ (repeat dispatchMode)
 
 -- | 
 dispatchMode :: MainCoroutine () 
-dispatchMode = get >>= return . hoodleModeStateEither . view hoodleModeState
-                   >>= either (const viewAppendMode) (const selectMode)
+dispatchMode = (view (unitHoodles.currentUnit) <$> get) 
+               >>= return . hoodleModeStateEither . view hoodleModeState
+               >>= either (const viewAppendMode) (const selectMode)
                      
 -- | 
 viewAppendMode :: MainCoroutine () 
 viewAppendMode = do 
   r1 <- nextevent 
   case r1 of 
-    PenDown cid pbtn pcoord -> do 
+    PenDown cid pbtn pcoord -> 
       widgetCheckPen cid pcoord $ do 
         ptype <- getPenType 
         case (ptype,pbtn) of 
-          (PenWork,PenButton1) -> penStart cid pcoord
+          (PenWork,PenButton1) -> do
+            r <- penStart cid pcoord
+            case r of 
+              Just (Just Nothing) -> do 
+                pureUpdateUhdl (isOneTimeSelectMode .~ YesBeforeSelect)
+                modeChange ToSelectMode
+                selectLassoStart PenButton3 cid pcoord
+              _ -> return ()
           (PenWork,PenButton2) -> eraserStart cid pcoord 
           (PenWork,PenButton3) -> do 
-            updateXState (return . set isOneTimeSelectMode YesBeforeSelect)
+            pureUpdateUhdl (isOneTimeSelectMode .~ YesBeforeSelect)
             modeChange ToSelectMode
             selectLassoStart PenButton3 cid pcoord
           (PenWork,EraserButton) -> eraserStart cid pcoord
           (PenWork,_) -> return () 
           (EraserWork,_)      -> eraserStart cid pcoord 
-          (HighlighterWork,_) -> highlighterStart cid pcoord
+          (HighlighterWork,_) -> do 
+            r <- highlighterStart cid pcoord 
+            case r of 
+              Just (Just Nothing) -> do 
+                pureUpdateUhdl (isOneTimeSelectMode .~ YesBeforeSelect)
+                modeChange ToSelectMode
+                selectLassoStart PenButton3 cid pcoord
+              _ -> return ()
           (VerticalSpaceWork,PenButton1) -> verticalSpaceStart cid pcoord 
           (VerticalSpaceWork,_) -> return () 
     TouchDown cid pcoord -> touchStart cid pcoord 
@@ -252,19 +270,15 @@
 disableTouch = do 
     xst <- get 
     let devlst = view deviceList xst 
-    let b = view (settings.doesUseTouch) xst 
-    when b $ do         
+    when (view (settings.doesUseTouch) xst) $ do         
       let nxst = set (settings.doesUseTouch) False xst 
-      doIOaction $ \_ -> do
-        setToggleUIForFlag "HANDA" (settings.doesUseTouch) nxst
+      doIOaction_ $ do
+        lensSetToggleUIForFlag "HANDA" (settings.doesUseTouch) nxst
         let touchstr = dev_touch_str devlst
         -- ad hoc
         when (touchstr /= "touch") $ do 
           readProcess "xinput" [ "disable", touchstr ] "" 
           return ()
-        -- 
-        return (UsrEv ActionOrdered)
-      waitSomeEvent (\x -> case x of ActionOrdered -> True ; _ -> False)
       put nxst
 
 -- |
@@ -298,7 +312,8 @@
 defaultEventProcess (VScrollBarMoved cid v) = vscrollBarMoved cid v
 defaultEventProcess (VScrollBarStart cid v) = vscrollStart cid v 
 defaultEventProcess PaneMoveStart = paneMoveStart 
-defaultEventProcess (CanvasConfigure cid w' h') = doCanvasConfigure cid (CanvasDimension (Dim w' h'))
+defaultEventProcess (CanvasConfigure cid w' h') =  
+    doCanvasConfigure cid (CanvasDimension (Dim w' h'))
 defaultEventProcess ToViewAppendMode = modeChange ToViewAppendMode
 defaultEventProcess ToSelectMode = modeChange ToSelectMode 
 defaultEventProcess ToSinglePage = viewModeChange ToSinglePage
@@ -323,9 +338,9 @@
     reflectPenWidthUI
 defaultEventProcess (BackgroundStyleChanged bsty) = do
     modify (backgroundStyle .~ bsty)
-    xstate <- get 
-    let pgnum = view (currentCanvasInfo . unboxLens currentPageNum) xstate
-        hdl = getHoodle xstate 
+    uhdl <- view (unitHoodles.currentUnit) <$> get 
+    let pgnum = view (currentCanvasInfo . unboxLens currentPageNum) uhdl
+        hdl = getHoodle uhdl
         pgs = view gpages hdl 
         cpage = getPageFromGHoodleMap pgnum hdl
         cbkg = view gbackground cpage
@@ -347,41 +362,36 @@
         npgs = set (at pgnum) (Just npage) pgs 
         nhdl = set gpages npgs hdl 
     modeChange ToViewAppendMode     
-    modify (set hoodleModeState (ViewAppendState nhdl))
+    pureUpdateUhdl (hoodleModeState .~ ViewAppendState nhdl)
     invalidateAll 
+defaultEventProcess (AssignNewPageMode nmod) = modify (settings.newPageMode .~ nmod)
 defaultEventProcess (GotContextMenuSignal ctxtmenu) = processContextMenu ctxtmenu
 defaultEventProcess (GetHoodleFileInfo ref) = do 
-  xst <- get
-  let hdl = getHoodle xst 
+  uhdl <- view (unitHoodles.currentUnit) <$> get
+  let hdl = getHoodle uhdl
       uuid = B.unpack (view ghoodleID hdl)
-  case view (hoodleFileControl.hoodleFileName) xst of 
+  case getHoodleFilePath uhdl of 
     Nothing -> liftIO $ writeIORef ref Nothing
     Just fp -> liftIO $ writeIORef ref (Just (uuid ++ "," ++ fp))
+defaultEventProcess (GetHoodleFileInfoFromTab uuidtab ref) = do 
+  uhdlmap <- view (unitHoodles._2) <$> get
+  let muhdl = (L.lookup uuidtab . map (\x -> (view unitUUID x,x)) . M.elems) uhdlmap
+  case muhdl of 
+    Nothing -> liftIO $ writeIORef ref Nothing
+    Just uhdl -> do 
+      let hdl = getHoodle uhdl
+          uuid = B.unpack (view ghoodleID hdl)
+      case getHoodleFilePath uhdl of 
+        Nothing -> liftIO $ writeIORef ref Nothing
+        Just fp -> liftIO $ writeIORef ref (Just (uuid ++ "," ++ fp))
 defaultEventProcess (GotLink mstr (x,y)) = gotLink mstr (x,y)    
-defaultEventProcess (Sync ctime) = do 
-  xst <- get
-  case view (hoodleFileControl.lastSavedTime) xst of 
-    Nothing -> return ()
-    Just otime -> do 
-      let dtime = diffUTCTime ctime otime
-      if dtime < dtime_bound * 10 
-        then return () 
-        else do 
-          let ioact = mkIOaction $ \evhandler -> do 
-                Gtk.postGUISync (evhandler (UsrEv FileReloadOrdered))
-                return (UsrEv ActionOrdered)
-          modify (tempQueue %~ enqueue ioact)
+
 defaultEventProcess FileReloadOrdered = fileReload 
 defaultEventProcess (CustomKeyEvent str) = do
-    liftIO $ print str
     if | str == "[]:\"Super_L\"" -> do  
            xst <- liftM (over (settings.doesUseTouch) not) get 
            put xst 
-           let action = mkIOaction $ \_evhandler -> do 
-                 setToggleUIForFlag "HANDA" (settings.doesUseTouch) xst
-                 return (UsrEv ActionOrdered)
-           modify (tempQueue %~ enqueue action)
-           waitSomeEvent (\x -> case x of ActionOrdered -> True ; _ -> False)    
+           doIOaction_ $ lensSetToggleUIForFlag "HANDA" (settings.doesUseTouch) xst
            toggleTouch
        | str == "[]:\"1\"" -> colorfunc ColorBlack
        | str == "[]:\"2\"" -> colorfunc ColorBlue 
@@ -402,210 +412,45 @@
   where 
     colorfunc c = doIOaction $ \_evhandler -> return (UsrEv (PenColorChanged c))
     toolfunc t = doIOaction $ \_evhandler -> return (UsrEv (AssignPenMode (Left t)))
+defaultEventProcess (SwitchTab i) = switchTab i
+defaultEventProcess (CloseTab uuid) = findTab uuid >>= mapM_  (\x-> switchTab x >> askIfSave closeTab)
+defaultEventProcess (OpenLink urlpath mid) = openLinkAction urlpath mid
+#ifdef HUB
+defaultEventProcess (OpenShared uuid) = openShared uuid
+defaultEventProcess (OpenTemp _uuid tmpfile) = getFileContent (TempDir tmpfile)
+                                              >> canvasZoomUpdateAll 
+                                              >> invalidateAll
+defaultEventProcess (NetworkProcess (NetworkReceived txt)) = networkReceived txt
 defaultEventProcess (DBusEv (ImageFileDropped fname)) = embedImage fname
 defaultEventProcess (DBusEv (DBusNetworkInput txt)) = dbusNetworkInput txt 
 defaultEventProcess (DBusEv (GoToLink (docid,anchorid))) = goToAnchorPos docid anchorid
-defaultEventProcess ev = -- for debugging
-                         do liftIO $ putStrLn "--- no default ---"
-                            liftIO $ print ev 
-                            liftIO $ putStrLn "------------------"
-                            return () 
-
--- |
-menuEventProcess :: MenuEvent -> MainCoroutine () 
-menuEventProcess MenuQuit = do 
-  xstate <- get
-  liftIO $ putStrLn "MenuQuit called"
-  if view isSaved xstate 
-    then liftIO $ Gtk.mainQuit
-    else askQuitProgram
-menuEventProcess MenuPreviousPage = changePage (\x->x-1)
-menuEventProcess MenuNextPage =  changePage (+1)
-menuEventProcess MenuFirstPage = changePage (const 0)
-menuEventProcess MenuLastPage = do 
-  totalnumofpages <- (either (M.size. view gpages) (M.size . view gselAll) 
-                      . hoodleModeStateEither . view hoodleModeState) <$> get 
-  changePage (const (totalnumofpages-1))
-menuEventProcess MenuNewPageBefore = newPage PageBefore 
-menuEventProcess MenuNewPageAfter = newPage PageAfter
-menuEventProcess MenuDeletePage = deleteCurrentPage
-menuEventProcess MenuExportPageSVG = exportCurrentPageAsSVG 
-menuEventProcess MenuNew  = askIfSave fileNew 
-menuEventProcess MenuAnnotatePDF = askIfSave fileAnnotatePDF
-menuEventProcess MenuLoadPNGorJPG = fileLoadPNGorJPG
-menuEventProcess MenuLoadSVG = fileLoadSVG
-menuEventProcess MenuText = textInput (Just (100,100)) "" 
-menuEventProcess MenuEmbedTextSource = embedTextSource
-menuEventProcess MenuEditEmbedTextSource = editEmbeddedTextSource
-menuEventProcess MenuEditNetEmbedTextSource = editNetEmbeddedTextSource
-menuEventProcess MenuTextFromSource = textInputFromSource (100,100)
-menuEventProcess MenuLaTeX = 
-    laTeXInput Nothing (laTeXHeader <> "\n\n" <> laTeXFooter)
-menuEventProcess MenuLaTeXNetwork = 
-    laTeXInputNetwork Nothing (laTeXHeader <> "\n\n" <> laTeXFooter)    
-menuEventProcess MenuCombineLaTeX = combineLaTeXText 
-menuEventProcess MenuLaTeXFromSource = laTeXInputFromSource (100,100)
-menuEventProcess MenuUndo = undo 
-menuEventProcess MenuRedo = redo
-menuEventProcess MenuOpen = askIfSave fileOpen
-menuEventProcess MenuSave = fileSave 
-menuEventProcess MenuSaveAs = fileSaveAs
-menuEventProcess MenuReload = fileReload 
-menuEventProcess MenuExport = fileExport 
-menuEventProcess MenuStartSync = fileStartSync
-menuEventProcess MenuVersionSave = fileVersionSave 
-menuEventProcess MenuShowRevisions = fileShowRevisions
-menuEventProcess MenuShowUUID = fileShowUUID
--- 
-menuEventProcess MenuCut = cutSelection
-menuEventProcess MenuCopy = copySelection
-menuEventProcess MenuPaste = pasteToSelection
-menuEventProcess MenuDelete = deleteSelection
-menuEventProcess MenuZoomIn = pageZoomChangeRel ZoomIn 
-menuEventProcess MenuZoomOut = pageZoomChangeRel ZoomOut
-menuEventProcess MenuNormalSize = pageZoomChange Original  
-menuEventProcess MenuPageWidth = pageZoomChange FitWidth 
-menuEventProcess MenuPageHeight = pageZoomChange FitHeight
-menuEventProcess MenuHSplit = eitherSplit SplitHorizontal
-menuEventProcess MenuVSplit = eitherSplit SplitVertical
-menuEventProcess MenuDelCanvas = deleteCanvas
-menuEventProcess MenuNewLayer = makeNewLayer 
-menuEventProcess MenuNextLayer = gotoNextLayer 
-menuEventProcess MenuPrevLayer = gotoPrevLayer
-menuEventProcess MenuGotoLayer = startGotoLayerAt 
-menuEventProcess MenuDeleteLayer = deleteCurrentLayer
-menuEventProcess MenuUseXInput = do 
-  xstate <- get 
-  b <- updateFlagFromToggleUI "UXINPUTA" (settings.doesUseXInput)
-  let cmap = getCanvasInfoMap xstate
-      canvases = map (getDrawAreaFromBox) . M.elems $ cmap 
-  if b
-    then mapM_ (\x->liftIO $ Gtk.widgetSetExtensionEvents x [Gtk.ExtensionEventsAll]) canvases
-    else mapM_ (\x->liftIO $ Gtk.widgetSetExtensionEvents x [Gtk.ExtensionEventsNone] ) canvases
-menuEventProcess MenuUseTouch = toggleTouch
-menuEventProcess MenuSmoothScroll = updateFlagFromToggleUI "SMTHSCRA" (settings.doesSmoothScroll) >> return ()
-menuEventProcess MenuUsePopUpMenu = updateFlagFromToggleUI "POPMENUA" (settings.doesUsePopUpMenu) >> return ()
-menuEventProcess MenuEmbedImage = updateFlagFromToggleUI "EBDIMGA" (settings.doesEmbedImage) >> return ()
-menuEventProcess MenuEmbedPDF = updateFlagFromToggleUI "EBDPDFA" (settings.doesEmbedPDF) >> return ()
-menuEventProcess MenuFollowLinks = updateFlagFromToggleUI "FLWLNKA" (settings.doesFollowLinks) >> return ()
-menuEventProcess MenuKeepAspectRatio = updateFlagFromToggleUI "KEEPRATIOA" (settings.doesKeepAspectRatio) >> return ()
-menuEventProcess MenuUseVariableCursor = updateFlagFromToggleUI "VCURSORA" (settings.doesUseVariableCursor) >> reflectCursor >> return ()
-menuEventProcess MenuPressureSensitivity = updateFlagFromToggleUI "PRESSRSENSA" (penInfo.variableWidthPen) >> return ()  
-menuEventProcess MenuRelaunch = liftIO $ relaunchApplication
-menuEventProcess MenuColorPicker = colorPick 
-menuEventProcess MenuFullScreen = fullScreen
-menuEventProcess MenuAddLink = addLink
-menuEventProcess MenuAddAnchor = addAnchor
-menuEventProcess MenuListAnchors = listAnchors
-menuEventProcess MenuEmbedPredefinedImage = embedPredefinedImage 
-menuEventProcess MenuEmbedPredefinedImage2 = embedPredefinedImage2 
-menuEventProcess MenuEmbedPredefinedImage3 = embedPredefinedImage3 
-menuEventProcess MenuApplyToAllPages = do 
-    xstate <- get 
-    let bsty = view backgroundStyle xstate 
-    let hdl = getHoodle xstate 
-        pgs = view gpages hdl 
-        changeBkg cpage = 
-          let cbkg = view gbackground cpage
-              nbkg 
-                | isRBkgSmpl cbkg = cbkg { rbkg_style = convertBackgroundStyleToByteString bsty }
-                | otherwise = cbkg 
-          in set gbackground nbkg cpage 
-        npgs = fmap changeBkg pgs 
-        nhdl = set gpages npgs hdl 
-    modeChange ToViewAppendMode     
-    modify (set hoodleModeState (ViewAppendState nhdl))
-    invalidateAll 
-menuEventProcess MenuEmbedAllPDFBkg = embedAllPDFBackground
-menuEventProcess MenuTogglePanZoomWidget = (togglePanZoom . view (currentCanvas._1)) =<< get 
-menuEventProcess MenuToggleLayerWidget = (toggleLayer . view (currentCanvas._1)) =<< get 
-menuEventProcess MenuToggleClockWidget = (toggleClock . view (currentCanvas._1)) =<< get
-menuEventProcess MenuHandwritingRecognitionDialog = 
-    handwritingRecognitionDialog >>= mapM_ (\(b,txt) -> when b $ embedHoodlet (T.unpack txt)) 
-menuEventProcess m = liftIO $ putStrLn $ "not implemented " ++ show m 
-
-
--- | 
-colorPick :: MainCoroutine () 
-colorPick = do mc <- colorPickerBox "Pen Color" 
-               maybe (return ())  
-                     (\c->modify (penInfo.currentTool.penColor .~ c)) 
-                     mc 
-
--- | 
-colorConvert :: Gtk.Color -> PenColor 
-colorConvert (Gtk.Color r g b) = ColorRGBA (realToFrac r/65536.0) (realToFrac g/65536.0) (realToFrac b/65536.0) 1.0 
-
--- | 
-colorPickerBox :: String -> MainCoroutine (Maybe PenColor) 
-colorPickerBox msg = do 
-   xst <- get 
-   let pcolor = view ( penInfo.currentTool.penColor) xst   
-   modify (tempQueue %~ enqueue (action pcolor)) >> go 
-  where 
-    action pcolor = 
-      mkIOaction $ 
-               \_evhandler -> do 
-                 dialog <- Gtk.colorSelectionDialogNew msg
-                 csel <- Gtk.colorSelectionDialogGetColor dialog
-                 let (r,g,b,_a) =  convertPenColorToRGBA pcolor 
-                     color = Gtk.Color (floor (r*65535.0)) (floor (g*65535.0)) (floor (b*65535.0))
-                
-                 Gtk.colorSelectionSetCurrentColor csel color
-                 res <- Gtk.dialogRun dialog 
-                 mc <- case res of 
-                         Gtk.ResponseOk -> do 
-                              clrsel <- Gtk.colorSelectionDialogGetColor dialog 
-                              clr <- Gtk.colorSelectionGetCurrentColor clrsel     
-                              return (Just (colorConvert clr))
-                         _ -> return Nothing 
-                 Gtk.widgetDestroy dialog 
-                 return (UsrEv (ColorChosen mc))
-    go = do r <- nextevent                   
-            case r of 
-              ColorChosen mc -> return mc 
-              UpdateCanvas cid -> -- this is temporary
-                invalidateInBBox Nothing Efficient cid >> go
-              _ -> go 
-
-
-pdfRendererMain :: ((UUID,(Double,Cairo.Surface))->IO ()) -> TVar (Seq (UUID,PDFCommand)) -> IO () 
-pdfRendererMain handler tvar = forever $ do     
-    -- putStrLn "pdfRenderMain called"
-    p <- atomically $ do 
-      lst' <- readTVar tvar
-      case viewl lst' of
-        EmptyL -> retry
-        p :< ps -> do 
-          writeTVar tvar ps 
-          return p 
-    pdfWorker handler p
-
-pdfWorker :: ((UUID,(Double,Cairo.Surface))->IO ()) -> (UUID,PDFCommand) -> IO ()
-pdfWorker _handler (_,GetDocFromFile fp tmvar) = do
-    -- putStrLn "pdfWorker : GetDocFromFile"
-    mdoc <- popplerGetDocFromFile fp
-    atomically $ putTMVar tmvar mdoc 
-pdfWorker _handler (_,GetDocFromDataURI str tmvar) = do
-    -- putStrLn "pdfWorker : GetDocFromDataURI"
-    mdoc <- popplerGetDocFromDataURI str
-    atomically $ putTMVar tmvar mdoc
-pdfWorker _handler (_,GetPageFromDoc doc pn tmvar) = do
-    -- putStrLn "pdfWorker : GetPageFromDoc"
-    mpg <- popplerGetPageFromDoc doc pn
-    atomically $ putTMVar tmvar mpg
-pdfWorker handler (uuid,RenderPageScaled page (Dim ow oh) (Dim w h)) = do
-    -- putStrLn "pdfWorker : RenderPageScaled"
-    let s = w / ow
-    sfc <- Cairo.createImageSurface Cairo.FormatARGB32 (floor w) (floor h)
-    Cairo.renderWith sfc $ do   
-      Cairo.setSourceRGBA 1 1 1 1
-      Cairo.rectangle 0 0 w h 
-      Cairo.fill
-      Cairo.scale s s
-      Poppler.pageRender page 
-    handler (uuid,(s,sfc))
-
-
+defaultEventProcess (DisconnectedHub tokfile (ofile,file) hinfo) = do
+    b <- okCancelMessageBox "authentication failure! do you want to start from the beginning?"
+    when b $ do
+      r' :: Either E.SomeException () <- liftIO (E.try (removeFile tokfile))
+      case r' of 
+        Left _ ->  msgShout "DisconnectedHub" >>  return ()
+        Right _ -> uploadWork (ofile,file) hinfo
+defaultEventProcess (Sync ctime) = do 
+  xst <- get
+  case view (unitHoodles.currentUnit.hoodleFileControl.lastSavedTime) xst of 
+    Nothing -> return ()
+    Just otime -> do 
+      let dtime = diffUTCTime ctime otime
+      if dtime < dtime_bound * 10 
+        then return () 
+        else 
+          doIOaction $ \evhandler -> do 
+            Gtk.postGUISync (evhandler (UsrEv FileReloadOrdered))
+            return (UsrEv ActionOrdered)
+defaultEventProcess (SyncInfoUpdated uhdluuid fstat) = updateSyncInfo uhdluuid fstat
+defaultEventProcess (SyncFileFinished fstat) = updateSyncInfoAll fstat
+defaultEventProcess (FileSyncFromHub uhdluuid fstat) = fileSyncFromHub uhdluuid fstat
+defaultEventProcess (GotSyncEvent isforced fileuuid uhdluuid) = gotSyncEvent isforced fileuuid uhdluuid
+#endif
 
+defaultEventProcess ev = -- for debugging
+                         do msgShout "--- no default ---"
+                            msgShout (show ev)
+                            msgShout "------------------"
 
diff --git a/src/Hoodle/Coroutine/Default/Menu.hs b/src/Hoodle/Coroutine/Default/Menu.hs
new file mode 100644
--- /dev/null
+++ b/src/Hoodle/Coroutine/Default/Menu.hs
@@ -0,0 +1,239 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Hoodle.Coroutine.Default.Menu
+-- Copyright   : (c) 2014, 2015 Ian-Woo Kim
+--
+-- License     : BSD3
+-- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
+-- Stability   : experimental
+-- Portability : GHC
+--
+-----------------------------------------------------------------------------
+
+module Hoodle.Coroutine.Default.Menu where
+
+import           Control.Applicative
+import           Control.Lens (_1,view,set,(.~))
+import           Control.Monad.IO.Class
+import           Control.Monad.State hiding (mapM_)
+import           Data.Foldable (mapM_)
+import qualified Data.IntMap as M
+import           Data.Monoid
+import qualified Data.Text as T
+import qualified Graphics.UI.Gtk as Gtk
+--
+import           Data.Hoodle.Generic
+import           Data.Hoodle.Select
+import           Graphics.Hoodle.Render.Type
+--
+import           Hoodle.Accessor
+import           Hoodle.Coroutine.Commit
+import           Hoodle.Coroutine.Draw
+import           Hoodle.Coroutine.File
+import           Hoodle.Coroutine.HandwritingRecognition
+import           Hoodle.Coroutine.LaTeX
+import           Hoodle.Coroutine.Layer
+import           Hoodle.Coroutine.Link
+import           Hoodle.Coroutine.Mode
+import           Hoodle.Coroutine.Page
+import           Hoodle.Coroutine.Select.Clipboard
+import           Hoodle.Coroutine.TextInput
+import           Hoodle.Coroutine.Window
+import           Hoodle.GUI.Reflect
+import           Hoodle.Type.Canvas
+import           Hoodle.Type.Coroutine
+import           Hoodle.Type.Enum
+import           Hoodle.Type.Event
+import           Hoodle.Type.HoodleState
+import           Hoodle.Type.PageArrangement
+import           Hoodle.Type.Window
+import           Hoodle.Widget.Clock
+import           Hoodle.Widget.Layer
+import           Hoodle.Widget.PanZoom
+import           Hoodle.Widget.Scroll
+#ifdef HUB
+import           Hoodle.Coroutine.Hub
+#endif
+#ifdef DYRE
+import           Hoodle.Script
+#endif
+--
+import Prelude hiding (mapM_)
+
+
+
+-- |
+menuEventProcess :: MenuEvent -> MainCoroutine () 
+menuEventProcess MenuQuit = do 
+    xstate <- get
+    if view (unitHoodles.currentUnit.isSaved) xstate 
+      then liftIO $ Gtk.mainQuit
+      else askQuitProgram
+menuEventProcess MenuPreviousPage = changePage (\x->x-1)
+menuEventProcess MenuNextPage =  changePage (+1)
+menuEventProcess MenuFirstPage = changePage (const 0)
+menuEventProcess MenuLastPage = do 
+    totalnumofpages <- (either (M.size. view gpages) (M.size . view gselAll) 
+                        . hoodleModeStateEither . view (unitHoodles.currentUnit.hoodleModeState)) <$> get 
+    changePage (const (totalnumofpages-1))
+menuEventProcess MenuNewPageBefore = newPage Nothing PageBefore 
+menuEventProcess MenuNewPageAfter = newPage Nothing PageAfter
+menuEventProcess MenuDeletePage = deleteCurrentPage
+menuEventProcess MenuExportPageSVG = exportCurrentPageAsSVG 
+menuEventProcess MenuNew  = addTab (LocalDir Nothing) -- askIfSave fileNew 
+menuEventProcess MenuAnnotatePDF = askIfSave fileAnnotatePDF
+menuEventProcess MenuLoadPNGorJPG = fileLoadPNGorJPG
+menuEventProcess MenuLoadSVG = fileLoadSVG
+menuEventProcess MenuLoadImageBackground = fileLoadImageBackground
+menuEventProcess MenuText = textInput (Just (100,100)) "" 
+menuEventProcess MenuEmbedTextSource = embedTextSource
+menuEventProcess MenuEditEmbedTextSource = editEmbeddedTextSource
+menuEventProcess MenuTextFromSource = textInputFromSource (100,100)
+menuEventProcess MenuLaTeX = 
+    laTeXInput Nothing (laTeXHeader <> "\n\n" <> laTeXFooter)
+menuEventProcess MenuCombineLaTeX = combineLaTeXText 
+menuEventProcess MenuLaTeXFromSource = laTeXInputFromSource (100,100)
+-- menuEventProcess MenuUpdateLaTeX = updateLaTeX
+menuEventProcess MenuUndo = undo 
+menuEventProcess MenuRedo = redo
+menuEventProcess MenuOpen = askIfSave fileOpen
+menuEventProcess MenuSave = fileSave 
+menuEventProcess MenuSaveAs = fileSaveAs
+menuEventProcess MenuReload = fileReload 
+menuEventProcess MenuExport = fileExport 
+-- menuEventProcess MenuStartSync = fileStartSync
+menuEventProcess MenuVersionSave = fileVersionSave 
+menuEventProcess MenuShowRevisions = fileShowRevisions
+menuEventProcess MenuShowUUID = fileShowUUID
+-- 
+menuEventProcess MenuCut = cutSelection
+menuEventProcess MenuCopy = copySelection
+menuEventProcess MenuPaste = pasteToSelection
+menuEventProcess MenuDelete = deleteSelection
+menuEventProcess MenuZoomIn = pageZoomChangeRel ZoomIn 
+menuEventProcess MenuZoomOut = pageZoomChangeRel ZoomOut
+menuEventProcess MenuNormalSize = pageZoomChange Original  
+menuEventProcess MenuPageWidth = pageZoomChange FitWidth 
+menuEventProcess MenuPageHeight = pageZoomChange FitHeight
+menuEventProcess MenuHSplit = eitherSplit SplitHorizontal
+menuEventProcess MenuVSplit = eitherSplit SplitVertical
+menuEventProcess MenuDelCanvas = deleteCanvas
+menuEventProcess MenuNewLayer = makeNewLayer 
+menuEventProcess MenuNextLayer = gotoNextLayer 
+menuEventProcess MenuPrevLayer = gotoPrevLayer
+menuEventProcess MenuGotoLayer = startGotoLayerAt 
+menuEventProcess MenuDeleteLayer = deleteCurrentLayer
+menuEventProcess MenuUseXInput = do 
+    uhdl <- view (unitHoodles.currentUnit) <$> get 
+    let cmap = view cvsInfoMap uhdl
+        canvases = map (getDrawAreaFromBox) . M.elems $ cmap 
+    updateFlagFromToggleUI "UXINPUTA" (settings.doesUseXInput) >>= \b -> 
+#ifdef GTK3      
+      return ()
+#else
+      if b
+        then mapM_ (\x->liftIO $ Gtk.widgetSetExtensionEvents x [Gtk.ExtensionEventsAll]) canvases
+        else mapM_ (\x->liftIO $ Gtk.widgetSetExtensionEvents x [Gtk.ExtensionEventsNone] ) canvases
+#endif
+menuEventProcess MenuUseTouch = toggleTouch
+menuEventProcess MenuUsePopUpMenu = updateFlagFromToggleUI "POPMENUA" (settings.doesUsePopUpMenu) >> return ()
+menuEventProcess MenuEmbedImage = updateFlagFromToggleUI "EBDIMGA" (settings.doesEmbedImage) >> return ()
+menuEventProcess MenuEmbedPDF = updateFlagFromToggleUI "EBDPDFA" (settings.doesEmbedPDF) >> return ()
+menuEventProcess MenuFollowLinks = updateFlagFromToggleUI "FLWLNKA" (settings.doesFollowLinks) >> return ()
+menuEventProcess MenuKeepAspectRatio = updateFlagFromToggleUI "KEEPRATIOA" (settings.doesKeepAspectRatio) >> return ()
+menuEventProcess MenuUseVariableCursor = updateFlagFromToggleUI "VCURSORA" (settings.doesUseVariableCursor) >> reflectCursor True >> return ()
+menuEventProcess MenuPressureSensitivity = updateFlagFromToggleUI "PRESSRSENSA" (penInfo.variableWidthPen) >> return ()  
+#ifdef DYRE
+menuEventProcess MenuRelaunch = liftIO $ relaunchApplication
+#endif
+menuEventProcess MenuColorPicker = colorPick 
+menuEventProcess MenuFullScreen = fullScreen
+menuEventProcess MenuAddLink = addLink
+menuEventProcess MenuAddAnchor = addAnchor
+menuEventProcess MenuListAnchors = listAnchors
+menuEventProcess MenuEmbedPredefinedImage = embedPredefinedImage 
+menuEventProcess MenuEmbedPredefinedImage2 = embedPredefinedImage2 
+menuEventProcess MenuEmbedPredefinedImage3 = embedPredefinedImage3 
+menuEventProcess MenuApplyToAllPages = do 
+    xst <- get 
+    let bsty = view backgroundStyle xst
+        uhdl = view (unitHoodles.currentUnit) xst
+        hdl = getHoodle uhdl
+        pgs = view gpages hdl 
+        changeBkg cpage = 
+          let cbkg = view gbackground cpage
+              nbkg 
+                | isRBkgSmpl cbkg = cbkg { rbkg_style = convertBackgroundStyleToByteString bsty }
+                | otherwise = cbkg 
+          in set gbackground nbkg cpage 
+        npgs = fmap changeBkg pgs 
+        nhdl = set gpages npgs hdl 
+    modeChange ToViewAppendMode     
+    pureUpdateUhdl (const ((hoodleModeState .~ ViewAppendState nhdl) uhdl))
+    invalidateAll 
+menuEventProcess MenuEmbedAllPDFBkg = embedAllPDFBackground
+menuEventProcess MenuTogglePanZoomWidget = togglePanZoom . view (unitHoodles.currentUnit.currentCanvas._1) =<< get 
+menuEventProcess MenuToggleLayerWidget = toggleLayer . view (unitHoodles.currentUnit.currentCanvas._1) =<< get 
+menuEventProcess MenuToggleClockWidget = toggleClock . view (unitHoodles.currentUnit.currentCanvas._1) =<< get
+menuEventProcess MenuToggleScrollWidget = toggleScroll . view (unitHoodles.currentUnit.currentCanvas._1) =<< get
+menuEventProcess MenuHandwritingRecognitionDialog = 
+    handwritingRecognitionDialog >>= mapM_ (\(b,txt) -> when b $ embedHoodlet (T.unpack txt)) 
+menuEventProcess MenuAddTab = addTab (LocalDir Nothing)
+-- menuEventProcess MenuNextTab = nextTab
+menuEventProcess MenuCloseTab = closeTab
+#ifdef HUB
+menuEventProcess MenuEditNetEmbedTextSource = editNetEmbeddedTextSource
+menuEventProcess MenuToggleNetworkEditSource = toggleNetworkEditSource
+menuEventProcess MenuLaTeXNetwork = 
+    laTeXInputNetwork Nothing (laTeXHeader <> "\n\n" <> laTeXFooter)
+menuEventProcess MenuHub = hubUpload
+-- menuEventProcess MenuHubSocket = socketConnect
+#endif
+menuEventProcess m = liftIO $ putStrLn $ "not implemented " ++ show m 
+
+-- | 
+colorPick :: MainCoroutine () 
+colorPick = colorPickerBox "Pen Color" >>= mapM_ (\c->modify (penInfo.currentTool.penColor .~ c))
+
+-- | 
+colorConvert :: Gtk.Color -> PenColor 
+colorConvert (Gtk.Color r g b) = ColorRGBA (realToFrac r/65536.0) (realToFrac g/65536.0) (realToFrac b/65536.0) 1.0 
+-- | 
+colorPickerBox :: String -> MainCoroutine (Maybe PenColor) 
+colorPickerBox msg = do 
+#ifdef GTK3 
+    -- color selection dialog is incomplete in gtk3
+    return Nothing
+#else
+    xst <- get 
+    let pcolor = view (penInfo.currentTool.penColor) xst   
+    doIOaction (action pcolor) >> go
+  where 
+    action pcolor _evhandler = do 
+      dialog <- Gtk.colorSelectionDialogNew msg
+      csel <- Gtk.colorSelectionDialogGetColor dialog
+      let (r,g,b,_a) =  convertPenColorToRGBA pcolor 
+          color = Gtk.Color (floor (r*65535.0)) (floor (g*65535.0)) (floor (b*65535.0))
+
+      Gtk.colorSelectionSetCurrentColor csel color
+      res <- Gtk.dialogRun dialog 
+      mc <- case res of 
+              Gtk.ResponseOk -> do 
+                   clrsel <- Gtk.colorSelectionDialogGetColor dialog 
+                   clr <- Gtk.colorSelectionGetCurrentColor clrsel     
+                   return (Just (colorConvert clr))
+              _ -> return Nothing 
+      Gtk.widgetDestroy dialog 
+      return (UsrEv (ColorChosen mc))
+    go = do r <- nextevent                   
+            case r of 
+              ColorChosen mc -> return mc 
+              UpdateCanvas cid -> -- this is temporary
+                invalidateInBBox Nothing Efficient cid >> go
+              _ -> go 
+#endif
diff --git a/src/Hoodle/Coroutine/Dialog.hs b/src/Hoodle/Coroutine/Dialog.hs
--- a/src/Hoodle/Coroutine/Dialog.hs
+++ b/src/Hoodle/Coroutine/Dialog.hs
@@ -1,9 +1,10 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE LambdaCase #-}
 
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.Dialog
--- Copyright   : (c) 2013 Ian-Woo Kim
+-- Copyright   : (c) 2013,2014 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
@@ -14,14 +15,15 @@
 
 module Hoodle.Coroutine.Dialog where
 
-import           Control.Lens ((%~),view)
+import           Control.Applicative ((<$>),(<*>))
+import           Control.Lens (view)
 import           Control.Monad.Loops
 import           Control.Monad.State
-import           Graphics.UI.Gtk hiding (get,set)
+import qualified Data.Foldable as F
+import qualified Data.Text as T
+import qualified Graphics.UI.Gtk as Gtk
 import           System.Directory (getCurrentDirectory)
 -- 
-import           Control.Monad.Trans.Crtn.Queue
---
 import           Hoodle.Coroutine.Draw
 import qualified Hoodle.Script.Coroutine as S
 import           Hoodle.Type.Coroutine
@@ -32,47 +34,152 @@
 
 -- |
 okMessageBox :: String -> MainCoroutine () 
-okMessageBox msg = modify (tempQueue %~ enqueue action) 
-                   >> waitSomeEvent (\case GotOk -> True ; _ -> False) 
-                   >> return () 
+okMessageBox msg = action >> waitSomeEvent (\case GotOk -> True ; _ -> False) >> return () 
   where 
-    action = mkIOaction $ 
+    action = doIOaction $ 
                \_evhandler -> do 
-                 dialog <- messageDialogNew Nothing [DialogModal]
-                   MessageQuestion ButtonsOk msg 
-                 _res <- dialogRun dialog 
-                 widgetDestroy dialog 
+                 dialog <- Gtk.messageDialogNew Nothing [Gtk.DialogModal]
+                   Gtk.MessageQuestion Gtk.ButtonsOk msg 
+                 _res <- Gtk.dialogRun dialog 
+                 Gtk.widgetDestroy dialog 
                  return (UsrEv GotOk)
 
+
 -- | 
 okCancelMessageBox :: String -> MainCoroutine Bool 
-okCancelMessageBox msg = modify (tempQueue %~ enqueue action) 
-                         >> waitSomeEvent p >>= return . q
+okCancelMessageBox msg = action >> waitSomeEvent p >>= return . q
   where 
     p (OkCancel _) = True 
     p _ = False 
     q (OkCancel b) = b 
     q _ = False 
-    action = mkIOaction $ 
+    action = doIOaction $ 
                \_evhandler -> do 
-                 dialog <- messageDialogNew Nothing [DialogModal]
-                   MessageQuestion ButtonsOkCancel msg 
-                 res <- dialogRun dialog 
+                 dialog <- Gtk.messageDialogNew Nothing [Gtk.DialogModal]
+                   Gtk.MessageQuestion Gtk.ButtonsOkCancel msg 
+                 res <- Gtk.dialogRun dialog 
                  let b = case res of 
-                           ResponseOk -> True
+                           Gtk.ResponseOk -> True
                            _ -> False
-                 widgetDestroy dialog 
+                 Gtk.widgetDestroy dialog 
                  return (UsrEv (OkCancel b))
 
+
+-- | single line text input : almost abandoned now
+textInputDialog :: String -> MainCoroutine (Maybe String) 
+textInputDialog msg = do 
+    doIOaction $ \_evhandler -> do 
+                   dialog <- Gtk.messageDialogNew Nothing [Gtk.DialogModal]
+                     Gtk.MessageQuestion Gtk.ButtonsOkCancel msg
+#ifdef GTK3
+                   vbox <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)
+                   txtvw <- Gtk.textViewNew
+                   Gtk.containerAdd vbox txtvw  
+#else 
+                   vbox <- Gtk.dialogGetUpper dialog
+                   txtvw <- Gtk.textViewNew
+                   Gtk.boxPackStart vbox txtvw Gtk.PackGrow 0 
+#endif
+                   Gtk.widgetShowAll dialog
+                   res <- Gtk.dialogRun dialog 
+                   case res of 
+                     Gtk.ResponseOk -> do 
+                       buf <- Gtk.textViewGetBuffer txtvw 
+                       (istart,iend) <- (,) <$> Gtk.textBufferGetStartIter buf
+                                            <*> Gtk.textBufferGetEndIter buf
+                       l <- Gtk.textBufferGetText buf istart iend True
+                       Gtk.widgetDestroy dialog
+                       return (UsrEv (TextInput (Just l)))
+                     _ -> do 
+                       Gtk.widgetDestroy dialog
+                       return (UsrEv (TextInput Nothing))
+    TextInput input <- waitSomeEvent (\case TextInput _ -> True ; _ -> False)
+    return input 
+
+
+
 -- | 
-fileChooser :: FileChooserAction -> Maybe String -> MainCoroutine (Maybe FilePath) 
+keywordDialog :: [T.Text] -> MainCoroutine (Maybe T.Text)
+keywordDialog keylst = do
+    doIOaction (keywordDialog' keylst)
+    keywordLoop
+
+-- |
+keywordDialog' :: [T.Text] -> (AllEvent -> IO ()) -> IO AllEvent
+keywordDialog' keys = \_evhandler -> do
+    dialog <- Gtk.dialogNew
+#ifdef GTK3
+    upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)
+    vbox <- Gtk.vBoxNew False 0 
+    Gtk.containerAdd upper vbox
+#else
+    vbox <- Gtk.dialogGetUpper dialog
+#endif
+    hbox <- Gtk.hBoxNew False 0
+    Gtk.boxPackStart vbox hbox Gtk.PackNatural 0
+    _btnOk <- Gtk.dialogAddButton dialog ("Ok" :: String) Gtk.ResponseOk
+    _btnCancel <- Gtk.dialogAddButton dialog ("Cancel" :: String) Gtk.ResponseCancel
+    cbx <- Gtk.comboBoxNewText 
+    klst <- mapM (Gtk.comboBoxAppendText cbx) keys
+    when ((not.null) klst) $ 
+      Gtk.comboBoxSetActive cbx (head klst)
+    Gtk.boxPackStart hbox cbx Gtk.PackGrow 2
+    Gtk.widgetShowAll dialog
+    res <- Gtk.dialogRun dialog
+    Gtk.widgetDestroy dialog
+    case res of 
+      Gtk.ResponseOk -> do
+        keystr <- Gtk.comboBoxGetActiveText cbx
+        (return . UsrEv . Keyword) keystr
+      Gtk.ResponseCancel -> return (UsrEv (Keyword Nothing))
+      _ -> return (UsrEv (Keyword Nothing))
+
+-- | main event loop for keyword dialog
+keywordLoop :: MainCoroutine (Maybe T.Text)
+keywordLoop = waitSomeEvent (\case Keyword _ -> True ; _ -> False ) >>= \(Keyword x) -> return x
+
+
+-- |
+longTextMessageBox :: String -> MainCoroutine () 
+longTextMessageBox msg = action
+                         >> waitSomeEvent (\case GotOk -> True ; _ -> False) 
+                         >> return () 
+  where 
+    action = doIOaction $ 
+               \_evhandler -> do 
+                 dialog <- Gtk.dialogNew
+
+#ifdef GTK3
+                 upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)
+                 vbox <- Gtk.vBoxNew False 0 
+                 Gtk.containerAdd upper vbox
+#else
+                 vbox <- Gtk.dialogGetUpper dialog
+#endif
+                 hbox <- Gtk.hBoxNew False 0
+                 txtbuf <- Gtk.textBufferNew Nothing
+                 Gtk.textBufferSetText txtbuf msg
+                 txtview <- Gtk.textViewNewWithBuffer txtbuf
+                 vadj <- Gtk.textViewGetVadjustment txtview
+                 vscr <- Gtk.vScrollbarNew vadj
+                 Gtk.widgetSetSizeRequest txtview 400 700
+                 Gtk.boxPackEnd hbox vscr Gtk.PackNatural 0 
+                 Gtk.boxPackStart hbox txtview Gtk.PackGrow 0
+                 Gtk.boxPackStart vbox hbox Gtk.PackGrow 0
+                 _btnOk <- Gtk.dialogAddButton dialog ("Ok" :: String) Gtk.ResponseOk
+                 Gtk.widgetShowAll dialog
+                 _res <- Gtk.dialogRun dialog 
+                 Gtk.widgetDestroy dialog 
+                 return (UsrEv GotOk)
+
+-- | 
+fileChooser :: Gtk.FileChooserAction -> Maybe String -> MainCoroutine (Maybe FilePath) 
 fileChooser choosertyp mfname = do 
     mrecentfolder <- S.recentFolderHook 
     xst <- get 
     let rtrwin = view rootOfRootWindow xst 
-    liftIO $ widgetQueueDraw rtrwin 
-        
-    modify (tempQueue %~ enqueue (action rtrwin mrecentfolder)) >> go 
+    liftIO $ Gtk.widgetQueueDraw rtrwin 
+    doIOaction (action rtrwin mrecentfolder) >> go
   where 
     go = do r <- nextevent                   
             case r of 
@@ -80,22 +187,22 @@
               UpdateCanvas cid -> -- this is temporary
                                   invalidateInBBox Nothing Efficient cid >> go  
               _ -> go 
-    action win mrf = mkIOaction $ \_evhandler -> do 
-      dialog <- fileChooserDialogNew Nothing (Just win) choosertyp 
-                  [ ("OK", ResponseOk) 
-                  , ("Cancel", ResponseCancel) ]
+    action win mrf _evhandler = do 
+      dialog <- Gtk.fileChooserDialogNew Nothing (Just win) choosertyp 
+                  [ ("OK", Gtk.ResponseOk) 
+                  , ("Cancel", Gtk.ResponseCancel) ]
       case mrf of 
-        Just rf -> fileChooserSetCurrentFolder dialog rf 
-        Nothing -> getCurrentDirectory >>= fileChooserSetCurrentFolder dialog 
-      maybe (return ()) (fileChooserSetCurrentName dialog) mfname 
+        Just rf -> Gtk.fileChooserSetCurrentFolder dialog rf 
+        Nothing -> getCurrentDirectory >>= Gtk.fileChooserSetCurrentFolder dialog 
+      F.mapM_ (Gtk.fileChooserSetCurrentName dialog) mfname 
       --   !!!!!! really hackish solution !!!!!!
-      whileM_ (liftM (>0) eventsPending) (mainIterationDo False)
+      whileM_ (liftM (>0) Gtk.eventsPending) (Gtk.mainIterationDo False)
       
-      res <- dialogRun dialog
+      res <- Gtk.dialogRun dialog
       mr <- case res of 
-              ResponseDeleteEvent -> return Nothing
-              ResponseOk ->  fileChooserGetFilename dialog 
-              ResponseCancel -> return Nothing 
+              Gtk.ResponseDeleteEvent -> return Nothing
+              Gtk.ResponseOk ->  Gtk.fileChooserGetFilename dialog 
+              Gtk.ResponseCancel -> return Nothing 
               _ -> putStrLn "??? in fileOpen" >> return Nothing 
-      widgetDestroy dialog
+      Gtk.widgetDestroy dialog
       return (UsrEv (FileChosen mr))
diff --git a/src/Hoodle/Coroutine/Draw.hs b/src/Hoodle/Coroutine/Draw.hs
--- a/src/Hoodle/Coroutine/Draw.hs
+++ b/src/Hoodle/Coroutine/Draw.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE LambdaCase #-}
@@ -7,9 +8,9 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.Draw 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -20,9 +21,8 @@
 
 -- from other packages
 import           Control.Applicative
-import           Control.Concurrent
--- import           Control.Concurrent.STM
-import           Control.Lens (view,set,(^.),(%~))
+import           Control.Concurrent.STM (atomically, modifyTVar')
+import           Control.Lens
 import           Control.Monad
 import           Control.Monad.State
 import           Control.Monad.Trans.Reader (runReaderT)
@@ -31,13 +31,14 @@
 import           Data.Time.Clock
 import           Data.Time.LocalTime
 import qualified Graphics.Rendering.Cairo as Cairo
-import           Graphics.UI.Gtk hiding (get,set)
+import qualified Graphics.UI.Gtk as Gtk
 -- from hoodle-platform
 import           Control.Monad.Trans.Crtn
 import           Control.Monad.Trans.Crtn.Object
 import           Control.Monad.Trans.Crtn.Queue
 import           Data.Hoodle.BBox
-import           Graphics.Hoodle.Render.Type.Renderer
+import           Graphics.Hoodle.Render.Type
+-- import           Graphics.Hoodle.Render.Type.Renderer
 -- from this package
 import           Hoodle.Accessor
 import           Hoodle.Type.Alias
@@ -48,18 +49,19 @@
 import           Hoodle.Type.PageArrangement
 import           Hoodle.Type.HoodleState
 import           Hoodle.Type.Widget
+import           Hoodle.Util
 import           Hoodle.View.Draw
--- import           Hoodle.Widget.Clock
 -- 
 
 
--- | 
+-- | all event
 nextevent :: MainCoroutine UserEvent 
 nextevent = do Arg DoEvent ev <- request (Res DoEvent ())
                case ev of
                  SysEv sev -> sysevent sev >> nextevent 
                  UsrEv uev -> return uev 
 
+-- | system event 
 sysevent :: SystemEvent -> MainCoroutine () 
 sysevent ClockUpdateEvent = do 
   utctime <- liftIO $ getCurrentTime 
@@ -69,29 +71,44 @@
       (h,m,s) :: (Int,Int,Int) = 
         (,,) <$> (\x->todHour x `mod` 12) <*> todMin <*> (floor . todSec) 
         $ ltimeofday
-  -- liftIO $ print (h,m,s)
   xst <- get 
-  let cinfo = view currentCanvasInfo xst
+  let uhdl = view (unitHoodles.currentUnit) xst
+      cinfo = view currentCanvasInfo uhdl
       cwgts = view (unboxLens canvasWidgets) cinfo   
       nwgts = set (clockWidgetConfig.clockWidgetTime) (h,m,s) cwgts
       ncinfo = set (unboxLens canvasWidgets) nwgts cinfo
-  put . set currentCanvasInfo ncinfo $ xst 
-              
+  pureUpdateUhdl (const ((currentCanvasInfo .~ ncinfo) uhdl))
   when (view (widgetConfig.doesUseClockWidget) cwgts) $ do 
-    let cid = getCurrentCanvasId xst
+    let cid = getCurrentCanvasId uhdl
     modify (tempQueue %~ enqueue (Right (UsrEv (UpdateCanvasEfficient cid))))
-    -- invalidateInBBox Nothing Efficient cid   
 sysevent (RenderCacheUpdate (uuid, ssfc)) = do
-  -- liftIO $ putStrLn "RenderCacheUpdate"
-  modify (renderCache %~ HM.insert uuid ssfc)
+  cachevar <- view renderCacheVar <$> get
+  liftIO $ atomically $ modifyTVar' cachevar (HM.insert uuid ssfc) 
   b <- ( ^. doesNotInvalidate ) <$> get
   when (not b) $ invalidateAll
-  
-
-  -- invalidateInBBox Nothing Efficient cid   
-sysevent ev = liftIO $ print ev 
-
+sysevent ev = msgShout (show ev)
 
+-- | update flag in HoodleState when corresponding toggle UI changed 
+updateFlagFromToggleUI :: String  -- ^ UI toggle button id
+                       -> Simple Lens HoodleState Bool -- ^ lens for flag 
+                       -> MainCoroutine Bool
+updateFlagFromToggleUI toggleid lensforflag = do 
+  xstate <- get 
+  let ui = view gtkUIManager xstate 
+  doIOaction $ \_ -> do
+    agr <- Gtk.uiManagerGetActionGroups ui >>= \x ->
+             case x of 
+               [] -> error "No action group? "
+               y:_ -> return y 
+    togglea <- Gtk.actionGroupGetAction agr toggleid 
+                 >>= maybe (error "updateFlagFromToggleUI") 
+                           (return . Gtk.castToToggleAction)
+    b <- Gtk.toggleActionGetActive togglea
+    return (UsrEv (UIEv (UIGetFlag b)))
+  UIEv (UIGetFlag b) <- 
+    waitSomeEvent (\case UIEv (UIGetFlag _) -> True ; _ -> False) 
+  modify (set lensforflag b) >> return b 
+  
 -- |
 data DrawingFunctionSet = 
   DrawingFunctionSet { singleEditDraw :: DrawingFunction SinglePage EditMode
@@ -108,46 +125,48 @@
                   -> DrawingFunction ContinuousPage SelectMode
                   -> MainCoroutine () 
 invalidateGeneral cid mbbox flag drawf drawfsel drawcont drawcontsel = do 
-    xst <- get 
-    unboxBiAct (fsingle xst) (fcont xst) . getCanvasInfo cid $ xst
+    xst <- get
+    let uhdl = view (unitHoodles.currentUnit) xst
+    cache <- renderCache
+    unboxBiAct (fsingle cache uhdl) (fcont cache uhdl) . getCanvasInfo cid $ uhdl
   where 
-    fsingle :: HoodleState -> CanvasInfo SinglePage -> MainCoroutine () 
-    fsingle xstate cvsInfo = do 
+    fsingle :: RenderCache -> UnitHoodle -> CanvasInfo SinglePage -> MainCoroutine () 
+    fsingle cache uhdl cvsInfo = do 
       let cpn = PageNum . view currentPageNum $ cvsInfo 
-	  isCurrentCvs = cid == getCurrentCanvasId xstate
-	  epage = getCurrentPageEitherFromHoodleModeState cvsInfo (view hoodleModeState xstate)
+	  isCurrentCvs = cid == getCurrentCanvasId uhdl
+	  epage = getCurrentPageEitherFromHoodleModeState cvsInfo (view hoodleModeState uhdl)
+          cvsid = view canvasId cvsInfo
 	  cvs = view drawArea cvsInfo
 	  msfc = view mDrawSurface cvsInfo 
-	  cache = view renderCache xstate
       case epage of 
 	Left page -> do  
-	  liftIO (unSinglePageDraw drawf cache isCurrentCvs (cvs,msfc) (cpn,page)
+	  liftIO (unSinglePageDraw drawf cache cvsid isCurrentCvs (cvs,msfc) (cpn,page)
 		  <$> view viewInfo <*> pure mbbox <*> pure flag $ cvsInfo )
 	  return ()
 	Right tpage -> do 
-	  liftIO (unSinglePageDraw drawfsel cache isCurrentCvs (cvs,msfc) (cpn,tpage)
+	  liftIO (unSinglePageDraw drawfsel cache cvsid isCurrentCvs (cvs,msfc) (cpn,tpage)
 		  <$> view viewInfo <*> pure mbbox <*> pure flag $ cvsInfo )
 	  return ()
-    fcont :: HoodleState -> CanvasInfo ContinuousPage -> MainCoroutine () 
-    fcont xstate cvsInfo = do 
-      let hdlmodst = view hoodleModeState xstate 
-	  isCurrentCvs = cid == getCurrentCanvasId xstate
-	  cache = view renderCache xstate
+    fcont :: RenderCache -> UnitHoodle -> CanvasInfo ContinuousPage -> MainCoroutine () 
+    fcont cache uhdl cvsInfo = do 
+      let hdlmodst = view hoodleModeState uhdl 
+	  isCurrentCvs = cid == getCurrentCanvasId uhdl
       case hdlmodst of 
 	ViewAppendState hdl -> do  
 	  hdl' <- liftIO (unContPageDraw drawcont cache isCurrentCvs cvsInfo mbbox hdl flag)
-	  put (set hoodleModeState (ViewAppendState hdl') xstate)
+          pureUpdateUhdl (const ((hoodleModeState .~ ViewAppendState hdl') uhdl))
 	SelectState thdl -> do 
 	  thdl' <- liftIO (unContPageDraw drawcontsel cache isCurrentCvs cvsInfo mbbox thdl flag)
-	  put (set hoodleModeState (SelectState thdl') xstate) 
+          pureUpdateUhdl (const ((hoodleModeState .~ SelectState thdl') uhdl))
           
 -- |         
 
 invalidateOther :: MainCoroutine () 
 invalidateOther = do 
-  xstate <- get
-  let currCvsId = getCurrentCanvasId xstate
-      cinfoMap  = getCanvasInfoMap xstate
+  xst <- get
+  let uhdl = view (unitHoodles.currentUnit) xst
+      currCvsId = getCurrentCanvasId uhdl
+      cinfoMap  = view cvsInfoMap uhdl
       keys = M.keys cinfoMap 
   mapM_ invalidate (filter (/=currCvsId) keys)
   
@@ -160,10 +179,11 @@
                     -> DrawFlag 
                     -> CanvasId -> MainCoroutine ()
 invalidateInBBox mbbox flag cid = do 
-  xst <- get 
-  geometry <- liftIO $ getCanvasGeometryCvsId cid xst 
-  invalidateGeneral cid mbbox flag 
-    (drawSinglePage geometry) (drawSinglePageSel geometry) (drawContHoodle geometry) (drawContHoodleSel geometry)
+    xst <- get 
+    let uhdl = view (unitHoodles.currentUnit) xst
+    geometry <- liftIO $ getCanvasGeometryCvsId cid uhdl
+    invalidateGeneral cid mbbox flag 
+      (drawSinglePage geometry) (drawSinglePageSel geometry) (drawContHoodle geometry) (drawContHoodleSel geometry)
 
 -- | 
 invalidateAllInBBox :: Maybe BBox -- ^ desktop coordinate 
@@ -173,26 +193,35 @@
 
 -- | 
 invalidateAll :: MainCoroutine () 
-invalidateAll = invalidateAllInBBox Nothing Clear -- >> liftIO (putStrLn "The SLOW invalidateAll Called")
+invalidateAll = invalidateAllInBBox Nothing Clear
  
 -- | Invalidate Current canvas
 invalidateCurrent :: MainCoroutine () 
-invalidateCurrent = invalidate . getCurrentCanvasId =<< get
+invalidateCurrent = invalidate . getCurrentCanvasId . view (unitHoodles.currentUnit) =<< get
        
 -- | Drawing temporary gadgets
 invalidateTemp :: CanvasId -> Cairo.Surface -> Cairo.Render () -> MainCoroutine ()
 invalidateTemp cid tempsurface rndr = do 
     xst <- get 
-    forBoth' unboxBiAct (fsingle xst) . getCanvasInfo cid $ xst 
+    let uhdl = view (unitHoodles.currentUnit) xst
+    forBoth' unboxBiAct (fsingle uhdl) . getCanvasInfo cid $ uhdl
   where 
-    fsingle :: HoodleState -> CanvasInfo a -> MainCoroutine ()   
-    fsingle xstate cvsInfo = do 
+    fsingle :: UnitHoodle -> CanvasInfo a -> MainCoroutine ()   
+    fsingle uhdl cvsInfo = do 
       let canvas = view drawArea cvsInfo
           pnum = PageNum . view currentPageNum $ cvsInfo 
-      geometry <- liftIO $ getCanvasGeometryCvsId cid xstate
-      win <- liftIO $ widgetGetDrawWindow canvas
+      geometry <- liftIO $ getCanvasGeometryCvsId cid uhdl
+#ifdef GTK3          
+      Just win <- liftIO $ Gtk.widgetGetWindow canvas
+#else
+      win <- liftIO $ Gtk.widgetGetDrawWindow canvas
+#endif 
       let xformfunc = cairoXform4PageCoordinate (mkXform4Page geometry pnum)
-      liftIO $ renderWithDrawable win $ do   
+#ifdef GTK3              
+      liftIO $ Gtk.renderWithDrawWindow win $ do 
+#else 
+      liftIO $ Gtk.renderWithDrawable win $ do   
+#endif
                  Cairo.setSourceSurface tempsurface 0 0 
                  Cairo.setOperator Cairo.OperatorSource 
                  Cairo.paint 
@@ -207,15 +236,24 @@
                        -> MainCoroutine ()
 invalidateTempBasePage cid tempsurface pnum rndr = do 
     xst <- get 
-    forBoth' unboxBiAct (fsingle xst) . getCanvasInfo cid $ xst 
+    let uhdl = view (unitHoodles.currentUnit) xst
+    forBoth' unboxBiAct (fsingle uhdl) . getCanvasInfo cid $ uhdl
   where 
-    fsingle :: HoodleState -> CanvasInfo a -> MainCoroutine ()
-    fsingle xstate cvsInfo = do 
+    fsingle :: UnitHoodle -> CanvasInfo a -> MainCoroutine ()
+    fsingle uhdl cvsInfo = do 
       let canvas = view drawArea cvsInfo
-      geometry <- liftIO $ getCanvasGeometryCvsId cid xstate
-      win <- liftIO $ widgetGetDrawWindow canvas
+      geometry <- liftIO $ getCanvasGeometryCvsId cid uhdl
+#ifdef GTK3          
+      Just win <- liftIO $ Gtk.widgetGetWindow canvas
+#else
+      win <- liftIO $ Gtk.widgetGetDrawWindow canvas
+#endif
       let xformfunc = cairoXform4PageCoordinate (mkXform4Page geometry pnum)
-      liftIO $ renderWithDrawable win $ do   
+#ifdef GTK3              
+      liftIO $ Gtk.renderWithDrawWindow win $ do   
+#else 
+      liftIO $ Gtk.renderWithDrawable win $ do   
+#endif
                  Cairo.setSourceSurface tempsurface 0 0 
                  Cairo.setOperator Cairo.OperatorSource 
                  Cairo.paint 
@@ -232,14 +270,29 @@
         invalidateInBBox Nothing Efficient cid >> waitSomeEvent p  
       _ -> if  p r then return r else waitSomeEvent p  
 
+-- | 
+doIOaction_ :: IO a -> MainCoroutine ()
+doIOaction_ action = do doIOaction $ \_ -> action >> return (UsrEv ActionOrdered)
+                        waitSomeEvent (\case ActionOrdered -> True; _ -> False );
+                        return ()
 
+defaultHandler :: (AllEvent -> IO ()) -> RendererEvent -> IO ()
+defaultHandler evhandler (SurfaceUpdate s) = 
+    Gtk.postGUIAsync . evhandler . SysEv . RenderCacheUpdate $ s
+defaultHandler evhandler (FinishCommandFor sfcid) =  
+    Gtk.postGUIAsync . evhandler . UsrEv . RenderEv . FinishCommand $ sfcid
+
+
+-- | order rendering routine
 callRenderer :: Renderer RenderEvent -> MainCoroutine ()
 callRenderer action = do
-    tvar <- (^. pdfRenderQueue) <$> get  
+    (tvarpdf,tvargen,tvarcache) <- ((,,)<$>(^. pdfRenderQueue)<*>(^. genRenderQueue)<*>(^. renderCacheVar))<$>get  
     doIOaction $ \evhandler -> do
-      let handler = postGUIAsync . evhandler . SysEv . RenderCacheUpdate
-      UsrEv . RenderEv <$> runReaderT action (handler,tvar)
-
+      -- let handler (SurfaceUpdate s) = 
+      --       Gtk.postGUIAsync . evhandler . SysEv . RenderCacheUpdate $ s
+      --     handler (FinishCommandFor sfcid) =
+      --       Gtk.postGUIAsync . evhandler . UsrEv . RenderEv . FinishCommand $ sfcid
+      UsrEv . RenderEv <$> runReaderT action (RendererState (defaultHandler evhandler) tvarpdf tvargen tvarcache)
 
 callRenderer_ :: Renderer a -> MainCoroutine ()
 callRenderer_ action = do
diff --git a/src/Hoodle/Coroutine/Eraser.hs b/src/Hoodle/Coroutine/Eraser.hs
--- a/src/Hoodle/Coroutine/Eraser.hs
+++ b/src/Hoodle/Coroutine/Eraser.hs
@@ -1,9 +1,9 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.Eraser 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -13,10 +13,9 @@
 module Hoodle.Coroutine.Eraser where
 
 import qualified Data.IntMap as IM
-import           Control.Lens (view,set,over)
+import           Control.Lens (view,set,over,(.~))
 import           Control.Monad.State 
 import qualified Control.Monad.State as St
--- import Graphics.UI.Gtk hiding (get,set,disconnect)
 -- 
 import Data.Hoodle.Generic
 import Graphics.Hoodle.Render
@@ -43,9 +42,9 @@
 -- |
 eraserStart :: CanvasId 
                -> PointerCoord 
-               -> MainCoroutine () 
-eraserStart cid = commonPenStart eraserAction cid  
-  where eraserAction _cinfo pnum geometry (x,y) = do 
+               -> MainCoroutine ()
+eraserStart cid = commonPenStart eraserAction cid  >=> const (return ())
+  where eraserAction _cinfo pnum geometry (x,y) _ = do 
           itms <- rItmsInCurrLyr
           eraserProcess cid pnum geometry itms (x,y)
 
@@ -60,7 +59,7 @@
 eraserProcess cid pnum geometry itms (x0,y0) = do 
     r <- nextevent 
     xst <- get
-    forBoth' unboxBiAct (f r xst) . getCanvasInfo cid $ xst 
+    forBoth' unboxBiAct (f r xst) . getCanvasInfo cid . view (unitHoodles.currentUnit) $ xst 
   where 
     f :: UserEvent -> HoodleState -> CanvasInfo a -> MainCoroutine ()
     f r xstate cvsInfo = penMoveAndUpOnly r pnum geometry defact 
@@ -75,19 +74,18 @@
       if hitState 
         then do 
           page <- getCurrentPageCvsId cid 
-          let currhdl     = unView . view hoodleModeState $ xstate 
-              dim         = view gdimension page
+          let uhdl = view (unitHoodles.currentUnit) xstate
+              currhdl     = unView . view hoodleModeState $ uhdl
               pgnum       = view currentPageNum cvsInfo
               currlayer   = getCurrentLayer page
-              cache       = view renderCache xstate
-          let (newitms,maybebbox) = St.runState (eraseHitted hittestitem) Nothing
-          newlayerbbox <- liftIO . updateLayerBuf cache dim maybebbox 
-                          . set gitems newitms $ currlayer 
+          let (newitms,_maybebbox) = St.runState (eraseHitted hittestitem) Nothing
+              newlayerbbox = set gitems newitms currlayer
+          callRenderer_ $ updateLayerBuf cid newlayerbbox
           let newpagebbox = adjustCurrentLayer newlayerbbox page 
               newhdlbbox = over gpages (IM.adjust (const newpagebbox) pgnum) currhdl
               newhdlmodst = ViewAppendState newhdlbbox
-          commit . set hoodleModeState newhdlmodst 
-            =<< (liftIO (updatePageAll newhdlmodst xstate))
+          uhdl' <- liftIO (updatePageAll newhdlmodst uhdl)
+          commit $ (unitHoodles.currentUnit .~ ((hoodleModeState .~ newhdlmodst) uhdl')) xstate
           invalidateInBBox Nothing Efficient cid 
           nitms <- rItmsInCurrLyr
           eraserProcess cid pnum geometry nitms (x,y)
diff --git a/src/Hoodle/Coroutine/File.hs b/src/Hoodle/Coroutine/File.hs
--- a/src/Hoodle/Coroutine/File.hs
+++ b/src/Hoodle/Coroutine/File.hs
@@ -6,9 +6,9 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.File 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -18,34 +18,34 @@
 module Hoodle.Coroutine.File where
 
 -- from other packages
-import           Control.Applicative ((<$>),(<*>))
-import           Control.Concurrent
-import           Control.Lens (view,set,over,(%~), (.~))
+import           Control.Applicative
+import           Control.Lens (at,view,set,over,(.~))
 import           Control.Monad.State hiding (mapM,mapM_,forM_)
 import           Control.Monad.Trans.Either
 import           Control.Monad.Trans.Maybe (MaybeT(..))
--- import           Control.Monad.Trans.Reader (runReaderT)
-import           Data.Attoparsec (parseOnly)
+import           Data.Attoparsec.ByteString.Char8 (parseOnly)
 import           Data.ByteString.Char8 as B (pack,unpack,readFile)
 import qualified Data.ByteString.Lazy as L
 import           Data.Digest.Pure.MD5 (md5)
 import           Data.Foldable (mapM_,forM_)
 import qualified Data.List as List 
 import           Data.Maybe
-import qualified Data.IntMap as IM
 import           Data.Time.Clock
-import           Filesystem.Path.CurrentOS (decodeString, encodeString)
 import qualified Graphics.Rendering.Cairo as Cairo
-import qualified Graphics.UI.Gtk as Gtk -- hiding (get,set)
+import qualified Graphics.UI.Gtk as Gtk 
 import           System.Directory
 import           System.FilePath
-import qualified System.FSNotify as FS
 import           System.IO (hClose, hFileSize, openFile, IOMode(..))
 import           System.Process 
+#ifdef HUB
+import           Control.Concurrent
+import qualified Control.Exception as E
+import           Control.Monad.Trans.Reader
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as TE
+#endif
 -- from hoodle-platform
 import           Control.Monad.Trans.Crtn
-import           Control.Monad.Trans.Crtn.Queue 
--- import           Data.Hoodle.BBox
 import           Data.Hoodle.Generic
 import           Data.Hoodle.Simple
 import           Data.Hoodle.Select
@@ -54,49 +54,55 @@
 import           Graphics.Hoodle.Render.Item
 import           Graphics.Hoodle.Render.Type
 import           Graphics.Hoodle.Render.Type.HitTest 
+import           Hoodle.Publish.PDF (renderHoodleToPDF)
 import           Text.Hoodle.Builder 
 import           Text.Hoodle.Migrate.FromXournal
 import qualified Text.Hoodlet.Parse.Attoparsec as Hoodlet
 import qualified Text.Xournal.Parse.Conduit as XP
--- import qualified Text.Hoodlet.Parse.Attoparsec as Hoodlet
 -- from this package 
 import           Hoodle.Accessor
 import           Hoodle.Coroutine.Dialog
 import           Hoodle.Coroutine.Draw
 import           Hoodle.Coroutine.Commit
+import           Hoodle.Coroutine.Layer
 import           Hoodle.Coroutine.Minibuffer
 import           Hoodle.Coroutine.Mode 
 import           Hoodle.Coroutine.Page
 import           Hoodle.Coroutine.Scroll
+import           Hoodle.Coroutine.Select.Clipboard
 import           Hoodle.Coroutine.TextInput
--- import           Hoodle.Coroutine.Window
+import           Hoodle.GUI.Reflect
 import           Hoodle.ModelAction.File
 import           Hoodle.ModelAction.Layer 
 import           Hoodle.ModelAction.Page
 import           Hoodle.ModelAction.Select
--- import           Hoodle.ModelAction.Select.Transform
 import           Hoodle.ModelAction.Window
 import qualified Hoodle.Script.Coroutine as S
 import           Hoodle.Script.Hook
 import           Hoodle.Type.Canvas
 import           Hoodle.Type.Coroutine
+import           Hoodle.Type.Enum
 import           Hoodle.Type.Event hiding (TypSVG)
 import           Hoodle.Type.HoodleState
 import           Hoodle.Type.PageArrangement
 import           Hoodle.Util
+#ifdef HUB
+import           Hoodle.Coroutine.Hub
+import           Hoodle.Coroutine.Hub.Common
+import           Hoodle.Coroutine.HubInternal
+import           Hoodle.Type.Hub
+import           Hoodle.Type.Synchronization
+#endif
 --
 import Prelude hiding (readFile,concat,mapM,mapM_)
 
 -- | 
 askIfSave :: MainCoroutine () -> MainCoroutine () 
 askIfSave action = do 
-    xstate <- get 
-    if not (view isSaved xstate)
-      then do  
-        b <- okCancelMessageBox "Current canvas is not saved yet. Will you proceed without save?" 
-        case b of 
-          True -> action 
-          False -> return () 
+    uhdl <- view (unitHoodles.currentUnit) <$> get 
+    if not (view isSaved uhdl)
+      then 
+        okCancelMessageBox "Current canvas is not saved yet. Will you proceed without save?" >>= flip when action
       else action 
 
 -- | 
@@ -110,9 +116,9 @@
       else action 
 
 
--- | get file content from xournal file and update xournal state 
-getFileContent :: Maybe FilePath -> MainCoroutine ()
-getFileContent (Just fname) = do 
+-- | get file content from xournal file and update hoodle state 
+getFileContent :: FileStore -> MainCoroutine ()
+getFileContent store@(LocalDir (Just fname)) = do 
     xstate <- get
     let ext = takeExtension fname
     case ext of 
@@ -124,39 +130,75 @@
           Right h -> do 
             constructNewHoodleStateFromHoodle h
             ctime <- liftIO $ getCurrentTime
-            modify ( hoodleFileControl.hoodleFileName .~ Just fname )
-            modify ( hoodleFileControl.lastSavedTime  .~ Just ctime )
+#ifdef HUB
+            -- let uhdluuid = view (unitHoodles.currentUnit.unitUUID) xstate
+            msqlfile <- view (settings.sqliteFileName) <$> get
+            let fileuuidbstr = view hoodleID h
+                fileuuidtxt = TE.decodeUtf8 fileuuidbstr
+            liftIO $ print fileuuidtxt
+            mfstat <- case msqlfile of
+              Nothing -> return Nothing
+              Just sqlfile -> liftIO (getLastSyncStatus sqlfile fileuuidtxt)
+            let mmd5 = fileSyncStatusMd5 <$> mfstat
+#else 
+            let mmd5 = Nothing 
+#endif    
+            pureUpdateUhdl ( (hoodleFileControl.hoodleFileName .~ store)
+                           . (hoodleFileControl.lastSavedTime  .~ Just ctime) 
+                           . (hoodleFileControl.syncMD5History .~ maybeToList mmd5)  )
             commit_
       ".xoj" -> do 
           liftIO (XP.parseXojFile fname) >>= \x -> case x of  
-            Left str -> liftIO $ putStrLn $ "file reading error : " ++ str 
+            Left str -> msgShout $ "file reading error : " ++ str 
             Right xojcontent -> do 
               hdlcontent <- liftIO $ mkHoodleFromXournal xojcontent 
               constructNewHoodleStateFromHoodle hdlcontent
               ctime <- liftIO $ getCurrentTime 
-              modify ( hoodleFileControl.hoodleFileName .~ Just fname )
-              modify ( hoodleFileControl.lastSavedTime  .~ Just ctime ) 
+              pureUpdateUhdl ( (hoodleFileControl.hoodleFileName .~ LocalDir Nothing)
+                             . (hoodleFileControl.lastSavedTime  .~ Just ctime) )
               commit_
       ".pdf" -> do 
         let doesembed = view (settings.doesEmbedPDF) xstate
         mhdl <- liftIO $ makeNewHoodleWithPDF doesembed fname 
         case mhdl of 
-          Nothing -> getFileContent Nothing
+          Nothing -> getFileContent (LocalDir Nothing)
           Just hdl -> do 
             constructNewHoodleStateFromHoodle hdl
-            modify ( hoodleFileControl.hoodleFileName .~ Nothing)
+            pureUpdateUhdl (hoodleFileControl.hoodleFileName .~ LocalDir Nothing)
             commit_
-      _ -> getFileContent Nothing    
+      _ -> getFileContent (LocalDir Nothing)
     xstate' <- get
-    doIOaction $ \evhandler -> do 
-      Gtk.postGUIAsync (setTitleFromFileName xstate')
-      return (UsrEv ActionOrdered)
-    ActionOrdered <- waitSomeEvent (\case ActionOrdered -> True ; _ -> False )
-    return ()
-getFileContent Nothing = do
+    doIOaction_ $ Gtk.postGUIAsync (setTitleFromFileName xstate')
+getFileContent (LocalDir Nothing) = do
     constructNewHoodleStateFromHoodle =<< liftIO defaultHoodle 
-    modify ( hoodleFileControl.hoodleFileName .~ Nothing ) 
+    pureUpdateUhdl (hoodleFileControl.hoodleFileName .~ LocalDir Nothing) 
     commit_ 
+#ifdef HUB
+getFileContent store@(TempDir fname) = do 
+    -- xstate <- get
+    -- let uhdluuid = view (unitHoodles.currentUnit.unitUUID) xstate
+    let ext = takeExtension fname
+    when (ext == ".hdl") $ do
+      bstr <- liftIO $ B.readFile fname
+      r <- liftIO $ checkVersionAndMigrate bstr 
+      case r of 
+        Left err -> liftIO $ putStrLn err
+        Right h -> do 
+          constructNewHoodleStateFromHoodle h
+          ctime <- liftIO $ getCurrentTime
+          let -- fileuuidbstr = view hoodleID h
+              -- fileuuidtxt = TE.decodeUtf8 fileuuidbstr
+              md5txt = T.pack . show . md5 . L.fromStrict $ bstr
+          pureUpdateUhdl ( (hoodleFileControl.hoodleFileName .~ store)
+                         . (hoodleFileControl.lastSavedTime  .~ Just ctime) 
+                         . (hoodleFileControl.syncMD5History .~ [md5txt] ) 
+                         )
+          commit_
+          xstate' <- get
+          doIOaction_ $ Gtk.postGUIAsync (setTitleFromFileName xstate')
+#else
+getFileContent _ = return ()
+#endif
 
 
 -- |
@@ -164,32 +206,35 @@
 constructNewHoodleStateFromHoodle hdl' = do 
     callRenderer $ cnstrctRHoodle hdl' >>= return . GotRHoodle
     RenderEv (GotRHoodle rhdl) <- waitSomeEvent (\case RenderEv (GotRHoodle _) -> True; _ -> False)
-    modify (hoodleModeState .~ ViewAppendState rhdl)
-
+    pureUpdateUhdl (hoodleModeState .~ ViewAppendState rhdl)
 
--- | 
+-- | deprecated
 fileNew :: MainCoroutine () 
-fileNew = do  
-    getFileContent Nothing
-    xstate' <- get 
-    ncvsinfo <- liftIO $ setPage xstate' 0 (getCurrentCanvasId xstate')
-    xstate'' <- return $ over currentCanvasInfo (const ncvsinfo) xstate'
-    liftIO $ setTitleFromFileName xstate''
-    commit xstate'' 
+fileNew = do 
+    getFileContent (LocalDir Nothing)
+    updateUhdl $ \uhdl -> do
+      ncvsinfo <- liftIO $ setPage uhdl 0 (getCurrentCanvasId uhdl)
+      return $ (currentCanvasInfo .~ ncvsinfo) uhdl
+    xst <- get
+    liftIO (setTitleFromFileName xst)
+    commit_
     invalidateAll 
 
 -- | 
 fileSave :: MainCoroutine ()
 fileSave = do 
-    xstate <- get 
-    case view (hoodleFileControl.hoodleFileName) xstate of
+    uhdl <- view (unitHoodles.currentUnit) <$> get
+    case getHoodleFilePath uhdl of
       Nothing -> fileSaveAs 
       Just filename -> do     
         -- this is rather temporary not to make mistake 
         if takeExtension filename == ".hdl" 
           then do 
-             put =<< (liftIO (saveHoodle xstate))
-             (S.afterSaveHook filename . rHoodle2Hoodle . getHoodle) xstate
+             updateUhdl $ liftIO . saveHoodle . const uhdl 
+             (S.afterSaveHook filename . rHoodle2Hoodle . getHoodle) uhdl
+#ifdef HUB
+             hubUpload
+#endif
           else fileExtensionInvalid (".hdl","save") >> fileSaveAs 
 
 -- | interleaving a monadic action between each pair of subsequent actions
@@ -199,63 +244,16 @@
 sequence1_ i (a:as) = a >> i >> sequence1_ i as 
 
 -- | 
-renderjob :: RenderCache -> RHoodle -> FilePath -> IO () 
-renderjob cache h ofp = do 
-  let p = maybe (error "renderjob") id $ IM.lookup 0 (view gpages h)  
-  let Dim width height = view gdimension p  
-  let rf x = cairoRenderOption (RBkgDrawPDF,DrawFull) cache (x,Nothing :: Maybe Xform4Page) >> return () 
-  Cairo.withPDFSurface ofp width height $ \s -> Cairo.renderWith s $  
-    (sequence1_ Cairo.showPage . map rf . IM.elems . view gpages ) h 
-
--- | 
 fileExport :: MainCoroutine ()
 fileExport = fileChooser Gtk.FileChooserActionSave Nothing >>= maybe (return ()) action 
   where 
-    action filename = 
+    action filename = do
       -- this is rather temporary not to make mistake 
       if takeExtension filename /= ".pdf" 
-      then fileExtensionInvalid (".pdf","export") >> fileExport 
-      else do      
-        xstate <- get 
-        let hdl = getHoodle xstate 
-            cache = view renderCache xstate
-        liftIO (renderjob cache hdl filename) 
-
--- | 
-fileStartSync :: MainCoroutine ()
-fileStartSync = do 
-  xst <- get 
-  let mf = (,) <$> view (hoodleFileControl.hoodleFileName) xst <*> view (hoodleFileControl.lastSavedTime) xst 
-  maybe (return ()) (\(filename,lasttime) -> action filename lasttime) mf  
-  where  
-    action filename _lasttime  = do 
-      let ioact = mkIOaction $ \evhandler ->do 
-            forkIO $ do 
-              FS.withManager $ \wm -> do 
-                origfile <- canonicalizePath filename 
-                let (filedir,_) = splitFileName origfile
-                print filedir 
-                _ <- FS.watchDir wm (decodeString filedir) (const True) $ \ev -> do
-                  let mchangedfile = case ev of 
-                        FS.Added fp _ -> Just (encodeString fp)
-                        FS.Modified fp _ -> Just (encodeString fp)
-                        FS.Removed _fp _ -> Nothing 
-                  print mchangedfile 
-                  case mchangedfile of 
-                    Nothing -> return ()
-                    Just changedfile -> do                       
-                      let changedfilename = takeFileName changedfile 
-                          changedfile' = (filedir </> changedfilename)
-                      if changedfile' == origfile 
-                        then do 
-                          ctime <- getCurrentTime 
-                          evhandler (UsrEv (Sync ctime))
-                        else return () 
-
-                let sec = 1000000
-                forever (threadDelay (100 * sec))
-            return (UsrEv ActionOrdered)
-      modify (tempQueue %~ enqueue ioact) 
+        then fileExtensionInvalid (".pdf","export") >> fileExport 
+        else do      
+          hdl <- rHoodle2Hoodle . getHoodle . view (unitHoodles.currentUnit) <$> get
+          liftIO (renderHoodleToPDF hdl filename) 
 
 -- | need to be merged with ContextMenuEventSVG
 exportCurrentPageAsSVG :: MainCoroutine ()
@@ -266,25 +264,27 @@
       if takeExtension filename /= ".svg" 
       then fileExtensionInvalid (".svg","export") >> exportCurrentPageAsSVG 
       else do
-        cache <- view renderCache <$> get
+        cvsid <- getCurrentCanvasId . view (unitHoodles.currentUnit) <$> get
+        cache <- renderCache
         cpg <- getCurrentPageCurr
         let Dim w h = view gdimension cpg 
         liftIO $ Cairo.withSVGSurface filename w h $ \s -> Cairo.renderWith s $ 
-         cairoRenderOption (InBBoxOption Nothing) cache (InBBox cpg,Nothing :: Maybe Xform4Page) >> return ()
+         cairoRenderOption (InBBoxOption Nothing) cache cvsid (InBBox cpg,Nothing :: Maybe Xform4Page) >> return ()
 
 -- | 
-fileLoad :: FilePath -> MainCoroutine () 
-fileLoad filename = do
-    getFileContent (Just filename)
-    xstate <- get 
-    ncvsinfo <- liftIO $ setPage xstate 0 (getCurrentCanvasId xstate)
-    xstateNew <- return $ over currentCanvasInfo (const ncvsinfo) xstate
-    put . set isSaved True $ xstateNew 
-    let ui = view gtkUIManager xstateNew
-    liftIO $ toggleSave ui False
-    liftIO $ setTitleFromFileName xstateNew  
+fileLoad :: FileStore -> MainCoroutine () 
+fileLoad filestore = do
+    getFileContent filestore
+    updateUhdl $ \uhdl -> do 
+      ncvsinfo <- liftIO $ setPage uhdl 0 (getCurrentCanvasId uhdl)
+      return . (currentCanvasInfo .~ ncvsinfo) . (isSaved .~ True) $ uhdl
+    xst <- get 
+    let ui = view gtkUIManager xst
+    liftIO $ reflectUIToggle ui "SAVEA" False
+    liftIO $ setTitleFromFileName xst
     clearUndoHistory 
     modeChange ToViewAppendMode 
+    canvasZoomUpdateAll
     resetHoodleBuffers 
     invalidateAll 
     applyActionToAllCVS adjustScrollbarWithGeometryCvsId
@@ -292,78 +292,75 @@
 -- | 
 resetHoodleBuffers :: MainCoroutine () 
 resetHoodleBuffers = do 
-    liftIO $ putStrLn "resetHoodleBuffers called"
-    xst <- get 
-    nhdlst <- liftIO $ resetHoodleModeStateBuffers  
-                         (view renderCache xst)
-                         (view hoodleModeState xst)
-    let nxst = set hoodleModeState nhdlst xst
-    put nxst     
+    updateUhdl $ \uhdl -> do 
+      let hdlst = view hoodleModeState uhdl
+          cvsid = getCurrentCanvasId uhdl
+      callRenderer_ $ resetHoodleModeStateBuffers cvsid hdlst
+      return . (hoodleModeState .~ hdlst) $ uhdl
 
+
 -- | main coroutine for open a file 
 fileOpen :: MainCoroutine ()
 fileOpen = do 
     mfilename <- fileChooser Gtk.FileChooserActionOpen Nothing
-    forM_ mfilename fileLoad 
+    forM_ mfilename (fileLoad . LocalDir . Just)
 
 -- | main coroutine for save as 
 fileSaveAs :: MainCoroutine () 
 fileSaveAs = do 
-    xstate <- get 
-    let hdl = (rHoodle2Hoodle . getHoodle) xstate
-    maybe (defSaveAsAction xstate hdl) (\f -> liftIO (f hdl))
-          (hookSaveAsAction xstate) 
+    hdl <- (rHoodle2Hoodle . getHoodle . view (unitHoodles.currentUnit)) <$> get
+    maybe (defSaveAsAction hdl) (\f -> liftIO (f hdl)) =<< hookSaveAsAction
   where 
-    hookSaveAsAction xstate = do 
-      hset <- view hookSet xstate
-      saveAsHook hset
-    defSaveAsAction xstate hdl = do 
-        let msuggestedact = view hookSet xstate >>= fileNameSuggestionHook 
-        (msuggested :: Maybe String) <- maybe (return Nothing) (liftM Just . liftIO) msuggestedact 
+    hookSaveAsAction = (saveAsHook <=< view hookSet) <$> get
+    msuggestedact = (fileNameSuggestionHook <=< view hookSet) <$> get
+    defSaveAsAction hdl = do 
+        (msuggested :: Maybe String) <- maybe (return Nothing) (liftM Just . liftIO) =<< msuggestedact 
         mr <- fileChooser Gtk.FileChooserActionSave msuggested 
-        maybe (return ()) (action xstate hdl) mr 
-      where action xst' hd filename = 
+        maybe (return ()) (action hdl) mr 
+      where action hd filename = 
               if takeExtension filename /= ".hdl" 
               then fileExtensionInvalid (".hdl","save")
               else do 
-                askIfOverwrite filename $ do 
-                  let ntitle = B.pack . snd . splitFileName $ filename 
-                      (hdlmodst',hdl') = case view hoodleModeState xst' of
-                         ViewAppendState hdlmap -> 
-                           if view gtitle hdlmap == "untitled"
-                             then ( ViewAppendState . set gtitle ntitle
-                                    $ hdlmap
-                                  , (set title ntitle hd))
-                             else (ViewAppendState hdlmap,hd)
-                         SelectState thdl -> 
-                           if view gselTitle thdl == "untitled"
-                             then ( SelectState $ set gselTitle ntitle thdl 
-                                  , set title ntitle hd)  
-                             else (SelectState thdl,hd)
-                      xstateNew = set (hoodleFileControl.hoodleFileName) (Just filename) 
-                                . set hoodleModeState hdlmodst' $ xst'
-                  liftIO . L.writeFile filename . builder $ hdl'
-                  put . set isSaved True $ xstateNew    
-                  let ui = view gtkUIManager xstateNew
-                  liftIO $ toggleSave ui False
-                  liftIO $ setTitleFromFileName xstateNew 
-                  S.afterSaveHook filename hdl'
-          
+                askIfOverwrite filename $ do
+                  updateUhdl $ \uhdl -> do
+                    let ntitle = B.pack . snd . splitFileName $ filename 
+                        (hdlmodst',hdl') = case view hoodleModeState uhdl of
+                           ViewAppendState hdlmap -> 
+                             if view gtitle hdlmap == "untitled"
+                               then ( ViewAppendState . set gtitle ntitle
+                                      $ hdlmap
+                                    , (set title ntitle hd))
+                               else (ViewAppendState hdlmap,hd)
+                           SelectState thdl -> 
+                             if view gselTitle thdl == "untitled"
+                               then ( SelectState $ set gselTitle ntitle thdl 
+                                    , set title ntitle hd)  
+                               else (SelectState thdl,hd)
+                    liftIO . L.writeFile filename . builder $ hdl'
+                    return . (hoodleFileControl.hoodleFileName .~ LocalDir (Just filename))
+                           . (hoodleModeState .~ hdlmodst') 
+                           . (isSaved .~ True)
+                           $ uhdl
+                xst <- get
+                let ui = view gtkUIManager xst
+                    hdl'' = (rHoodle2Hoodle . getHoodle . view (unitHoodles.currentUnit)) xst
+                liftIO $ reflectUIToggle ui "SAVEA" False
+                liftIO $ setTitleFromFileName xst
+                S.afterSaveHook filename hdl''
+#ifdef HUB
+                hubUpload          
+#endif
 
 -- | main coroutine for open a file 
 fileReload :: MainCoroutine ()
-fileReload = do 
-    xstate <- get
-    case view (hoodleFileControl.hoodleFileName) xstate of 
-      Nothing -> return () 
-      Just filename -> do
-        if not (view isSaved xstate) 
-          then do
-            b <- okCancelMessageBox "Discard changes and reload the file?" 
-            case b of 
-              True -> fileLoad filename 
-              False -> return ()
-          else fileLoad filename
+fileReload = do
+    uhdl <- view (unitHoodles.currentUnit) <$> get
+    let filestore = view (hoodleFileControl.hoodleFileName) uhdl
+    if not (view isSaved uhdl) 
+      then do
+        b <- okCancelMessageBox "Discard changes and reload the file?" 
+        when b (fileLoad filestore)
+      else fileLoad filestore
 
 -- | 
 fileExtensionInvalid :: (String,String) -> MainCoroutine ()
@@ -387,11 +384,10 @@
       mhdl <- liftIO $ makeNewHoodleWithPDF doesembed filename 
       flip (maybe warning) mhdl $ \hdl -> do 
         constructNewHoodleStateFromHoodle hdl
-        modify ( hoodleFileControl.hoodleFileName .~ Nothing)
+        pureUpdateUhdl (hoodleFileControl.hoodleFileName .~ LocalDir Nothing)
         commit_        
         setTitleFromFileName_ 
         canvasZoomUpdateAll
-        -- invalidateAll  
       
 
 -- | set frame title according to file name
@@ -427,11 +423,45 @@
 fileLoadPNGorJPG = do 
     fileChooser Gtk.FileChooserActionOpen Nothing >>= maybe (return ()) embedImage
 
+
+-- | 
+fileLoadImageBackground :: MainCoroutine ()
+fileLoadImageBackground = do 
+    fileChooser Gtk.FileChooserActionOpen Nothing >>= maybe (return ()) action
+  where 
+    action filename = do 
+      xst <- get
+      let fDoesEmbedImg = view (settings.doesEmbedImage) xst
+          uhdl = view (unitHoodles.currentUnit) xst
+          hdl = getHoodle uhdl
+          Dim pw _ph = (view gdimension . fromJust . view (gpages.at 0)) hdl 
+
+      itm <- if fDoesEmbedImg 
+               then checkEmbedImageSize filename 
+                    >>= maybe (liftIO $ makeNewItemImage True filename) 
+                              (liftIO . makeNewItemImage True)
+               else liftIO (makeNewItemImage False filename)
+      let ItemImage img = itm
+          Dim w h = img_dim img
+          ratio = h/w 
+          ndim = Dim pw (pw*ratio)
+          img' = img { img_dim = ndim }
+      changePage (const 0)
+      newPage (Just ndim) PageBefore
+      callRenderer $ cnstrctRItem (ItemImage img') >>= return . GotRItem 
+      RenderEv (GotRItem nitm) <- waitSomeEvent (\case RenderEv (GotRItem _) -> True ; _ -> False)
+      insertItemAt (Just (PageNum 0, PageCoord (0,0))) nitm
+      modeChange ToViewAppendMode
+      makeNewLayer
+
+
 embedImage :: FilePath -> MainCoroutine ()
 embedImage filename = do  
-    xst <- get 
+    xst <- get
+    let fDoesEmbedImg = view (settings.doesEmbedImage) xst
+        uhdl = view (unitHoodles.currentUnit) xst
     nitm <- 
-      if view (settings.doesEmbedImage) xst
+      if fDoesEmbedImg 
         then do  
           mf <- checkEmbedImageSize filename 
           --
@@ -445,7 +475,7 @@
           RenderEv (GotRItem r) <- waitSomeEvent (\case RenderEv (GotRItem _) -> True ; _ -> False )
           return r
 
-    let cpn = view (currentCanvasInfo . unboxLens currentPageNum) xst
+    let cpn = view (currentCanvasInfo . unboxLens currentPageNum) uhdl
     my <- autoPosText 
     let mpos = (\y->(PageNum cpn,PageCoord (50,y)))<$>my  
     insertItemAt mpos nitm 
@@ -457,11 +487,12 @@
     fileChooser Gtk.FileChooserActionOpen Nothing >>= maybe (return ()) action 
   where 
     action filename = do 
-      xstate <- get 
-      liftIO $ putStrLn filename 
+      xst <- get 
       bstr <- liftIO $ B.readFile filename 
-      let pgnum = view (currentCanvasInfo . unboxLens currentPageNum) xstate
-          hdl = getHoodle xstate 
+      let uhdl = view (unitHoodles.currentUnit) xst
+          cvsid = getCurrentCanvasId uhdl
+          pgnum = view (currentCanvasInfo . unboxLens currentPageNum) uhdl
+          hdl = getHoodle uhdl
           currpage = getPageFromGHoodleMap pgnum hdl
           currlayer = getCurrentLayer currpage
       --
@@ -472,14 +503,14 @@
       let otheritems = view gitems currlayer  
       let ntpg = makePageSelectMode currpage (otheritems :- (Hitted [newitem]) :- Empty)  
       modeChange ToSelectMode 
-      nxstate <- get 
-      let cache = view renderCache nxstate
-      thdl <- case view hoodleModeState nxstate of
-                SelectState thdl' -> return thdl'
-                _ -> (lift . EitherT . return . Left . Other) "fileLoadSVG"
-      nthdl <- liftIO $ updateTempHoodleSelectIO cache thdl ntpg pgnum 
-      put ( ( set hoodleModeState (SelectState nthdl) 
-            . set isOneTimeSelectMode YesAfterSelect) nxstate)
+      updateUhdl $ \uhdl' -> do
+        thdl <- case view hoodleModeState uhdl' of
+                  SelectState thdl' -> return thdl'
+                  _ -> (lift . EitherT . return . Left . Other) "fileLoadSVG"
+        nthdl <- updateTempHoodleSelectM cvsid thdl ntpg pgnum 
+        return . (hoodleModeState .~ SelectState nthdl)
+               . (isOneTimeSelectMode .~ YesAfterSelect) $ uhdl'
+      commit_
       invalidateAll 
 
 -- |
@@ -487,7 +518,7 @@
 askQuitProgram = do 
     b <- okCancelMessageBox "Current canvas is not saved yet. Will you close hoodle?" 
     case b of 
-      True -> liftIO Gtk.mainQuit
+      True -> doIOaction_ $ Gtk.postGUIAsync Gtk.mainQuit >> return (UsrEv ActionOrdered)
       False -> return ()
   
 -- | 
@@ -517,11 +548,10 @@
 -- | 
 embedAllPDFBackground :: MainCoroutine () 
 embedAllPDFBackground = do 
-  xst <- get 
-  let hdl = getHoodle xst
+  hdl <- (rHoodle2Hoodle  . getHoodle . view (unitHoodles.currentUnit)) <$> get
   nhdl <- liftIO . embedPDFInHoodle $ hdl
-  modeChange ToViewAppendMode
-  commit (set hoodleModeState (ViewAppendState nhdl) xst)
+  constructNewHoodleStateFromHoodle nhdl
+  commit_
   invalidateAll   
   
 -- | embed an item from hoodlet using hoodlet identifier
@@ -547,11 +577,11 @@
     return (md5str,name) 
 
 
-mkRevisionPdfFile :: RenderCache -> RHoodle -> String -> IO ()
-mkRevisionPdfFile cache hdl fname = do 
+mkRevisionPdfFile :: Hoodle -> String -> IO ()
+mkRevisionPdfFile hdl fname = do 
     hdir <- getHomeDirectory
     tempfile <- mkTmpFile "pdf"
-    renderjob cache hdl tempfile 
+    renderHoodleToPDF hdl tempfile 
     let nfilename = fname <.> "pdf"
         vcsdir = hdir </> ".hoodle.d" </> "vcs"
     b <- doesDirectoryExist vcsdir 
@@ -561,67 +591,73 @@
 -- | 
 fileVersionSave :: MainCoroutine () 
 fileVersionSave = do 
-    rhdl <- getHoodle <$> get 
-    cache <- view renderCache <$> get
-    let hdl = rHoodle2Hoodle rhdl
+    hdl <- rHoodle2Hoodle . getHoodle . view (unitHoodles.currentUnit) <$> get
     rmini <- minibufDialog "Commit Message:"
     case rmini of 
       Right [] -> return ()
       Right strks' -> do
         doIOaction $ \_evhandler -> do 
           (md5str,fname) <- mkRevisionHdlFile hdl
-          mkRevisionPdfFile cache rhdl fname
+          mkRevisionPdfFile hdl fname
           return (UsrEv (GotRevisionInk md5str strks'))
         r <- waitSomeEvent (\case GotRevisionInk _ _ -> True ; _ -> False )
         let GotRevisionInk md5str strks = r          
             nrev = RevisionInk (B.pack md5str) strks
-        modify (\xst -> let hdlmodst = view hoodleModeState xst 
-                        in case hdlmodst of 
-                             ViewAppendState rhdl' -> 
-                               let nrhdl = over grevisions (<> [nrev]) rhdl' 
-                               in set hoodleModeState (ViewAppendState nrhdl) xst 
-                             SelectState thdl -> 
-                               let nthdl = over gselRevisions (<> [nrev]) thdl
-                               in set hoodleModeState (SelectState nthdl) xst)
+        pureUpdateUhdl $ \uhdl -> 
+          let hdlmodst = view hoodleModeState uhdl
+          in case hdlmodst of 
+               ViewAppendState rhdl' -> 
+                 let nrhdl = over grevisions (<> [nrev]) rhdl' 
+                 in (hoodleModeState .~ ViewAppendState nrhdl) uhdl
+               SelectState thdl -> 
+                 let nthdl = over gselRevisions (<> [nrev]) thdl
+                 in (hoodleModeState .~ SelectState nthdl) uhdl
         commit_ 
       Left () -> do 
-        txtstr <- maybe "" id <$> textInputDialog
+        txtstr <- maybe "" id <$> textInputDialog "revision description"
         doIOaction $ \_evhandler -> do 
           (md5str,fname) <- mkRevisionHdlFile hdl
-          mkRevisionPdfFile cache rhdl fname
+          mkRevisionPdfFile hdl fname
           return (UsrEv (GotRevision md5str txtstr))
         r <- waitSomeEvent (\case GotRevision _ _ -> True ; _ -> False )
         let GotRevision md5str txtstr' = r          
             nrev = Revision (B.pack md5str) (B.pack txtstr')
-        modify (\xst -> let hdlmodst = view hoodleModeState xst 
-                        in case hdlmodst of 
-                             ViewAppendState rhdl' -> 
-                               let nrhdl = over grevisions (<> [nrev]) rhdl' 
-                               in set hoodleModeState (ViewAppendState nrhdl) xst 
-                             SelectState thdl -> 
-                               let nthdl = over gselRevisions (<> [nrev]) thdl
-                               in set hoodleModeState (SelectState nthdl) xst)
+        pureUpdateUhdl $ \uhdl -> 
+          let hdlmodst = view hoodleModeState uhdl
+          in case hdlmodst of 
+               ViewAppendState rhdl' -> 
+                 let nrhdl = over grevisions (<> [nrev]) rhdl' 
+                 in (hoodleModeState .~ ViewAppendState nrhdl) uhdl
+               SelectState thdl -> 
+                 let nthdl = over gselRevisions (<> [nrev]) thdl
+                 in (hoodleModeState .~ SelectState nthdl) uhdl
         commit_ 
 
 
 
 showRevisionDialog :: Hoodle -> [Revision] -> MainCoroutine ()
-showRevisionDialog hdl revs = 
-    liftM (view renderCache) get >>= \cache -> 
-    modify (tempQueue %~ enqueue (action cache)) 
-    >> waitSomeEvent (\case GotOk -> True ; _ -> False)
-    >> return ()
+showRevisionDialog hdl revs = do
+    cvsid <- getCurrentCanvasId . view (unitHoodles.currentUnit) <$> get
+    cache <- renderCache
+    doIOaction (action (cache,cvsid))
+    waitSomeEvent (\case GotOk -> True ; _ -> False)
+    return ()
   where 
-    action cache 
-       = mkIOaction $ \_evhandler -> do 
-               dialog <- Gtk.dialogNew
-               vbox <- Gtk.dialogGetUpper dialog
-               mapM_ (addOneRevisionBox cache vbox hdl) revs 
-               _btnOk <- Gtk.dialogAddButton dialog "Ok" Gtk.ResponseOk
-               Gtk.widgetShowAll dialog
-               _res <- Gtk.dialogRun dialog
-               Gtk.widgetDestroy dialog
-               return (UsrEv GotOk)
+    action (cache,cvsid) _evhandler = do 
+      dialog <- Gtk.dialogNew
+#ifdef GTK3
+      upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)
+      vbox <- Gtk.vBoxNew False 0
+      Gtk.containerAdd upper vbox 
+#else 
+      vbox <- Gtk.dialogGetUpper dialog
+#endif
+      mapM_ (addOneRevisionBox cache cvsid vbox hdl) revs 
+      _btnOk <- Gtk.dialogAddButton dialog ("Ok" :: String) Gtk.ResponseOk
+      Gtk.widgetShowAll dialog
+      _res <- Gtk.dialogRun dialog
+      Gtk.widgetDestroy dialog
+      return (UsrEv GotOk)
 
 
 mkPangoText :: String -> Cairo.Render ()
@@ -630,7 +666,7 @@
           ctxt <- Gtk.cairoCreateContext Nothing 
           layout <- Gtk.layoutEmpty ctxt   
           fdesc <- Gtk.fontDescriptionNew 
-          Gtk.fontDescriptionSetFamily fdesc "Sans Mono"
+          Gtk.fontDescriptionSetFamily fdesc ("Sans Mono" :: String)
           Gtk.fontDescriptionSetSize fdesc 8.0 
           Gtk.layoutSetFontDescription layout (Just fdesc)
           Gtk.layoutSetWidth layout (Just 250)
@@ -643,19 +679,27 @@
     layout <- liftIO $ pangordr 
     rdr layout
 
-addOneRevisionBox :: RenderCache -> Gtk.VBox -> Hoodle -> Revision -> IO ()
-addOneRevisionBox cache vbox hdl rev = do 
+addOneRevisionBox :: RenderCache -> CanvasId -> Gtk.VBox -> Hoodle -> Revision -> IO ()
+addOneRevisionBox cache cvsid vbox hdl rev = do 
     cvs <- Gtk.drawingAreaNew 
     cvs `Gtk.on` Gtk.sizeRequest $ return (Gtk.Requisition 250 25)
     cvs `Gtk.on` Gtk.exposeEvent $ Gtk.tryEvent $ do 
+#ifdef GTK3      
+      Just drawwdw <- liftIO $ Gtk.widgetGetWindow cvs 
+#else
       drawwdw <- liftIO $ Gtk.widgetGetDrawWindow cvs 
+#endif
+#ifdef GTK3
+      liftIO . Gtk.renderWithDrawWindow drawwdw $ do
+#else 
       liftIO . Gtk.renderWithDrawable drawwdw $ do 
+#endif
         case rev of 
-          RevisionInk _ strks -> Cairo.scale 0.5 0.5 >> mapM_ (cairoRender cache) strks
+          RevisionInk _ strks -> Cairo.scale 0.5 0.5 >> mapM_ (cairoRender cache cvsid) strks
           Revision _ txt -> mkPangoText (B.unpack txt)            
     hdir <- getHomeDirectory
     let vcsdir = hdir </> ".hoodle.d" </> "vcs"
-    btn <- Gtk.buttonNewWithLabel "view"
+    btn <- Gtk.buttonNewWithLabel ("view" :: String)
     btn `Gtk.on` Gtk.buttonPressEvent $ Gtk.tryEvent $ do 
       files <- liftIO $ getDirectoryContents vcsdir 
       let fstrinit = "UUID_" ++ B.unpack (view hoodleID hdl)  
@@ -675,14 +719,14 @@
 
 fileShowRevisions :: MainCoroutine ()
 fileShowRevisions = do 
-    rhdl <- liftM getHoodle get  
+    rhdl <- getHoodle . view (unitHoodles.currentUnit) <$> get  
     let hdl = rHoodle2Hoodle rhdl
     let revs = view grevisions rhdl
     showRevisionDialog hdl revs 
   
 fileShowUUID :: MainCoroutine ()
 fileShowUUID = do 
-    hdl <- liftM getHoodle get  
+    hdl <- getHoodle . view (unitHoodles.currentUnit) <$> get  
     let uuidstr = view ghoodleID hdl
     okMessageBox (B.unpack uuidstr)
   
@@ -698,7 +742,7 @@
          let fp = hoodletdir </> str <.> "hdlt"
          bstr <- liftIO $ B.readFile fp 
          case parseOnly Hoodlet.hoodlet bstr of 
-           Left err -> liftIO $ putStrLn err >> return Nothing
+           Left err -> msgShout err >> return Nothing
            Right itm -> do
              --
              callRenderer $ cnstrctRItem itm >>= return . GotRItem 
@@ -709,5 +753,45 @@
        else return Nothing
 
   
-  
+#ifdef HUB
+-- |
+syncFile :: MainCoroutine ()
+syncFile = do 
+    liftIO (putStrLn "syncFile called")
+    xst <- get
+    let uhdl = view (unitHoodles.currentUnit) xst
+    hdir <- liftIO $ getHomeDirectory
+    let tokfile = hdir </> ".hoodle.d" </> "token.txt"
+    runMaybeT $ do
+      let hdlidtxt = getHoodleID uhdl 
+      hset <- (MaybeT . return . view hookSet) xst
+      hinfo <- (MaybeT . return) (hubInfo hset)
+      sqlfile <- (MaybeT . return . view (settings.sqliteFileName)) xst
+      hdlfp <- MaybeT . return $ getHoodleFilePath uhdl
+      mfstat <- liftIO $ getLastSyncStatus sqlfile hdlidtxt 
+      lift $ prepareToken hinfo tokfile 
+      lift $ doIOaction $ \evhandler -> do 
+        forkIO $ (`E.catch` (\(e :: E.SomeException)-> print e >> return ())) $ 
+          withHub hinfo tokfile $ \manager coojar -> do
+            flip runReaderT (manager,coojar) $ do
+              Just fstatServer <- sessionGetJSON (hubURL hinfo </> "sync" </> T.unpack hdlidtxt)
+              let patchwork = 
+                    rsyncPatchWork hinfo hdlfp fstatServer $ do
+                      putStrLn "Am I called?"
+                      (evhandler . UsrEv . SyncFileFinished) fstatServer
+
+              case mfstat of 
+                Nothing -> patchwork
+                Just fstat ->  
+                  if fileSyncStatusTime fstat < fileSyncStatusTime fstatServer
+                  then patchwork 
+                  else (liftIO . Gtk.postGUIAsync . evhandler . UsrEv . SyncFileFinished) fstat
+        return (UsrEv ActionOrdered)
+      SyncFileFinished nfstat <- 
+        lift (waitSomeEvent (\case SyncFileFinished _-> True ; _ -> False ))
+      liftIO $ print nfstat
+      lift (updateSyncInfoAll nfstat)
+      when (Just nfstat /= mfstat) (lift fileReload)
+    return ()
+#endif
   
diff --git a/src/Hoodle/Coroutine/HandwritingRecognition.hs b/src/Hoodle/Coroutine/HandwritingRecognition.hs
--- a/src/Hoodle/Coroutine/HandwritingRecognition.hs
+++ b/src/Hoodle/Coroutine/HandwritingRecognition.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
@@ -16,43 +17,36 @@
 
 module Hoodle.Coroutine.HandwritingRecognition where
 
-import           Control.Lens (view,_1,_2,(%~))
+import           Control.Lens (view,_1,_2)
 import           Control.Monad ((<=<),guard,when)
-import           Control.Monad.State (modify)
 import           Control.Monad.Trans (liftIO)
 import           Control.Monad.Trans.Either
 import           Data.Aeson as A
--- import           Data.Aeson.Encode
--- import           Data.Aeson.Encode.Pretty
-import qualified Data.Attoparsec as AP
--- import           Data.Attoparsec.Number
+import qualified Data.Attoparsec.ByteString.Char8 as AP
 import qualified Data.ByteString.Char8 as B
 import qualified Data.ByteString.Lazy.Char8 as LB
 import           Data.Foldable (mapM_)
 import qualified Data.HashMap.Strict as HM
 import qualified Data.List as L (lookup)
 import           Data.Maybe
--- import           Data.Scientific
 import           Data.Strict.Tuple
 import qualified Data.Text as T
 import           Data.Traversable (forM)
 import           Data.UUID.V4
 import           Data.Vector hiding (map,head,null,(++),take,modify,mapM_,zip,forM)
-import           Graphics.UI.Gtk 
+import qualified Graphics.UI.Gtk as Gtk
 import           System.Directory
 import           System.Exit
 import           System.FilePath
 import           System.Process
 -- 
-import           Control.Monad.Trans.Crtn.Queue
 import           Data.Hoodle.Simple
 -- from this package
--- import           Hoodle.Coroutine.Dialog
 import           Hoodle.Coroutine.Draw (waitSomeEvent)
 import           Hoodle.Coroutine.Minibuffer
 import           Hoodle.Type.Coroutine
 import           Hoodle.Type.Event
-import           Hoodle.Type.HoodleState
+import           Hoodle.Util
 -- 
 import           Prelude hiding (fst,snd,mapM_)
 
@@ -66,7 +60,6 @@
 
 handwritingRecognitionDialog :: MainCoroutine (Maybe (Bool,T.Text))
 handwritingRecognitionDialog = do
-  liftIO $ putStrLn "handwriting recognition test here"
   r <- minibufDialog "test handwriting recognition"
   case r of 
     Left err -> liftIO $ putStrLn (show err) >> return Nothing 
@@ -76,8 +69,7 @@
       let bstr = (encode . mkAesonInk) strks
       let fp = tdir </> show uuid <.> "json"
       liftIO $ LB.writeFile fp bstr
-      (excode,gresult,gerror) <- liftIO $ readProcessWithExitCode "curl" ["-X", "POST", "-H", "Content-Type: application/json ", "--data-ascii", "@"++fp, "http://inputtools.google.com/request?itc=en-t-i0-handwrit&app=chext" ] ""
-      -- let ev0 = AP.parseOnly json (B.pack gresult)  
+      (excode,gresult,gerror) <- liftIO $ readProcessWithExitCode "curl" ["-X", "POST", "-H", "Content-Type: application/json ", "--data-ascii", "@"++fp, "http://inputtools.google.com/request?itc=en-t-i0-handwrit" ] ""
       case excode of 
         ExitSuccess -> do 
           r_parse <- runEitherT $ do  
@@ -91,15 +83,15 @@
             (return . mapMaybe f . toList) v4
       
           case r_parse of 
-            Left err -> liftIO $ putStrLn err >> return Nothing 
+            Left err -> msgShout ("handwritingRecognitionDialog: " ++ err) >> return Nothing 
             Right lst -> showRecogTextDialog lst 
-        _ -> liftIO $ print gerror >> return Nothing 
+        _ -> msgShout ("handwritingRecognitionDialog: " ++ gerror) >> return Nothing 
 
 
 
 showRecogTextDialog :: [T.Text] -> MainCoroutine (Maybe (Bool,T.Text))
 showRecogTextDialog txts = do 
-    modify (tempQueue %~ enqueue action) 
+    doIOaction action
     >> waitSomeEvent (\case OkCancel _ -> True 
                             GotRecogResult _ _ -> True
                             _ -> False)
@@ -107,9 +99,15 @@
               GotRecogResult b txt -> return (Just (b,txt))
               _ -> return Nothing
   where 
-    action = mkIOaction $ \evhandler -> do 
-               dialog <- dialogNew
-               vbox <- dialogGetUpper dialog
+    action = \evhandler -> do 
+               dialog <- Gtk.dialogNew
+#ifdef GTK3
+               upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)
+               vbox <- Gtk.vBoxNew False 0        
+               Gtk.containerAdd upper vbox
+#else
+               vbox <- Gtk.dialogGetUpper dialog
+#endif
                let txtlst' = zip [1..] txts
                txtlst <- forM txtlst' $ \(n,txt) -> do
                  let str = T.unpack txt 
@@ -122,26 +120,27 @@
                          else doesFileExist (hoodletdir </> str <.> "hdlt")      
                  return (n,(b2,txt))
                mapM_ (addOneTextBox evhandler dialog vbox) txtlst  
-               _btnCancel <- dialogAddButton dialog "Cancel" ResponseCancel
-               widgetShowAll dialog
-               res <- dialogRun dialog
-               widgetDestroy dialog
+               _btnCancel <- Gtk.dialogAddButton dialog ("Cancel" :: String) Gtk.ResponseCancel
+               Gtk.widgetShowAll dialog
+               res <- Gtk.dialogRun dialog
+               Gtk.widgetDestroy dialog
                case res of 
-                 ResponseUser n -> case L.lookup n txtlst of
+                 Gtk.ResponseUser n -> case L.lookup n txtlst of
                                      Nothing -> return (UsrEv (OkCancel False))
                                      Just (b,txt) -> return (UsrEv (GotRecogResult b txt)) 
                  _ -> return (UsrEv (OkCancel False))
                  
-addOneTextBox :: (AllEvent -> IO ()) -> Dialog -> VBox -> (Int,(Bool,T.Text)) -> IO ()
+addOneTextBox :: (AllEvent -> IO ()) -> Gtk.Dialog -> Gtk.VBox 
+              -> (Int,(Bool,T.Text)) -> IO ()
 addOneTextBox _evhandler dialog vbox (n,(b,txt)) = do
-  btn <- buttonNewWithLabel (T.unpack txt)
+  btn <- Gtk.buttonNewWithLabel (T.unpack txt)
   when b $ do 
-    widgetModifyBg btn StateNormal (Color 60000 60000 30000)
-    widgetModifyBg btn StatePrelight (Color 63000 63000 40000)
-    widgetModifyBg btn StateActive (Color 45000 45000 18000)
-  btn `on` buttonPressEvent $ tryEvent $ do
-    liftIO $ dialogResponse dialog (ResponseUser n)
-  boxPackStart vbox btn PackNatural 0 
+    Gtk.widgetModifyBg btn Gtk.StateNormal (Gtk.Color 60000 60000 30000)
+    Gtk.widgetModifyBg btn Gtk.StatePrelight (Gtk.Color 63000 63000 40000)
+    Gtk.widgetModifyBg btn Gtk.StateActive (Gtk.Color 45000 45000 18000)
+  btn `Gtk.on` Gtk.buttonPressEvent $ Gtk.tryEvent $ do
+    liftIO $ Gtk.dialogResponse dialog (Gtk.ResponseUser n)
+  Gtk.boxPackStart vbox btn Gtk.PackNatural 0 
 
 mkAesonInk :: [Stroke] -> Value
 mkAesonInk strks = 
diff --git a/src/Hoodle/Coroutine/Highlighter.hs b/src/Hoodle/Coroutine/Highlighter.hs
--- a/src/Hoodle/Coroutine/Highlighter.hs
+++ b/src/Hoodle/Coroutine/Highlighter.hs
@@ -17,11 +17,8 @@
 import Hoodle.Type.Canvas
 import Hoodle.Coroutine.Pen 
 
-import Control.Monad.Trans
-
 -- | 
 
-highlighterStart :: CanvasId -> PointerCoord -> MainCoroutine () 
-highlighterStart cid pcoord = do 
-  liftIO $ putStrLn "highlighter started"
-  penStart cid pcoord
+highlighterStart :: CanvasId -> PointerCoord 
+                 -> MainCoroutine (Maybe (Maybe (Maybe ())))
+highlighterStart cid pcoord = penStart cid pcoord
diff --git a/src/Hoodle/Coroutine/Hub.hs b/src/Hoodle/Coroutine/Hub.hs
new file mode 100644
--- /dev/null
+++ b/src/Hoodle/Coroutine/Hub.hs
@@ -0,0 +1,61 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Hoodle.Coroutine.Hub
+-- Copyright   : (c) 2014,2015 Ian-Woo Kim
+--
+-- License     : BSD3
+-- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
+-- Stability   : experimental
+-- Portability : GHC
+--
+-----------------------------------------------------------------------------
+
+module Hoodle.Coroutine.Hub where
+
+import           Control.Applicative
+import           Control.Lens (view)
+import           Control.Monad.IO.Class
+import           Control.Monad.State
+import           Control.Monad.Trans.Maybe
+import System.Directory
+import System.FilePath (makeRelative)
+--
+import Hoodle.Coroutine.HubInternal
+import Hoodle.Coroutine.Dialog
+import Hoodle.Script.Hook
+import Hoodle.Type.Coroutine
+import Hoodle.Type.Hub
+import Hoodle.Type.HoodleState
+--
+
+-- |
+hubUpload :: MainCoroutine ()
+hubUpload = do
+    xst <- get
+    uhdl <- view (unitHoodles.currentUnit) <$> get
+    if not (view isSaved uhdl) 
+      then 
+        okMessageBox "hub action can be done only after saved" >> return ()
+      else do r <- runMaybeT $ do 
+                     hset <- (MaybeT . return) $ view hookSet xst
+                     hinfo <- (MaybeT . return) (hubInfo hset)
+                     let hdir = hubFileRoot hinfo
+                     (canfp,mhdlfp) <- 
+                          case view (hoodleFileControl.hoodleFileName) uhdl of
+                             LocalDir Nothing -> MaybeT (return Nothing)
+                             LocalDir (Just fp) -> do 
+                               canfp <- liftIO $ canonicalizePath fp
+                               let relfp = makeRelative hdir canfp
+                               MaybeT . return . Just $ (canfp,Just relfp)
+                             TempDir fp -> do 
+                               canfp <- liftIO $ canonicalizePath fp
+                               MaybeT . return . Just $ (canfp,Nothing)
+                     lift (uploadWork (canfp,mhdlfp) hinfo)
+              case r of 
+                Nothing -> okMessageBox "upload not successful" >> return ()
+                Just _ -> return ()  
+
diff --git a/src/Hoodle/Coroutine/Hub/Common.hs b/src/Hoodle/Coroutine/Hub/Common.hs
new file mode 100644
--- /dev/null
+++ b/src/Hoodle/Coroutine/Hub/Common.hs
@@ -0,0 +1,123 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Hoodle.Coroutine.Hub.Common
+-- Copyright   : (c) 2015 Ian-Woo Kim
+--
+-- License     : BSD3
+-- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
+-- Stability   : experimental
+-- Portability : GHC
+--
+-----------------------------------------------------------------------------
+
+module Hoodle.Coroutine.Hub.Common where
+
+import           Control.Applicative
+import           Control.Monad.IO.Class
+import           Control.Monad.State
+import           Control.Monad.Trans.Reader
+import           Control.Monad.Trans.Resource
+import           Data.Aeson as AE
+import qualified Data.ByteString.Lazy.Char8 as BL
+import qualified Data.Foldable as F
+import           Data.IORef
+import           Data.Monoid ((<>))
+import qualified Data.Text as T (Text,pack,unpack)
+import           Data.Text.Encoding (encodeUtf8)
+import           Database.Persist (getBy,entityVal)
+import           Database.Persist.Sqlite (runSqlite)
+import           Network
+import           Network.Google.OAuth2 ( formUrl, exchangeCode, refreshTokens
+                                       , OAuth2Client(..), OAuth2Tokens(..))
+import           Network.HTTP.Client (GivesPopper)
+import           Network.HTTP.Conduit ( CookieJar, Manager
+                                      , cookieJar, createCookieJar
+                                      , httpLbs, parseUrl
+                                      , requestHeaders
+                                      , responseBody, responseCookieJar, withManager)
+import           System.Directory
+import           System.Exit    (ExitCode(..))
+import           System.Info (os)
+import           System.Process (rawSystem)
+--
+--
+import           Hoodle.Coroutine.Dialog
+import           Hoodle.Type.Coroutine
+import           Hoodle.Type.Hub
+import           Hoodle.Type.Synchronization
+--
+
+-- |
+streamContent :: BL.ByteString -> GivesPopper ()
+streamContent lb np = do
+    lbref <- newIORef lb 
+    np (popper lbref)
+  where popper lbref = do
+          lbstr <- readIORef lbref
+          if (not .BL.null) lbstr
+            then do 
+              let (lbstr1,lbstr2) = BL.splitAt 10240 lbstr
+              writeIORef lbref lbstr2
+              return (BL.toStrict lbstr1)
+            else do
+              return ""
+
+-- |
+prepareToken :: HubInfo -> FilePath -> MainCoroutine ()
+prepareToken HubInfo {..} tokfile = do
+    let client = OAuth2Client { clientId = T.unpack googleClientId, clientSecret = T.unpack googleClientSecret }
+        permissionUrl = formUrl client ["email"]
+    liftIO $ putStrLn "prepareToken"
+    liftIO (doesFileExist tokfile) >>= \b -> unless b $ do       
+      case os of
+        "linux"  -> liftIO $ rawSystem "chromium" [permissionUrl]
+        "darwin" -> liftIO $ rawSystem "open"       [permissionUrl]
+        _        -> return ExitSuccess
+      mauthcode <- textInputDialog "Please paste the verification code: "
+      F.forM_ mauthcode $ \authcode -> do
+        tokens  <- liftIO $ exchangeCode client authcode
+        liftIO $ writeFile tokfile (show tokens)
+
+-- |
+withHub :: HubInfo -> FilePath 
+           -> (Manager -> CookieJar -> ResourceT IO a) -> IO a 
+withHub HubInfo {..} tokfile action = 
+    withSocketsDo $ withManager $ \manager -> do
+      let client = OAuth2Client { clientId = T.unpack googleClientId
+                                , clientSecret = T.unpack googleClientSecret }
+      -- refresh token
+      oldtok <- liftIO $ read <$> (readFile tokfile)
+      newtok  <- liftIO $ refreshTokens client oldtok
+      liftIO $ writeFile tokfile (show newtok)
+      --
+      accessTok <- fmap (accessToken . read) (liftIO (readFile tokfile))
+      request' <- parseUrl googleAuthURL
+      let request = request' 
+            { requestHeaders =  [ ("Authorization", encodeUtf8 $ "Bearer " <> T.pack accessTok) ]
+            , cookieJar = Just (createCookieJar  [])
+            }
+      response <- httpLbs request manager
+      let coojar = responseCookieJar response
+      action manager coojar
+
+
+sessionGetJSON :: (FromJSON a) => 
+                  String -> ReaderT (Manager,CookieJar) (ResourceT IO) (Maybe a)
+sessionGetJSON url = do
+    (manager,coojar) <- ask 
+    req' <- lift $ parseUrl url
+    let req = req' 
+          { requestHeaders = [ ("Accept", "application/json; charset=utf-8") ] 
+          , cookieJar = Just coojar }
+    res <- lift $ httpLbs req manager
+    return (AE.decode (responseBody res))
+
+-- |
+getLastSyncStatus :: FilePath -> T.Text -> IO (Maybe FileSyncStatus)
+getLastSyncStatus fp uuidtxt = 
+    fmap entityVal <$> runSqlite (T.pack fp) (getBy (UniqueFileSyncStatusUUID uuidtxt))
+
+ 
diff --git a/src/Hoodle/Coroutine/HubInternal.hs b/src/Hoodle/Coroutine/HubInternal.hs
new file mode 100644
--- /dev/null
+++ b/src/Hoodle/Coroutine/HubInternal.hs
@@ -0,0 +1,315 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Hoodle.Coroutine.HubInternal
+-- Copyright   : (c) 2014, 2015 Ian-Woo Kim
+--
+-- License     : BSD3
+-- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
+-- Stability   : experimental
+-- Portability : GHC
+--
+-----------------------------------------------------------------------------
+
+module Hoodle.Coroutine.HubInternal where
+
+import           Control.Applicative
+import           Control.Concurrent
+import qualified Control.Exception as E
+import           Control.Lens (over,view,set,_2)
+import           Control.Monad.IO.Class
+import           Control.Monad.State
+import           Control.Monad.Trans.Maybe
+import           Control.Monad.Trans.Reader
+import           Control.Monad.Trans.Resource
+import           Data.Aeson as AE
+import qualified Data.ByteString.Base64 as B64
+import qualified Data.ByteString.Char8 as B
+import qualified Data.ByteString.Lazy.Char8 as BL
+import           Data.Digest.Pure.MD5 (md5)
+import qualified Data.Foldable as F
+import qualified Data.IntMap as IM
+import           Data.List (find)
+import qualified Data.Text as T (Text,pack,unpack)
+import qualified Data.Text.Encoding as TE (encodeUtf8,decodeUtf8)
+import           Data.UUID
+import           Data.UUID.V4
+import           Database.Persist (upsert, getBy)
+import           Database.Persist.Sql (runMigration)
+import           Database.Persist.Sqlite (runSqlite)
+import qualified Graphics.UI.Gtk as Gtk
+import           Network.HTTP.Conduit ( RequestBody(..), CookieJar, Manager
+                                      , cookieJar, httpLbs, method, parseUrl
+                                      , requestBody, responseBody)
+import           Network.HTTP.Types (methodPut)
+import           System.Directory
+import           System.FilePath ((</>),(<.>),makeRelative)
+import           System.Process (readProcessWithExitCode)
+--
+import           Data.Hoodle.Generic
+import           Data.Hoodle.Simple
+import           Graphics.Hoodle.Render.Type.Hoodle
+import           Text.Hoodle.Builder (builder)
+--
+import           Hoodle.Accessor
+import           Hoodle.Coroutine.Hub.Common
+import           Hoodle.Script.Hook
+import           Hoodle.Type.Coroutine
+import           Hoodle.Type.Event
+import           Hoodle.Type.Hub
+import           Hoodle.Type.HoodleState
+import           Hoodle.Type.Synchronization
+--
+
+         
+uploadWork :: (FilePath,Maybe FilePath) -> HubInfo -> MainCoroutine ()
+uploadWork (canfp,mhdlfp) hinfo@(HubInfo {..}) = do
+    uhdl0 <- view (unitHoodles.currentUnit) <$> get
+    let hdl = (rHoodle2Hoodle . getHoodle) uhdl0
+        hdllbstr = builder hdl
+        hdlbstr = BL.toStrict hdllbstr
+        hdlmd5txt = T.pack (show (md5 hdllbstr))
+    pureUpdateUhdl $ over (hoodleFileControl.syncMD5History) (hdlmd5txt:)
+    uhdl <- view (unitHoodles.currentUnit) <$> get
+    let synchist = view (hoodleFileControl.syncMD5History) uhdl
+        uhdluuid = view unitUUID uhdl
+
+    hdir <- liftIO $ getHomeDirectory
+    msqlfile <- view (settings.sqliteFileName) <$> get
+    let tokfile = hdir </> ".hoodle.d" </> "token.txt"
+    prepareToken hinfo tokfile
+    doIOaction $ \evhandler -> do 
+      forkIO $ (`E.catch` (\(e :: E.SomeException)-> print e >> (Gtk.postGUIAsync . evhandler . UsrEv) (DisconnectedHub tokfile (canfp,mhdlfp) hinfo) >> return ())) $ 
+        withHub hinfo tokfile $ \manager coojar -> do
+          let uuidtxt = TE.decodeUtf8 (view hoodleID hdl)
+          flip runReaderT (manager,coojar) $ do
+            mfstat <- sessionGetJSON (hubURL </> "sync" </> T.unpack uuidtxt)
+            liftIO $ print (mfstat :: Maybe FileSyncStatus)
+            liftIO $ print synchist
+            let uploading = uploadAndUpdateSync evhandler uhdluuid hinfo uuidtxt hdlbstr (canfp,mhdlfp) msqlfile
+            flip (maybe uploading) ((,) <$> msqlfile <*> mfstat) $ 
+              \(sqlfile,fstat) -> do
+                me <- runSqlite (T.pack sqlfile) $ getBy (UniqueFileSyncStatusUUID (fileSyncStatusUuid fstat))
+                case me of 
+                  Just _ -> do 
+                    let remotemd5saved = fileSyncStatusMd5 fstat
+                    if (remotemd5saved `elem` synchist ) || (Prelude.null synchist)
+                      then uploading
+                      else do 
+                        liftIO $ putStrLn ("uploadWork" ++ show remotemd5saved ++ "," ++ show synchist)
+                        liftIO $ evhandler (UsrEv (FileSyncFromHub uhdluuid fstat))
+                  Nothing -> uploading
+      return (UsrEv ActionOrdered)
+
+
+uploadAndUpdateSync :: (AllEvent -> IO ()) -> UUID -> HubInfo -> T.Text -> B.ByteString  
+                    -> (FilePath,Maybe FilePath) -> Maybe FilePath 
+                    -> ReaderT (Manager,CookieJar) (ResourceT IO) ()
+uploadAndUpdateSync evhandler uhdluuid hinfo uuidtxt hdlbstr (canfp,mhdlfp) msqlfile = do
+    mfrsync <- sessionGetJSON (hubURL hinfo </> "file" </> T.unpack uuidtxt) 
+    b64txt <- case mfrsync of 
+      Nothing -> (return . TE.decodeUtf8 . B64.encode) hdlbstr
+      Just frsync -> liftIO $ do
+        let rsyncbstr = (B64.decodeLenient . TE.encodeUtf8 . frsync_sig) frsync
+        tdir <- getTemporaryDirectory
+        uuid'' <- nextRandom
+        let tsigfile = tdir </> show uuid'' <.> "sig"
+            tdeltafile = tdir </> show uuid'' <.> "delta"
+        B.writeFile tsigfile rsyncbstr
+        readProcessWithExitCode "rdiff" 
+          ["delta", tsigfile, canfp, tdeltafile] ""
+        deltabstr <- B.readFile tdeltafile 
+        mapM_ removeFile [tsigfile,tdeltafile]
+        (return . TE.decodeUtf8 . B64.encode) deltabstr
+    let filecontent = toJSON FileContent { file_uuid = uuidtxt
+                                         , file_path = T.pack <$> mhdlfp 
+                                         , file_content = b64txt 
+                                         , file_rsync = mfrsync 
+                                         , client_uuid = T.pack (show uhdluuid)
+                                         }
+        filecontentbstr = encode filecontent
+    (manager,coojar) <- ask
+    request3' <- lift $ parseUrl (hubURL hinfo </> "file" </> T.unpack uuidtxt )
+    let request3 = request3' { method = methodPut
+                             , requestBody = RequestBodyStreamChunked (streamContent filecontentbstr)
+                             , cookieJar = Just coojar }
+    _response3 <- lift $ httpLbs request3 manager
+    mfstat2 :: Maybe FileSyncStatus 
+      <- sessionGetJSON (hubURL hinfo </> "sync" </> T.unpack uuidtxt)
+    F.forM_ ((,) <$> msqlfile <*> mfstat2) $ \(sqlfile,fstat2) -> do 
+      runSqlite (T.pack sqlfile) $ upsert fstat2 []
+      liftIO $ evhandler (UsrEv (SyncInfoUpdated uhdluuid fstat2))
+    return ()
+
+-- | 
+initSqliteDB :: MainCoroutine ()
+initSqliteDB = do
+    msqlfile <- view (settings.sqliteFileName) <$> get
+    F.forM_ msqlfile $ \sqlfile -> liftIO $ do
+      runSqlite (T.pack sqlfile) $ runMigration $ migrateAll
+
+-- | 
+updateSyncInfo :: UUID -> FileSyncStatus -> MainCoroutine ()
+updateSyncInfo uuid fstat = do
+    liftIO $ putStrLn "updateSyncInfo called"
+    uhdlsMap <-  snd . view unitHoodles <$> get
+    let uhdls = IM.elems uhdlsMap
+    case find (\x -> view unitUUID x == uuid) uhdls of 
+      Nothing -> return ()
+      Just uhdl -> do 
+        let nuhdlsMap = IM.adjust (over (hoodleFileControl.syncMD5History) (fileSyncStatusMd5 fstat :) ) (view unitKey uhdl) uhdlsMap
+        modify (set (unitHoodles._2) nuhdlsMap)
+
+
+-- | 
+updateSyncInfoAll :: FileSyncStatus -> MainCoroutine ()
+updateSyncInfoAll fstat = do
+    let fileuuid = fileSyncStatusUuid fstat    
+    uhdlsMap <-  snd . view unitHoodles <$> get
+    let f uhdl = let fileuuid' = getHoodleID uhdl
+                 in if fileuuid == fileuuid' 
+                    then over (hoodleFileControl.syncMD5History) (fileSyncStatusMd5 fstat :) uhdl
+                    else uhdl
+        nuhdlsMap = fmap f uhdlsMap
+    modify (set (unitHoodles._2) nuhdlsMap)
+    
+-- |
+fileSyncFromHub :: UUID -> FileSyncStatus -> MainCoroutine ()
+fileSyncFromHub unituuid fstat = do
+    liftIO $ putStrLn "fileSyncFromHub called"
+    uhdlsMap <-  snd . view unitHoodles <$> get
+    let uhdls = IM.elems uhdlsMap
+    hdir <- liftIO $ getHomeDirectory
+    let tokfile = hdir </> ".hoodle.d" </> "token.txt"
+    xst <- get
+    runMaybeT $ do
+      uhdl <- (MaybeT . return . find (\x -> view unitUUID x == unituuid)) uhdls 
+      hdlfp <- MaybeT . return $ getHoodleFilePath uhdl  
+      hset <- (MaybeT . return . view hookSet) xst
+      hinfo <- (MaybeT . return) (hubInfo hset)
+      lift $ prepareToken hinfo tokfile
+      lift $ doIOaction $ \evhandler -> do 
+        forkIO $ (`E.catch` (\(e :: E.SomeException)-> print e >> return ())) $ 
+          withHub hinfo tokfile $ \manager coojar -> do
+            flip runReaderT (manager,coojar) $
+              rsyncPatchWork hinfo hdlfp fstat $
+                (evhandler . UsrEv) (SyncInfoUpdated unituuid fstat)
+        return (UsrEv ActionOrdered)
+    return ()
+
+-- |
+rsyncPatchWork :: HubInfo -> FilePath -> FileSyncStatus 
+               -> IO ()
+               -> ReaderT (Manager,CookieJar) (ResourceT IO) ()
+rsyncPatchWork hinfo hdlfile fstat action = do 
+    (manager,coojar) <- ask
+    let uuidtxt = fileSyncStatusUuid fstat
+    sigtxt <- liftIO $ do 
+                uuid' <- nextRandom
+                tdir <- getTemporaryDirectory
+                let sigfile = tdir </> show uuid' <.> "sig"
+                readProcessWithExitCode "rdiff" ["signature", hdlfile, sigfile] ""
+                bstr <- B.readFile sigfile
+                return (TE.decodeUtf8 (B64.encode bstr))
+    let frsync = FileRsync uuidtxt sigtxt
+        frsyncjsonbstr = (encode . toJSON) frsync
+    req' <- lift $ parseUrl (hubURL hinfo </> "rsyncdown" </> T.unpack uuidtxt)
+    let req = req' { cookieJar = Just coojar 
+                   , requestBody = RequestBodyStreamChunked (streamContent frsyncjsonbstr)
+                   }
+    mfcont <- lift $ AE.decode . responseBody <$> httpLbs req manager
+    F.forM_ mfcont $ \fcont -> do
+      let filebstr = (B64.decodeLenient . TE.encodeUtf8 . file_content) fcont 
+      liftIO $ do 
+        uuid' <- nextRandom
+        tdir <- getTemporaryDirectory 
+        let deltafile = tdir </> show uuid' <.> "delta"
+            newfile = tdir </> show uuid' <.> "hdlnew"
+        B.writeFile deltafile filebstr
+        readProcessWithExitCode "rdiff" ["patch", hdlfile, deltafile, newfile] ""
+        md5str <- show . md5 <$> BL.readFile newfile 
+        when (md5str == T.unpack (fileSyncStatusMd5 fstat)) $ do
+          copyFile newfile hdlfile
+          mapM_ removeFile [deltafile,newfile]
+          Gtk.postGUIAsync action
+        
+-- |
+gotSyncEvent :: Bool -> UUID -> FileSyncStatus -> MainCoroutine ()
+gotSyncEvent isforced unituuid fstat = do
+    liftIO $ putStrLn "gotSyncEvent called"
+    uhdlsMap <-  snd . view unitHoodles <$> get
+    let uhdls = IM.elems uhdlsMap
+    let b = maybe True (const isforced) (find (\x -> view unitUUID x == unituuid) uhdls)
+    when b $ fileSyncFromHub unituuid fstat
+
+-- |
+registerFile :: UUID -> (FilePath,Hoodle) -> MainCoroutine ()
+registerFile uhdluuid (fp,hdl) = do 
+    liftIO $ putStrLn "registerFile called"
+    let hdlbstr = (BL.toStrict . builder) hdl
+    hdir <- liftIO $ getHomeDirectory
+    canfp <- liftIO $ canonicalizePath fp
+    let mhdlfp = Just (makeRelative hdir canfp)
+    xst <- get
+    let fileuuidbstr = view hoodleID hdl
+        fileuuidtxt = TE.decodeUtf8 fileuuidbstr
+    let tokfile = hdir </> ".hoodle.d" </> "token.txt"
+    runMaybeT $ do
+      sqlfile <- (MaybeT . return . view (settings.sqliteFileName)) xst
+      hset <- (MaybeT . return . view hookSet) xst
+      hinfo <- (MaybeT . return) (hubInfo hset)
+      lift $ prepareToken hinfo tokfile
+      lift . doIOaction $ \evhandler -> do 
+        forkIO $ (`E.catch` (\(e :: E.SomeException)-> print e)) $ 
+          withHub hinfo tokfile $ \manager coojar -> do
+            flip runReaderT (manager,coojar) $ do
+              uploadAndUpdateSync evhandler uhdluuid hinfo fileuuidtxt hdlbstr (canfp,mhdlfp) (Just sqlfile)
+              Just fstat <- sessionGetJSON (hubURL hinfo </> "sync" </> T.unpack fileuuidtxt)
+
+              (liftIO . Gtk.postGUIAsync . evhandler . UsrEv) (SyncInfoUpdated uhdluuid fstat)
+        return (UsrEv ActionOrdered)
+    return ()    
+
+-- |
+findUnitHoodleByHoodleID :: String ->  MainCoroutine (Maybe UnitHoodle)
+findUnitHoodleByHoodleID uuidstr = do 
+    uhdlsMap <-  snd . view unitHoodles <$> get
+    let uhdls = IM.elems uhdlsMap
+        muhdl = find ((== uuidstr) . B.unpack . view ghoodleID . getHoodle) uhdls 
+    return muhdl 
+
+
+
+
+openShared :: UUID -> MainCoroutine ()
+openShared uuid = do 
+    xst <- get
+    hdir <- liftIO $ getHomeDirectory
+    let uuidstr = show uuid
+    let tokfile = hdir </> ".hoodle.d" </> "token.txt"
+    tmpfile <- liftIO $ (</> uuidstr <.> "hdl" ) <$> getTemporaryDirectory 
+    liftIO $ writeFile tmpfile "" 
+    runMaybeT $ do
+      hset <- (MaybeT . return . view hookSet) xst
+      hinfo <- (MaybeT . return) (hubInfo hset)
+      lift $ prepareToken hinfo tokfile
+      lift $ doIOaction $ \evhandler -> do 
+        forkIO $ (`E.catch` (\(e :: E.SomeException)-> print e >> return ())) $ 
+          withHub hinfo tokfile $ \manager coojar -> do
+            flip runReaderT (manager,coojar) $ do
+              mfstat <- sessionGetJSON (hubURL hinfo </> "sync" </> uuidstr)
+              case mfstat of
+                Nothing -> return ()
+                Just fstat -> 
+                  rsyncPatchWork hinfo tmpfile fstat $
+                    (evhandler . UsrEv) (OpenTemp uuid tmpfile)
+        return (UsrEv ActionOrdered)
+    return ()
+
+
diff --git a/src/Hoodle/Coroutine/HubInternal.hs-boot b/src/Hoodle/Coroutine/HubInternal.hs-boot
new file mode 100644
--- /dev/null
+++ b/src/Hoodle/Coroutine/HubInternal.hs-boot
@@ -0,0 +1,67 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Hoodle.Coroutine.HubInternal
+-- Copyright   : (c) 2014 Ian-Woo Kim
+--
+-- License     : BSD3
+-- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
+-- Stability   : experimental
+-- Portability : GHC
+--
+-----------------------------------------------------------------------------
+
+module Hoodle.Coroutine.HubInternal where
+
+import           Control.Applicative
+import qualified Control.Exception as E
+import           Control.Lens (view)
+import           Control.Monad (unless)
+import           Control.Monad.IO.Class
+import           Control.Monad.State
+import           Control.Monad.Trans.Maybe
+-- import           Control.Monad.Trans.State
+import           Data.Aeson as AE
+import qualified Data.ByteString.Base64 as B64
+import qualified Data.ByteString.Char8 as B
+import qualified Data.ByteString.Lazy.Char8 as BL
+import qualified Data.Foldable as F
+import qualified Data.HashMap.Strict as H
+import qualified Data.List as L
+import Data.Monoid ((<>))
+import Data.Text (Text,pack,unpack)
+import Data.Text.Encoding (encodeUtf8,decodeUtf8)
+import Data.Time.Calendar
+import Data.Time.Clock
+import Data.UUID.V4
+import Network
+import Network.Google.OAuth2 (formUrl, exchangeCode, refreshTokens,
+                               OAuth2Client(..), OAuth2Tokens(..))
+import Network.Google (makeRequest, doRequest)
+import Network.HTTP.Conduit
+import Network.HTTP.Types (methodPut)
+import System.Directory
+import System.Environment (getEnv)
+import System.Exit    (ExitCode(..))
+import System.FilePath ((</>),(<.>),makeRelative)
+import System.Info (os)
+import System.Process (system, rawSystem,readProcessWithExitCode)
+--
+-- import Data.Hoodle.Generic
+import Data.Hoodle.Simple
+import Graphics.Hoodle.Render.Type.Hoodle
+import Text.Hoodle.Builder (builder)
+--
+import Hoodle.Coroutine.Draw
+import Hoodle.Script.Hook
+import Hoodle.Type.Coroutine
+import Hoodle.Type.Event
+import Hoodle.Type.Hub
+import Hoodle.Type.HoodleState
+import Hoodle.Util
+
+
+uploadWork :: (FilePath,FilePath) -> HubInfo -> MainCoroutine ()
diff --git a/src/Hoodle/Coroutine/LaTeX.hs b/src/Hoodle/Coroutine/LaTeX.hs
new file mode 100644
--- /dev/null
+++ b/src/Hoodle/Coroutine/LaTeX.hs
@@ -0,0 +1,100 @@
+{-# LANGUAGE MultiWayIf #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TupleSections #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Hoodle.Coroutine.LaTeX
+-- Copyright   : (c) 2011-2014 Ian-Woo Kim
+--
+-- License     : BSD3
+-- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
+-- Stability   : experimental
+-- Portability : GHC
+--
+-----------------------------------------------------------------------------
+
+module Hoodle.Coroutine.LaTeX where
+
+import Control.Lens
+import Control.Monad.Trans.Maybe
+import Control.Monad.State
+import           Data.Function (on)
+import Data.List (sortBy)
+import Data.Maybe
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as TE
+-- 
+import Data.Hoodle.Simple
+--
+import Hoodle.ModelAction.Text
+--
+
+hoistMaybe :: (Monad m) => Maybe a -> MaybeT m a
+hoistMaybe = MaybeT . return
+
+getLaTeXComponentsFromHdl :: Hoodle -> [(Maybe T.Text,(Int,Double,T.Text))] 
+getLaTeXComponentsFromHdl hdl = 
+    let mlatex_components = do 
+          (pgnum,pg) <- (zip ([1..] :: [Int]) . view pages) hdl  
+          l <- view layers pg
+          i <- view items l
+          case i of 
+            ItemSVG svg -> 
+              runMaybeT $ do
+                v <- hoistMaybe (svg_command svg)
+                guard (v == "latex")
+                svgtextbstr <- hoistMaybe (svg_text svg)
+                let (_,y) = svg_pos svg  
+                    svgtext = TE.decodeUtf8 svgtextbstr
+                    mk = extractKeyword svgtext
+                return (mk,(pgnum,y,svgtext))
+            _ -> []
+        cfunc :: (Ord a,Ord b,Ord c) => (a,b,c) -> (a,b,c) -> Ordering 
+        cfunc x y | view _1 x > view _1 y = GT
+                  | view _1 x < view _1 y = LT
+                  | otherwise = if | view _2 x > view _2 y -> GT
+                                   | view _2 x < view _2 y -> LT
+                                   | otherwise -> EQ
+        latex_components = catMaybes  mlatex_components
+        sorted = sortBy (cfunc `on` snd) latex_components 
+    in sorted
+
+{- 
+updateLaTeX :: MainCoroutine ()
+updateLaTeX = do
+    rhdl <- getHoodle <$> get
+    let hdl = rHoodle2Hoodle rhdl
+    runMaybeT $ do 
+      {- txtsrc <- -} MaybeT $ return (rhdl ^. gembeddedtext)  
+      -- let km = getKeywordMap txtsrc
+      -- liftIO $ print km
+    -- let sorted = getLaTeXComponentsFromHdl hdl
+    -- liftIO $ print sorted 
+    return ()
+-}
+
+laTeXHeader :: T.Text
+laTeXHeader = 
+  "\\documentclass[a4paper]{article}\n\
+  \\\usepackage[affil-it]{authblk}\n\
+  \\\usepackage{xeCJK}\n\
+  \\\xeCJKsetup{\n\
+  \  CJKspace=true,\n\
+  \  CJKecglue={}\n\
+  \}\n\
+  \\\usepackage{setspace}\n\
+  \\\onehalfspacing\n\
+  \\\usepackage{fontspec}\n\
+  \\\setCJKmainfont{NanumGothic}\n\
+  \\\usepackage{minted}\n\
+  \\\pagestyle{empty}\n\
+  \\\begin{document}\n"
+
+
+-- \\\\documentclass{article}\n\
+--              \\\pagestyle{empty}\n\
+--              \\\begin{document}\n
+                                
+laTeXFooter :: T.Text
+laTeXFooter = "\\end{document}\n"
diff --git a/src/Hoodle/Coroutine/Layer.hs b/src/Hoodle/Coroutine/Layer.hs
--- a/src/Hoodle/Coroutine/Layer.hs
+++ b/src/Hoodle/Coroutine/Layer.hs
@@ -3,9 +3,9 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.Layer 
--- Copyright   : (c) 2011-2013 Ian-Woo Kim
+-- Copyright   : (c) 2011-2014 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -17,10 +17,9 @@
 import Control.Monad.State
 import qualified Data.IntMap as M
 import Control.Category
--- import Data.Label
 import Control.Lens (view,set)
 import Data.IORef
-import Graphics.UI.Gtk hiding (get,set)
+import qualified Graphics.UI.Gtk as Gtk
 --
 import Data.Hoodle.Generic
 import Data.Hoodle.Zipper
@@ -40,32 +39,39 @@
 
 
 layerAction :: (HoodleModeState -> Int -> Page EditMode -> MainCoroutine HoodleModeState) 
-            -> MainCoroutine HoodleState
+            -> MainCoroutine UnitHoodle
 layerAction action = do 
     xst <- get 
-    forBoth' unboxBiAct (fsingle xst) . view currentCanvasInfo $ xst
+    forBoth' unboxBiAct (fsingle xst) . view (unitHoodles.currentUnit.currentCanvasInfo) $ xst
   where 
     fsingle xstate cvsInfo = do
-      let epage = getCurrentPageEitherFromHoodleModeState cvsInfo hdlmodst
+      let uhdl = view (unitHoodles.currentUnit) xstate
+          epage = getCurrentPageEitherFromHoodleModeState cvsInfo hdlmodst
           cpn = view currentPageNum cvsInfo
-          hdlmodst = view hoodleModeState xstate
+          hdlmodst = view hoodleModeState uhdl
       newhdlmodst <- either (action hdlmodst cpn) (action hdlmodst cpn . hPage2RPage) epage 
-      return =<< (liftIO (updatePageAll newhdlmodst . set hoodleModeState newhdlmodst $ xstate))
+      return =<< (liftIO (updatePageAll newhdlmodst . set hoodleModeState newhdlmodst $ uhdl))
 
 -- | 
 
 makeNewLayer :: MainCoroutine () 
-makeNewLayer = layerAction newlayeraction >>= commit >> invalidateAll 
+makeNewLayer = do
+    xst <- get
+    commit . flip (set (unitHoodles.currentUnit)) xst =<< layerAction newlayeraction
+    invalidateAll 
   where newlayeraction hdlmodst cpn page = do 
+          sfcid <- issueSurfaceID
           let lyrzipper = view glayers page  
-              emptylyr = emptyRLayer 
+              emptylyr = emptyRLayer sfcid
               nlyrzipper = appendGoLast lyrzipper emptylyr 
               npage = set glayers nlyrzipper page
           return . setPageMap (M.adjust (const npage) cpn . getPageMap $ hdlmodst) $ hdlmodst 
                 
 
 gotoNextLayer :: MainCoroutine ()
-gotoNextLayer = layerAction nextlayeraction >>= put >> invalidateAll 
+gotoNextLayer = do
+    modify . set (unitHoodles.currentUnit) =<< layerAction nextlayeraction 
+    invalidateAll 
   where nextlayeraction hdlmodst cpn page = do 
           let lyrzipper = view glayers page  
               mlyrzipper = moveRight lyrzipper 
@@ -73,7 +79,9 @@
           return . setPageMap (M.adjust (const npage) cpn . getPageMap $ hdlmodst) $ hdlmodst  
 
 gotoPrevLayer :: MainCoroutine ()
-gotoPrevLayer = layerAction prevlayeraction >>= put >> invalidateAll 
+gotoPrevLayer = do
+    modify . set (unitHoodles.currentUnit) =<< layerAction prevlayeraction
+    invalidateAll 
   where prevlayeraction hdlmodst cpn page = do 
           let lyrzipper = view glayers page  
               mlyrzipper = moveLeft lyrzipper 
@@ -82,7 +90,9 @@
 
 
 gotoLayerAt :: Int -> MainCoroutine ()
-gotoLayerAt n = layerAction gotoaction >>= put >> invalidateAll 
+gotoLayerAt n = do
+    modify . set (unitHoodles.currentUnit) =<< layerAction gotoaction 
+    invalidateAll 
   where gotoaction hdlmodst cpn page = do 
           let lyrzipper = view glayers page  
               mlyrzipper = moveTo n lyrzipper 
@@ -91,7 +101,10 @@
 
 
 deleteCurrentLayer :: MainCoroutine ()
-deleteCurrentLayer = layerAction deletelayeraction >>= commit >> invalidateAll 
+deleteCurrentLayer = do
+    xst <- get
+    commit . flip (set (unitHoodles.currentUnit)) xst =<< layerAction deletelayeraction
+    invalidateAll 
   where deletelayeraction hdlmodst cpn page = do 
           let lyrzipper = view glayers page  
               mlyrzipper = deleteCurrent lyrzipper 
@@ -100,27 +113,27 @@
 
 startGotoLayerAt :: MainCoroutine ()
 startGotoLayerAt = 
-    forBoth' unboxBiAct fsingle . view currentCanvasInfo =<< get
+    forBoth' unboxBiAct fsingle . view (unitHoodles.currentUnit.currentCanvasInfo) =<< get
   where 
     fsingle cvsInfo = do 
       xstate <- get 
-      let hdlmodst = view hoodleModeState xstate
-      let epage = getCurrentPageEitherFromHoodleModeState cvsInfo hdlmodst
+      let uhdl = view (unitHoodles.currentUnit) xstate
+          hdlmodst = view hoodleModeState uhdl
+          epage = getCurrentPageEitherFromHoodleModeState cvsInfo hdlmodst
           page = either id (hPage2RPage) epage 
           lyrzipper = view glayers page
           cidx = currIndex lyrzipper
           len  = lengthSZ lyrzipper 
       lref <- liftIO $ newIORef cidx
       dialog <- liftIO (layerChooseDialog lref cidx len)
-      res <- liftIO $ dialogRun dialog
+      res <- liftIO $ Gtk.dialogRun dialog
       case res of 
-        ResponseDeleteEvent -> liftIO $ widgetDestroy dialog
-        ResponseOk ->  do
-          liftIO $ widgetDestroy dialog
+        Gtk.ResponseDeleteEvent -> liftIO $ Gtk.widgetDestroy dialog
+        Gtk.ResponseOk ->  do
+          liftIO $ Gtk.widgetDestroy dialog
           newnum <- liftIO (readIORef lref)
-          -- liftIO $ putStrLn (show (newnum))
           gotoLayerAt newnum
-        ResponseCancel -> liftIO $ widgetDestroy dialog
+        Gtk.ResponseCancel -> liftIO $ Gtk.widgetDestroy dialog
         _ -> error "??? in fileOpen " 
       return ()
 
diff --git a/src/Hoodle/Coroutine/Link.hs b/src/Hoodle/Coroutine/Link.hs
--- a/src/Hoodle/Coroutine/Link.hs
+++ b/src/Hoodle/Coroutine/Link.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE OverloadedStrings #-}
@@ -8,9 +9,9 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.Link
--- Copyright   : (c) 2013, 2014 Ian-Woo Kim
+-- Copyright   : (c) 2013-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -20,28 +21,32 @@
 module Hoodle.Coroutine.Link where
 
 import           Control.Applicative
-import           Control.Concurrent (forkIO)
-import           Control.Lens (at,view,set,(%~))
-import           Control.Monad (forever,void)
-import           Control.Monad.State (get,put,modify,liftIO,guard,when)
+import           Control.Lens (_2,at,view,set,(^.))
+import           Control.Monad hiding (forM_)
+import           Control.Monad.State (get,liftIO)
 import           Control.Monad.Trans.Maybe
 import qualified Data.ByteString.Char8 as B 
 import           Data.Foldable (forM_)
+import qualified Data.IntMap as IM
 import qualified Data.Map as M
 import           Data.Maybe (mapMaybe)
 import           Data.Monoid (mconcat)
 import           Data.UUID.V4 (nextRandom)
 import qualified Data.Text as T
 import qualified Data.Text.Encoding as TE
+import qualified Graphics.UI.Gtk as Gtk
+import           System.Directory
+import           System.FilePath 
+import           System.Process (createProcess, proc)
+#ifdef HUB
+import           Control.Concurrent (forkIO)
 import           DBus
 import           DBus.Client
-import           Graphics.UI.Gtk hiding (get,set) 
-import           System.FilePath 
+#endif
 -- from hoodle-platform
-import           Control.Monad.Trans.Crtn.Queue 
 import           Data.Hoodle.BBox
 import           Data.Hoodle.Generic
-import           Data.Hoodle.Simple -- (Anchor(..),Item(..),SVG(..),pages,layers,items)
+import           Data.Hoodle.Simple
 import           Data.Hoodle.Zipper
 import           Graphics.Hoodle.Render.Item 
 import           Graphics.Hoodle.Render.Type 
@@ -51,10 +56,10 @@
 import           Hoodle.Accessor
 import           Hoodle.Coroutine.Dialog
 import           Hoodle.Coroutine.Draw
--- import           Hoodle.Coroutine.File (insertItemAt)
 import           Hoodle.Coroutine.Page (changePage)
 import           Hoodle.Coroutine.Select.Clipboard
 import           Hoodle.Coroutine.TextInput 
+import           Hoodle.Coroutine.Window
 import           Hoodle.Device 
 import           Hoodle.ModelAction.ContextMenu
 import           Hoodle.ModelAction.File (makeNewItemImage)
@@ -67,17 +72,49 @@
 import           Hoodle.Type.PageArrangement
 import           Hoodle.Util 
 import           Hoodle.View.Coordinate
+#ifdef HUB
+import           Hoodle.Coroutine.File
+#endif
 --
 import Prelude hiding (mapM_)
 
+-- | 
+openLinkAction :: UrlPath 
+               -> Maybe (T.Text,T.Text) -- ^ (docid,anchorid)
+               -> MainCoroutine () 
+openLinkAction urlpath mid = do 
+    case urlpath of 
+      FileUrl fp -> do
+        mk <- liftIO . checkPreviouslyOpenedFile fp =<< get
+        case mk of 
+          Just k -> switchTab k >> forM_ mid (uncurry goToAnchorPos)
+          Nothing -> addTab (LocalDir (Just fp)) >> 
+#ifdef HUB
+                     syncFile >> 
+#endif
+                     forM_ mid (uncurry goToAnchorPos)
+      HttpUrl url -> liftIO $ createProcess (proc "xdg-open" [url]) >> return () 
+
+-- |
+checkPreviouslyOpenedFile :: FilePath -> HoodleState -> IO (Maybe Int)
+checkPreviouslyOpenedFile fp xst = do
+    cfp <- canonicalizePath fp
+    lst <- filterM (checker cfp . snd) (IM.assocs (xst ^. unitHoodles._2))
+    case lst of
+      x:_ -> return (Just (fst x))
+      _ -> return Nothing
+  where checker cfp uhdl = getHoodleFilePath uhdl # 
+                             maybe (return False) $ \fp' -> do cfp' <- canonicalizePath fp' 
+                                                               return (cfp == cfp') 
+
 makeTextSVGFromStringAt :: String 
-                           -> CanvasId 
-                           -> HoodleState
-                           -> CanvasCoordinate
-                           -> IO (B.ByteString, BBox)
-makeTextSVGFromStringAt str cid xst ccoord = do 
+                        -> CanvasId 
+                        -> UnitHoodle
+                        -> CanvasCoordinate
+                        -> IO (B.ByteString, BBox)
+makeTextSVGFromStringAt str cid uhdl ccoord = do 
     rdr <- makePangoTextSVG (0,0) (T.pack str) -- for the time being, I use string  
-    geometry <- getCanvasGeometryCvsId cid xst 
+    geometry <- getCanvasGeometryCvsId cid uhdl
     let mpgcoord = (desktop2Page geometry . canvas2Desktop geometry) ccoord 
     return $ case mpgcoord of 
                Nothing -> rdr 
@@ -88,11 +125,11 @@
 -- | 
 notifyLink :: CanvasId -> PointerCoord -> MainCoroutine () 
 notifyLink cid pcoord = do 
-    xst <- get 
-    (forBoth' unboxBiAct (f xst) . getCanvasInfo cid) xst 
+    uhdl <- view (unitHoodles.currentUnit) <$> get 
+    forBoth' unboxBiAct (f uhdl) (getCanvasInfo cid uhdl)
   where 
-    f :: forall b. HoodleState -> CanvasInfo b -> MainCoroutine ()
-    f xst cvsInfo = do 
+    f :: forall b. UnitHoodle -> CanvasInfo b -> MainCoroutine ()
+    f uhdl cvsInfo = do 
       let cpn = PageNum . view currentPageNum $ cvsInfo
           arr = view (viewInfo.pageArrangement) cvsInfo              
           mnotifyitem = view notifiedItem cvsInfo
@@ -102,7 +139,7 @@
         case (desktop2Page geometry . device2Desktop geometry) pcoord of 
           Nothing -> return Nothing 
           Just (pnum,PageCoord (x,y)) -> do 
-            let hdl = getHoodle xst
+            let hdl = getHoodle uhdl
                 mpage = view (gpages.at (unPageNum pnum)) hdl
             case mpage of
               Nothing -> return Nothing
@@ -113,27 +150,26 @@
                     hitted = takeHitted hlnks 
                 case mnotifyitem of 
                   Nothing -> if ((not.null) hitted) 
-                             then Just <$> newNotify cvsInfo geometry pnum (head hitted) Nothing  
+                             then Just <$> newNotify geometry pnum (head hitted) Nothing  
                              else return Nothing 
                   Just (opnum,obbx,_) -> do
                     let obbx_desk = xformBBox (unDeskCoord . page2Desktop geometry . (opnum,) . PageCoord) obbx   
                     if pnum == opnum &&  isPointInBBox obbx (x,y) 
                       then return Nothing
                       else if ((not.null) hitted) 
-                           then Just <$> newNotify cvsInfo geometry pnum (head hitted) (Just obbx_desk)
+                           then Just <$> newNotify geometry pnum (head hitted) (Just obbx_desk)
                            else return (Just (Nothing,obbx_desk))
       forM_ mresult (\(mnewnotified,bbx_desk) -> do
-                      let ncinfobox = (set (unboxLens notifiedItem) mnewnotified . getCanvasInfo cid) xst 
-                      put (setCanvasInfo (cid,ncinfobox) xst)
+                      let ncinfobox = (set (unboxLens notifiedItem) mnewnotified . getCanvasInfo cid) uhdl 
+                      pureUpdateUhdl $ setCanvasInfo (cid,ncinfobox)
                       invalidateInBBox (Just bbx_desk) Efficient cid )
     ----                                                                                      
-    newNotify :: CanvasInfo a -> CanvasGeometry -> PageNum -> RItem -> Maybe BBox 
+    newNotify :: CanvasGeometry -> PageNum -> RItem -> Maybe BBox 
                  -> MainCoroutine (Maybe (PageNum,BBox,RItem),BBox) 
-    newNotify _cvsInfo geometry pnum lnk mobbx_desk = do        
+    newNotify geometry pnum lnk mobbx_desk = do        
       let bbx = getBBox lnk
           bbx_desk = xformBBox (unDeskCoord . page2Desktop geometry . (pnum,) . PageCoord) bbx
-          nbbx_desk = maybe bbx_desk (\obbx_desk->unionBBox bbx_desk obbx_desk) mobbx_desk
-      liftIO $ print (pnum,bbx)
+          nbbx_desk = maybe bbx_desk (unionBBox bbx_desk) mobbx_desk
       return (Just (pnum,bbx,lnk),nbbx_desk)
           
 
@@ -141,9 +177,9 @@
 gotLink :: Maybe String -> (Int,Int) -> MainCoroutine () 
 gotLink mstr (x,y) = do 
   xst <- get 
-  -- liftIO $ print mstr 
-  let cid = getCurrentCanvasId xst
-      cache = view renderCache xst
+  cache <- renderCache
+  let uhdl = view (unitHoodles.currentUnit) xst 
+      cid = getCurrentCanvasId uhdl
   mr <- runMaybeT $ do 
     str <- (MaybeT . return) mstr 
     let (str1,rem1) = break (== ',') str 
@@ -165,17 +201,16 @@
                                liftIO (makeNewItemImage isembedded file)
               RenderEv (GotRItem nitm) <- 
                 waitSomeEvent (\case RenderEv (GotRItem _) -> True ; _ -> False )
-              geometry <- liftIO $ getCanvasGeometryCvsId cid xst               
+              geometry <- liftIO $ getCanvasGeometryCvsId cid uhdl               
               let ccoord = CvsCoord (fromIntegral x,fromIntegral y)
                   mpgcoord = (desktop2Page geometry . canvas2Desktop geometry) ccoord 
               insertItemAt mpgcoord nitm 
             else return ()  
         Just (HttpUrl url) -> do 
-          case getSelectedItmsFromHoodleState xst of     
+          case getSelectedItmsFromUnitHoodle uhdl of     
             Nothing -> do 
               uuidbstr <- liftIO $ B.pack . show <$> nextRandom              
-              rdrbbx <- liftIO $ makeTextSVGFromStringAt url cid xst 
-                                   (CvsCoord (fromIntegral x,fromIntegral y))
+              rdrbbx <- liftIO $ makeTextSVGFromStringAt url cid uhdl (CvsCoord (fromIntegral x,fromIntegral y))
               linkInsert "simple" (uuidbstr,url) url rdrbbx
             Just hititms -> do 
               b <- okCancelMessageBox ("replace selected item with link to " ++ url  ++ "?")
@@ -183,24 +218,23 @@
                 let ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) hititms 
                 case ulbbox of 
                   Middle bbox -> do 
-                    svg <- liftIO $ makeSVGFromSelection cache hititms bbox
+                    svg <- liftIO $ makeSVGFromSelection cache cid hititms bbox
                     uuidbstr <- liftIO $ B.pack . show <$> nextRandom
                     deleteSelection 
                     linkInsert "simple" (uuidbstr,url) url (svg_render svg,bbox)  
                   _ -> return ()          
     Just (uuidbstr,fp) -> do 
       let fn = takeFileName fp 
-      case getSelectedItmsFromHoodleState xst of     
+      case getSelectedItmsFromUnitHoodle uhdl of     
         Nothing -> do 
           rdr <- liftIO (makePangoTextSVG (0,0) (T.pack fn)) 
-          geometry <- liftIO $ getCanvasGeometryCvsId cid xst 
+          geometry <- liftIO $ getCanvasGeometryCvsId cid uhdl 
           let ccoord = CvsCoord (fromIntegral x,fromIntegral y)
               mpgcoord = (desktop2Page geometry . canvas2Desktop geometry) ccoord 
               rdr' = case mpgcoord of 
                        Nothing -> rdr 
                        Just (_,PageCoord (x',y')) -> 
-                         let bbox' = moveBBoxULCornerTo (x',y') (snd rdr) 
-                         in (fst rdr,bbox')
+                         let bbox' = moveBBoxULCornerTo (x',y') (snd rdr) in (fst rdr,bbox')
           linkInsert "simple" (uuidbstr,fp) fn rdr' 
         Just hititms -> do 
           b <- okCancelMessageBox ("replace selected item with link to " ++ fn ++ "?")
@@ -208,22 +242,20 @@
             let ulbbox = (unUnion . mconcat . fmap (Union . Middle . getBBox)) hititms 
             case ulbbox of 
               Middle bbox -> do 
-                svg <- liftIO $ makeSVGFromSelection cache hititms bbox
+                svg <- liftIO $ makeSVGFromSelection cache cid hititms bbox
                 uuid <- liftIO $ nextRandom
                 let uuidbstr' = B.pack (show uuid) 
                 deleteSelection 
                 linkInsert "simple" (uuidbstr',fp) fn (svg_render svg,bbox)  
               _ -> return ()          
-  liftIO $ putStrLn "gotLink"
-  liftIO $ print mstr 
-  liftIO $ print (x,y)
 
+
 -- | 
 addLink :: MainCoroutine ()
 addLink = do 
-    mfilename <- fileChooser FileChooserActionOpen Nothing 
-    modify (tempQueue %~ enqueue (action mfilename)) 
-    minput <- go
+    mfilename <- fileChooser Gtk.FileChooserActionOpen Nothing 
+    doIOaction $ const (action mfilename) 
+    AddLink minput <- waitSomeEvent (\case AddLink _ -> True; _ -> False)
     case minput of 
       Nothing -> return () 
       Just (str,fname) -> do 
@@ -232,60 +264,51 @@
         rdr <- liftIO (makePangoTextSVG (0,0) (T.pack str)) 
         linkInsert "simple" (uuidbstr,fname) str rdr 
   where 
-    go = do r <- nextevent
-            case r of 
-              AddLink minput -> return minput 
-              UpdateCanvas cid -> -- this is temporary 
-                                  (invalidateInBBox Nothing Efficient cid) >> go 
-              _ -> go 
-    action mfn = mkIOaction $ 
-                   \_evhandler -> do 
-                     dialog <- messageDialogNew Nothing [DialogModal]
-                                 MessageQuestion ButtonsOkCancel "add link" 
-                     vbox <- dialogGetUpper dialog
-                     txtvw <- textViewNew
-                     boxPackStart vbox txtvw PackGrow 0 
-                     widgetShowAll dialog
-                     res <- dialogRun dialog 
+    action mfn = do  dialog <- Gtk.messageDialogNew Nothing [Gtk.DialogModal]
+                                 Gtk.MessageQuestion Gtk.ButtonsOkCancel ("add link" :: String)
+#ifdef GTK3                               
+                     upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)
+                     vbox <- Gtk.vBoxNew False 0
+                     Gtk.containerAdd upper vbox
+#else
+                     vbox <- Gtk.dialogGetUpper dialog
+#endif
+                     txtvw <- Gtk.textViewNew
+                     Gtk.boxPackStart vbox txtvw Gtk.PackGrow 0 
+                     Gtk.widgetShowAll dialog
+                     res <- Gtk.dialogRun dialog 
                      case res of 
-                       ResponseOk -> do 
-                         buf <- textViewGetBuffer txtvw 
-                         (istart,iend) <- (,) <$> textBufferGetStartIter buf
-                                              <*> textBufferGetEndIter buf
-                         l <- textBufferGetText buf istart iend True
-                         widgetDestroy dialog
+                       Gtk.ResponseOk -> do 
+                         buf <- Gtk.textViewGetBuffer txtvw 
+                         (istart,iend) <- (,) <$> Gtk.textBufferGetStartIter buf
+                                              <*> Gtk.textBufferGetEndIter buf
+                         l <- Gtk.textBufferGetText buf istart iend True
+                         Gtk.widgetDestroy dialog
                          return (UsrEv (AddLink ((l,) <$> mfn)))
-                       _ -> do 
-                         widgetDestroy dialog
-                         return (UsrEv (AddLink Nothing))
+                       _ -> Gtk.widgetDestroy dialog >> return (UsrEv (AddLink Nothing))
 
                 
 -- | 
 listAnchors :: MainCoroutine ()
-listAnchors = liftIO . print . getAnchorMap . rHoodle2Hoodle . getHoodle =<< get
+listAnchors = msgShout . show . getAnchorMap . rHoodle2Hoodle . getHoodle . view (unitHoodles.currentUnit) =<< get
 
 getAnchorMap :: Hoodle -> M.Map T.Text (Int, (Double,Double))
 getAnchorMap hdl = 
     let pgs = view pages hdl
-        itemsInPage pg = do l <- view layers pg 
-                            i <- view items l 
-                            return i
+        itemsInPage pg = [i | l <- view layers pg, i <- view items l ]
         anchorsWithPageNum :: [(Int,[Anchor])] 
-        anchorsWithPageNum = zip [0..] 
-                               (map (mapMaybe lookupAnchor . itemsInPage) pgs)
-        anchormap = foldr (\(p,ys) m -> foldr (insertAnchor p) m ys) 
-                      M.empty anchorsWithPageNum
-    in anchormap
+        anchorsWithPageNum = zip [0..] (map (mapMaybe lookupAnchor . itemsInPage) pgs)
+    in foldr (\(p,ys) m -> foldr (insertAnchor p) m ys) M.empty anchorsWithPageNum -- anchormap
   where lookupAnchor (ItemAnchor a) = Just a
         lookupAnchor _ = Nothing
-        insertAnchor pgnum (Anchor {..}) = 
-          M.insert (TE.decodeUtf8 anchor_id) (pgnum,anchor_pos)  
+        insertAnchor pgnum (Anchor {..}) = M.insert (TE.decodeUtf8 anchor_id) (pgnum,anchor_pos)  
          
+
 -- | 
+#ifdef HUB
 startLinkReceiver :: MainCoroutine ()
 startLinkReceiver = do 
-    xst <- get
-    let callback = view callBack xst 
+    callback <- view callBack <$> get 
     liftIO . forkIO $ do
       client <- connectSession
       requestName client "org.ianwookim" []
@@ -304,19 +327,18 @@
               let  r = T.splitOn "," txt
               case r of 
                 docid:anchorid:_ -> 
-                  (postGUISync . callback . UsrEv . DBusEv . GoToLink) 
+                  (Gtk.postGUISync . callback . UsrEv . DBusEv . GoToLink) 
                     (docid,anchorid) 
                 _ -> return ()
             _ -> return ()           
+#endif
 
+
 goToAnchorPos :: T.Text -> T.Text -> MainCoroutine ()
 goToAnchorPos docid anchorid = do 
-    xst <- get
-    let rhdl = getHoodle xst 
-        hdl = rHoodle2Hoodle rhdl
+    rhdl <- getHoodle . view (unitHoodles.currentUnit) <$> get
+    let hdl = rHoodle2Hoodle rhdl
     when (docid == (TE.decodeUtf8 . view ghoodleID) rhdl) $ do
       let anchormap = getAnchorMap hdl
-      forM_ (M.lookup anchorid anchormap) $ \(pgnum,(x,y))-> do
-        liftIO $ print (pgnum,(x,y))
-        changePage (const pgnum)
+      forM_ (M.lookup anchorid anchormap) $ \(pgnum,_)-> changePage (const pgnum)
 
diff --git a/src/Hoodle/Coroutine/Minibuffer.hs b/src/Hoodle/Coroutine/Minibuffer.hs
--- a/src/Hoodle/Coroutine/Minibuffer.hs
+++ b/src/Hoodle/Coroutine/Minibuffer.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE LambdaCase #-}
 
 -----------------------------------------------------------------------------
@@ -15,15 +16,14 @@
 module Hoodle.Coroutine.Minibuffer where 
 
 import           Control.Applicative ((<$>),(<*>))
-import           Control.Lens ((%~),view)
-import           Control.Monad.State (modify,get)
+import           Control.Lens (view)
+import           Control.Monad.State (get)
 import           Control.Monad.Trans (liftIO)
 import           Data.Foldable (Foldable(..),mapM_,forM_,toList)
 import           Data.Sequence (Seq,(|>),empty,singleton,viewl,ViewL(..))
 import qualified Graphics.Rendering.Cairo as Cairo
-import           Graphics.UI.Gtk hiding (get,set)
+import qualified Graphics.UI.Gtk as Gtk
 -- 
-import           Control.Monad.Trans.Crtn.Queue (enqueue)
 import           Data.Hoodle.Simple
 import           Graphics.Hoodle.Render (renderStrk)
 --
@@ -60,40 +60,48 @@
     xst <- get
     let dev = view deviceList xst 
     let ui = view gtkUIManager xst 
-    agr <- liftIO ( uiManagerGetActionGroups ui >>= \x ->
+    agr <- liftIO ( Gtk.uiManagerGetActionGroups ui >>= \x ->
                       case x of 
                         [] -> error "No action group? "
                         y:_ -> return y )
-    uxinputa <- liftIO (actionGroupGetAction agr "UXINPUTA" >>= \(Just x) -> 
-                          return (castToToggleAction x) )
-    doesUseX11Ext <- liftIO $ toggleActionGetActive uxinputa
-    modify (tempQueue %~ enqueue (action dev doesUseX11Ext)) 
+    uxinputa <- liftIO (Gtk.actionGroupGetAction agr "UXINPUTA" >>= \(Just x) -> 
+                          return (Gtk.castToToggleAction x) )
+    doesUseX11Ext <- liftIO $ Gtk.toggleActionGetActive uxinputa
+    doIOaction (action dev doesUseX11Ext)
     minibufInit
   where 
-    action dev _doesUseX11Ext = mkIOaction $ \evhandler -> do 
-      dialog <- dialogNew 
-      msgLabel <- labelNew (Just msg) 
-      cvs <- drawingAreaNew                           
-      cvs `on` sizeRequest $ return (Requisition 500 50)
-      cvs `on` exposeEvent $ tryEvent $ do
-        drawwdw <- liftIO $ widgetGetDrawWindow cvs                 
-        liftIO (renderWithDrawable drawwdw drawMiniBufBkg)
+    action dev _doesUseX11Ext = \evhandler -> do 
+      dialog <- Gtk.dialogNew 
+      msgLabel <- Gtk.labelNew (Just msg) 
+      cvs <- Gtk.drawingAreaNew                           
+      cvs `Gtk.on` Gtk.sizeRequest $ return (Gtk.Requisition 500 50)
+      cvs `Gtk.on` Gtk.exposeEvent $ Gtk.tryEvent $ do
+#ifdef GTK3        
+        Just drawwdw <- liftIO $ Gtk.widgetGetWindow cvs
+#else
+        drawwdw <- liftIO $ Gtk.widgetGetDrawWindow cvs                 
+#endif
+#ifdef GTK3
+        liftIO (Gtk.renderWithDrawWindow drawwdw drawMiniBufBkg)
+#else
+        liftIO (Gtk.renderWithDrawable drawwdw drawMiniBufBkg)
+#endif
         (liftIO . evhandler . UsrEv . MiniBuffer . MiniBufferInitialized) drawwdw
-      cvs `on` buttonPressEvent $ tryEvent $ do 
+      cvs `Gtk.on` Gtk.buttonPressEvent $ Gtk.tryEvent $ do 
         (mbtn,mp) <- getPointer dev
         forM_ mp $ \p -> do
           let pbtn = maybe PenButton1 id mbtn 
           case pbtn of
             TouchButton -> return ()
             _ -> (liftIO . evhandler . UsrEv . MiniBuffer) (MiniBufferPenDown pbtn p)
-      cvs `on` buttonReleaseEvent $ tryEvent $ do 
+      cvs `Gtk.on` Gtk.buttonReleaseEvent $ Gtk.tryEvent $ do 
         (mbtn,mp) <- getPointer dev
         forM_ mp $ \p -> do  
           let pbtn = maybe PenButton1 id mbtn 
           case pbtn of
             TouchButton -> return ()
             _ -> (liftIO . evhandler . UsrEv . MiniBuffer) (MiniBufferPenUp p)
-      cvs `on` motionNotifyEvent $ tryEvent $ do 
+      cvs `Gtk.on` Gtk.motionNotifyEvent $ Gtk.tryEvent $ do 
         (mbtn,mp) <- getPointer dev
         forM_ mp $ \p -> do  
             let pbtn = maybe PenButton1 id mbtn      
@@ -103,23 +111,29 @@
       {- if doesUseX11Ext 
         then widgetSetExtensionEvents cvs [ExtensionEventsAll]
         else widgetSetExtensionEvents cvs [ExtensionEventsNone] -}
-      widgetAddEvents cvs [PointerMotionMask,Button1MotionMask]      
+      Gtk.widgetAddEvents cvs [Gtk.PointerMotionMask,Gtk.Button1MotionMask]
       --
-      vbox <- dialogGetUpper dialog
-      hbox <- hBoxNew False 0 
-      boxPackStart hbox msgLabel PackNatural 0 
-      boxPackStart vbox hbox PackNatural 0
-      boxPackStart vbox cvs PackNatural 0
-      _btnOk <- dialogAddButton dialog "Ok" ResponseOk
-      _btnCancel <- dialogAddButton dialog "Cancel" ResponseCancel
-      _btnText <- dialogAddButton dialog "TextInput" (ResponseUser 1) 
-      widgetShowAll dialog
-      res <- dialogRun dialog 
-      widgetDestroy dialog 
+#ifdef GTK3
+      upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)
+      vbox <- Gtk.vBoxNew False 0 
+      Gtk.containerAdd upper vbox
+#else 
+      vbox <- Gtk.dialogGetUpper dialog
+#endif
+      hbox <- Gtk.hBoxNew False 0 
+      Gtk.boxPackStart hbox msgLabel Gtk.PackNatural 0 
+      Gtk.boxPackStart vbox hbox Gtk.PackNatural 0
+      Gtk.boxPackStart vbox cvs Gtk.PackNatural 0
+      _btnOk <- Gtk.dialogAddButton dialog "Ok" Gtk.ResponseOk
+      _btnCancel <- Gtk.dialogAddButton dialog "Cancel" Gtk.ResponseCancel
+      _btnText <- Gtk.dialogAddButton dialog "TextInput" (Gtk.ResponseUser 1) 
+      Gtk.widgetShowAll dialog
+      res <- Gtk.dialogRun dialog 
+      Gtk.widgetDestroy dialog 
       case res of 
-        ResponseOk -> return (UsrEv (OkCancel True))
-        ResponseCancel -> return (UsrEv (OkCancel False))
-        ResponseUser 1 -> return (UsrEv ChangeDialog)
+        Gtk.ResponseOk -> return (UsrEv (OkCancel True))
+        Gtk.ResponseCancel -> return (UsrEv (OkCancel False))
+        Gtk.ResponseUser 1 -> return (UsrEv ChangeDialog)
         _ -> return (UsrEv (OkCancel False))
 
 minibufInit :: MainCoroutine (Either () [Stroke])
@@ -135,14 +149,18 @@
                minibufStart drawwdw (srcsfc,tgtsfc) empty 
              _ -> minibufInit)
 
-invalidateMinibuf :: DrawWindow -> Cairo.Surface -> IO ()
+invalidateMinibuf :: Gtk.DrawWindow -> Cairo.Surface -> IO ()
 invalidateMinibuf drawwdw tgtsfc = 
-  renderWithDrawable drawwdw $ do 
+#ifdef GTK3
+  Gtk.renderWithDrawWindow drawwdw $ do 
+#else 
+  Gtk.renderWithDrawable drawwdw $ do 
+#endif
     Cairo.setSourceSurface tgtsfc 0 0 
     Cairo.setOperator Cairo.OperatorSource 
     Cairo.paint
 
-minibufStart :: DrawWindow 
+minibufStart :: Gtk.DrawWindow 
              -> (Cairo.Surface,Cairo.Surface)  -- ^ (source, target)
              -> Seq Stroke 
              -> MainCoroutine (Either () [Stroke])
@@ -161,7 +179,7 @@
         minibufStart drawwdw (srcsfc,tgtsfc) nstrks
       _ -> minibufStart drawwdw (srcsfc,tgtsfc) strks
       
-onestroke :: DrawWindow
+onestroke :: Gtk.DrawWindow
           -> (Cairo.Surface,Cairo.Surface) -- ^ (source, target)
           -> Seq PointerCoord 
           -> MainCoroutine (Seq PointerCoord)
diff --git a/src/Hoodle/Coroutine/Mode.hs b/src/Hoodle/Coroutine/Mode.hs
--- a/src/Hoodle/Coroutine/Mode.hs
+++ b/src/Hoodle/Coroutine/Mode.hs
@@ -5,7 +5,7 @@
 -- Module      : Hoodle.Coroutine.Mode 
 -- Copyright   : (c) 2011-2014 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -15,10 +15,10 @@
 module Hoodle.Coroutine.Mode where
 
 import           Control.Applicative
-import           Control.Lens (view,set,over)
+import           Control.Lens (view,set,(.~))
 import           Control.Monad.State 
 import qualified Data.IntMap as M
-import           Graphics.UI.Gtk (adjustmentGetValue) 
+import qualified Graphics.UI.Gtk as Gtk (adjustmentGetValue)
 -- from hoodle-platform
 import           Data.Hoodle.BBox
 import           Data.Hoodle.Generic
@@ -45,107 +45,109 @@
 modeChange command = do 
     case command of 
       ToViewAppendMode -> updateXState select2edit >> invalidateAll 
-                          -- invalidateAllInBBox Nothing Efficient -- invalidateAll 
-      ToSelectMode     -> updateXState edit2select >> invalidateAllInBBox Nothing Efficient -- invalidateAll 
+      ToSelectMode     -> updateXState edit2select >> invalidateAllInBBox Nothing Efficient
       _ -> return ()
     reflectPenModeUI
     reflectPenColorUI
     reflectPenWidthUI
   where select2edit xst =  
-          either (noaction xst) (whenselect xst) . hoodleModeStateEither . view hoodleModeState $ xst
+          either (noaction xst) (whenselect xst) . hoodleModeStateEither 
+          . view (unitHoodles.currentUnit.hoodleModeState) $ xst
         edit2select xst = 
-          either (whenedit xst) (noaction xst) . hoodleModeStateEither . view hoodleModeState $ xst
+          either (whenedit xst) (noaction xst) . hoodleModeStateEither 
+          . view (unitHoodles.currentUnit.hoodleModeState) $ xst
         noaction :: HoodleState -> a -> MainCoroutine HoodleState
-        noaction xstate = const (return xstate)
+        noaction xst = const (return xst)
         whenselect :: HoodleState -> Hoodle SelectMode -> MainCoroutine HoodleState
-        whenselect xstate thdl = do 
+        whenselect xst thdl = do 
           let pages = view gselAll thdl
               mselect = view gselSelected thdl
-              cache = view renderCache xstate
+              cid = getCurrentCanvasId (view (unitHoodles.currentUnit) xst)
           npages <- maybe (return pages) 
                           (\(spgn,spage) -> do 
-                             npage <- (liftIO.updatePageBuf cache.hPage2RPage) spage  
+                             let npage = hPage2RPage spage
+                             callRenderer_ $ updatePageBuf cid npage
                              return $ M.adjust (const npage) spgn pages )
                           mselect
           let nthdl = set gselAll npages . set gselSelected Nothing $ thdl  
-          return . flip (set hoodleModeState) xstate 
-            . ViewAppendState . gSelect2GHoodle $ nthdl  
+          return $ (unitHoodles.currentUnit.hoodleModeState .~ ViewAppendState (gSelect2GHoodle nthdl)) xst
         whenedit :: HoodleState -> Hoodle EditMode -> MainCoroutine HoodleState   
-        whenedit xstate hdl = do 
-          return . flip (set hoodleModeState) xstate 
-                          . SelectState  
-                          . gHoodle2GSelect $ hdl 
+        whenedit xst hdl =
+          return $ (unitHoodles.currentUnit.hoodleModeState .~ SelectState  (gHoodle2GSelect hdl)) xst
 
+
 -- | 
 viewModeChange :: UserEvent -> MainCoroutine () 
 viewModeChange command = do 
     case command of 
-      ToSinglePage -> updateXState cont2single >> invalidateAll 
-      ToContSinglePage -> updateXState single2cont >> invalidateAll 
+      ToSinglePage -> updateUhdl cont2single >> invalidateAll 
+      ToContSinglePage -> updateUhdl single2cont >> invalidateAll 
       _ -> return ()
     adjustScrollbarWithGeometryCurrent     
-  where cont2single xst =  
-          unboxBiAct (noaction xst) (whencont xst) . view currentCanvasInfo $ xst
-        single2cont xst = 
-          unboxBiAct (whensing xst) (noaction xst) . view currentCanvasInfo $ xst
-        noaction :: HoodleState -> a -> MainCoroutine HoodleState  
-        noaction xstate = const (return xstate)
-        -------------------------------------
-        whencont xstate cinfo = do 
-          geometry <- liftIO $ getGeometry4CurrCvs xstate 
-          cdim <- liftIO $  return . canvasDim $ geometry 
-          page <- getCurrentPageCurr
-          let zmode = view (viewInfo.zoomMode) cinfo
-              canvas = view drawArea cinfo 
-              cpn = PageNum . view currentPageNum $ cinfo 
+  where cont2single :: UnitHoodle -> MainCoroutine UnitHoodle
+        cont2single uhdl = unboxBiAct (const (return uhdl)) (cont2SingPage uhdl) . view currentCanvasInfo $ uhdl
+        single2cont :: UnitHoodle -> MainCoroutine UnitHoodle
+        single2cont uhdl = unboxBiAct (sing2ContPage uhdl) (const (return uhdl)) . view currentCanvasInfo $ uhdl
 
-              pdim = PageDimension (view gdimension page)
-              ViewPortBBox bbox = view (viewInfo.pageArrangement.viewPortBBox) cinfo       
-              (x0,y0) = bbox_upperleft bbox 
-              (xpos,ypos) = maybe (0,0) (unPageCoord.snd) $ desktop2Page geometry (DeskCoord (x0,y0))  
-          let arr = makeSingleArrangement zmode pdim cdim (xpos,ypos) 
-          let nvinfo = ViewInfo (view zoomMode (view viewInfo cinfo)) arr 
-              ncinfo = CanvasInfo (view canvasId cinfo)
-                                  canvas
-                                  (view mDrawSurface cinfo)
-                                  (view scrolledWindow cinfo)
-                                  nvinfo 
-                                  (unPageNum cpn)
-                                  (view horizAdjustment cinfo)
-                                  (view vertAdjustment cinfo)
-                                  (view horizAdjConnId cinfo)
-                                  (view vertAdjConnId cinfo)
-                                  (view canvasWidgets cinfo)
-                                  (view notifiedItem cinfo)
-          return $ set currentCanvasInfo (CanvasSinglePage ncinfo) xstate 
-        -------------------------------------
-        whensing xstate cinfo = do 
-          cdim <- liftIO $  return . canvasDim =<< getGeometry4CurrCvs xstate 
-          let zmode = view (viewInfo.zoomMode) cinfo
-              canvas = view drawArea cinfo 
-              cpn = PageNum . view currentPageNum $ cinfo 
-              (hadj,vadj) = view adjustments cinfo 
-          (xpos,ypos) <- liftIO $ (,) <$> adjustmentGetValue hadj <*> adjustmentGetValue vadj
-          let arr = makeContinuousArrangement zmode cdim (getHoodle xstate) 
-                                                    (cpn, PageCoord (xpos,ypos))
-          geometry <- liftIO $ makeCanvasGeometry cpn arr canvas
-          let DeskCoord (nxpos,nypos) = page2Desktop geometry (cpn,PageCoord (xpos,ypos))
-          let vinfo = view viewInfo cinfo 
-              nvinfo = ViewInfo (view zoomMode vinfo) arr 
-              ncinfotemp = CanvasInfo (view canvasId cinfo)
-                                      (view drawArea cinfo)
-                                      (view mDrawSurface cinfo)
-                                      (view scrolledWindow cinfo)
-                                      nvinfo 
-                                      (view currentPageNum cinfo)
-                                      hadj 
-                                      vadj 
-                                      (view horizAdjConnId cinfo)
-                                      (view vertAdjConnId cinfo)
-                                      (view canvasWidgets cinfo) 
-                                      (view notifiedItem cinfo)
-              ncpn = maybe cpn fst $ desktop2Page geometry (DeskCoord (nxpos,nypos))
-              ncinfo = over currentPageNum (const (unPageNum ncpn)) ncinfotemp
-          return . over currentCanvasInfo (const (CanvasContPage ncinfo)) $ xstate
+cont2SingPage :: UnitHoodle -> CanvasInfo a -> MainCoroutine UnitHoodle
+cont2SingPage uhdl cinfo = do
+    geometry <- liftIO $ getGeometry4CurrCvs uhdl
+    cdim <- liftIO $  return . canvasDim $ geometry 
+    page <- getCurrentPageCurr
+    let zmode = view (viewInfo.zoomMode) cinfo
+        canvas = view drawArea cinfo 
+        cpn = PageNum . view currentPageNum $ cinfo 
+
+        pdim = PageDimension (view gdimension page)
+        ViewPortBBox bbox = view (viewInfo.pageArrangement.viewPortBBox) cinfo       
+        (x0,y0) = bbox_upperleft bbox 
+        (xpos,ypos) = maybe (0,0) (unPageCoord.snd) $ desktop2Page geometry (DeskCoord (x0,y0))  
+    let arr = makeSingleArrangement zmode pdim cdim (xpos,ypos) 
+    let nvinfo = ViewInfo (view zoomMode (view viewInfo cinfo)) arr 
+        ncinfo = CanvasInfo (view canvasId cinfo)
+                            canvas
+                            (view mDrawSurface cinfo)
+                            (view scrolledWindow cinfo)
+                            nvinfo 
+                            (unPageNum cpn)
+                            (view horizAdjustment cinfo)
+                            (view vertAdjustment cinfo)
+                            (view horizAdjConnId cinfo)
+                            (view vertAdjConnId cinfo)
+                            (view canvasWidgets cinfo)
+                            (view notifiedItem cinfo)
+    return $ (currentCanvasInfo .~ CanvasSinglePage ncinfo) uhdl
+
+
+sing2ContPage :: UnitHoodle -> CanvasInfo a -> MainCoroutine UnitHoodle
+sing2ContPage uhdl cinfo = do
+    cdim <- liftIO $  return . canvasDim =<< getGeometry4CurrCvs uhdl
+    let zmode = view (viewInfo.zoomMode) cinfo
+        canvas = view drawArea cinfo 
+        cpn = PageNum . view currentPageNum $ cinfo 
+        (hadj,vadj) = view adjustments cinfo 
+    (xpos,ypos) <- liftIO $ (,) <$> Gtk.adjustmentGetValue hadj <*> Gtk.adjustmentGetValue vadj
+    let arr = makeContinuousArrangement zmode cdim (getHoodle uhdl) 
+                                              (cpn, PageCoord (xpos,ypos))
+    geometry <- liftIO $ makeCanvasGeometry cpn arr canvas
+    let DeskCoord (nxpos,nypos) = page2Desktop geometry (cpn,PageCoord (xpos,ypos))
+    let vinfo = view viewInfo cinfo 
+        nvinfo = ViewInfo (view zoomMode vinfo) arr 
+        ncinfotemp = CanvasInfo (view canvasId cinfo)
+                                (view drawArea cinfo)
+                                (view mDrawSurface cinfo)
+                                (view scrolledWindow cinfo)
+                                nvinfo 
+                                (view currentPageNum cinfo)
+                                hadj 
+                                vadj 
+                                (view horizAdjConnId cinfo)
+                                (view vertAdjConnId cinfo)
+                                (view canvasWidgets cinfo) 
+                                (view notifiedItem cinfo)
+        ncpn = maybe cpn fst $ desktop2Page geometry (DeskCoord (nxpos,nypos))
+        ncinfo = (currentPageNum .~ unPageNum ncpn) ncinfotemp
+    return $ (currentCanvasInfo .~ CanvasContPage ncinfo) uhdl
+
 
 
diff --git a/src/Hoodle/Coroutine/Network.hs b/src/Hoodle/Coroutine/Network.hs
--- a/src/Hoodle/Coroutine/Network.hs
+++ b/src/Hoodle/Coroutine/Network.hs
@@ -7,7 +7,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.Network
--- Copyright   : (c) 2013 Ian-Woo Kim
+-- Copyright   : (c) 2013, 2014 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
@@ -20,86 +20,83 @@
 
 import           Control.Applicative
 import           Control.Concurrent hiding (yield)
-
 import           Control.Lens 
-
-import           Control.Monad.State (modify,get)
+import           Control.Monad
+import           Control.Monad.Loops 
+import           Control.Monad.State (get)
 import           Control.Monad.Trans
 import           Control.Monad.Trans.Maybe (MaybeT(..))
 import qualified Data.Binary as Bi 
 import qualified Data.ByteString.Char8 as B
 import qualified Data.ByteString.Lazy.Char8 as LB
-import qualified Data.Foldable as F (mapM_)
-
+-- import qualified Data.Foldable as F (mapM_)
+import           Data.IORef
 import           Data.Monoid ((<>),mconcat)
 import qualified Data.Text as T
 import qualified Data.Text.Encoding as TE
+import qualified Data.Traversable as Tr
 import           Data.Word
-import           Graphics.UI.Gtk hiding (get,set)
+import qualified Graphics.UI.Gtk as Gtk
 import           Network.Info
 import           Network.Simple.TCP
-
 -- 
-
-import           Control.Monad.Trans.Crtn.Queue (enqueue)
--- 
-
 import           Hoodle.Coroutine.Draw
 import           Hoodle.Script.Hook
 import           Hoodle.Type.Coroutine
 import           Hoodle.Type.Enum
 import           Hoodle.Type.Event
-import           Hoodle.Type.HoodleState (tempQueue,hookSet)
+import           Hoodle.Type.HoodleState (hookSet)
 -- 
 
 server :: (AllEvent -> IO ()) -> HostPreference -> T.Text -> IO ()
-server evhandler ip txt = do
-  listen ip  "4040" $ \(lsock, _) -> 
-    accept lsock $ \(sock,addr) -> do 
-      let bstr = TE.encodeUtf8 txt
-          bstr_size :: Word32 = (fromIntegral . B.length) bstr 
-          bstr_size_binary = (mconcat . LB.toChunks . Bi.encode) bstr_size
-      -- B.putStrLn () 
-      putStrLn $ "TCP connection established from " ++ show addr
-      send sock (bstr_size_binary <> TE.encodeUtf8 txt)
-      
-      mbstr <- runMaybeT $ do 
-        bstr' <- MaybeT (recv sock 4)
-        let getsize :: B.ByteString -> Word32 
-            getsize = Bi.decode . LB.fromChunks . return
-            size = (fromIntegral . getsize) bstr'
+server evhandler ip txtorig = do
+    ref <- newIORef txtorig
+    forever $ listen ip  "4040" $ \(lsock, _) -> 
+      accept lsock $ \(sock,addr) -> do
+        txt <- readIORef ref
+        let bstr = TE.encodeUtf8 txt
+            bstr_size :: Word32 = (fromIntegral . B.length) bstr 
+            bstr_size_binary = (mconcat . LB.toChunks . Bi.encode) bstr_size
+        putStrLn $ "TCP connection established from " ++ show addr
+        send sock (bstr_size_binary <> TE.encodeUtf8 txt)
+        unfoldM_ $ do
+          mbstr <- runMaybeT $ do 
+            bstr' <- MaybeT (recv sock 4)
+            let getsize :: B.ByteString -> Word32 
+                getsize = Bi.decode . LB.fromChunks . return
+                size = (fromIntegral . getsize) bstr'
 
-            go s bs = do 
-              liftIO $ putStrLn ("requested size = " ++ show s)
-              bstr1 <- MaybeT (recv sock s)
-              let s' = B.length bstr1 
-              liftIO $ putStrLn ("obtained size = " ++ show s')
-              if s <= s' 
-                then return (bs <> bstr1)
-                else go (s-s') (bs <> bstr1) 
-        go size B.empty 
-        
-      -- print mbstr 
-      F.mapM_ (evhandler . UsrEv . NetworkProcess . NetworkReceived . TE.decodeUtf8) mbstr
+                go s bs = do 
+                  liftIO $ putStrLn ("requested size = " ++ show s)
+                  bstr1 <- MaybeT (recv sock s)
+                  let s' = B.length bstr1 
+                  liftIO $ putStrLn ("obtained size = " ++ show s')
+                  if s <= s' 
+                    then return (bs <> bstr1)
+                    else go (s-s') (bs <> bstr1) 
+            go size B.empty 
+          Tr.forM mbstr $ \bstr' -> do 
+            let txt' = TE.decodeUtf8 bstr'
+            (evhandler . UsrEv . NetworkProcess . NetworkReceived) txt'
+            writeIORef ref txt'
+          return mbstr
+        putStrLn "FINISHED"
 
-networkTextInput :: T.Text -> MainCoroutine (Maybe T.Text)
-networkTextInput txt = do 
+
+networkTextInputBody :: T.Text -> MainCoroutine (String,ThreadId,MVar ()) -- ^ (ip address,thread id,lock)
+networkTextInputBody txt = do
     mipscr <- runMaybeT $ do hkset <- MaybeT (view hookSet <$> lift get)
                              (MaybeT . return)  (getIPaddress hkset) 
-    
     let ipfind = do 
           let ipv4num (IPv4 x) = x 
               ismacnull (MAC a b c d e f) = a == 0 && b == 0 && c == 0 
                                             && d == 0 && e == 0 && f == 0 
-          
           ifcs <- liftIO $ getNetworkInterfaces
           let ifcs2 = Prelude.filter (not . ismacnull . mac) 
                       . Prelude.filter (((/=) 0) . ipv4num . ipv4 ) $ ifcs
           return (if Prelude.null ifcs2 then "127.0.0.1" else (show . ipv4 . head) ifcs2) 
     ip <- maybe ipfind liftIO mipscr 
-
     doIOaction $ \evhandler -> do  
-      -- T.putStrLn txt
       done <- newEmptyMVar
       tid <- forkIO (server evhandler (Host ip) txt) 
       (return . UsrEv . NetworkProcess) (NetworkInitialized tid done)
@@ -110,23 +107,24 @@
             NetworkProcess (NetworkInitialized tid done) -> return (tid,done)
             _ -> go 
     (tid,done) <- go 
-    let ipdialog msg = mkIOaction $ 
-               \_evhandler -> do                  
-                 dialog <- messageDialogNew Nothing [DialogModal]
-                   MessageQuestion ButtonsOkCancel msg 
-                 forkIO $ do          
-                   readMVar done 
-                   dialogResponse dialog ResponseOk
-                  
-                 res <- dialogRun dialog 
-                 let b = case res of 
-                           ResponseOk -> True
-                           _ -> False
-                 widgetDestroy dialog 
-                 return (UsrEv (OkCancel b))
+    return (ip,tid,done)
 
-    
-    modify (tempQueue %~ enqueue (ipdialog ("networkedit " ++ ip ++ " 4040")))
+networkTextInput :: T.Text -> MainCoroutine (Maybe T.Text)
+networkTextInput txt = do 
+    (ip,tid,done) <- networkTextInputBody txt
+    let ipdialog msg = \_evhandler -> do                  
+          dialog <- Gtk.messageDialogNew Nothing [Gtk.DialogModal]
+            Gtk.MessageQuestion Gtk.ButtonsOkCancel msg 
+          forkIO $ do          
+            readMVar done 
+            Gtk.dialogResponse dialog Gtk.ResponseOk
+          res <- Gtk.dialogRun dialog 
+          let b = case res of 
+                    Gtk.ResponseOk -> True
+                    _ -> False
+          Gtk.widgetDestroy dialog 
+          return (UsrEv (OkCancel b))
+    doIOaction (ipdialog ("networkedit " ++ ip ++ " 4040"))
     --
     let actf t = do 
           r <- nextevent
@@ -136,7 +134,7 @@
             OkCancel True -> (return . Just) t
             OkCancel False -> return Nothing
             NetworkProcess (NetworkReceived txt') ->  do 
-              doIOaction $ \_ -> postGUISync (putMVar done ())
+              doIOaction $ \_ -> Gtk.postGUISync (putMVar done ())
                                  >> (return . UsrEv . NetworkProcess) NetworkCloseDialog
               actf txt' 
               
@@ -148,4 +146,5 @@
       (return . UsrEv . NetworkProcess) NetworkClosed
     --
     return ntxt
+
 
diff --git a/src/Hoodle/Coroutine/Page.hs b/src/Hoodle/Coroutine/Page.hs
--- a/src/Hoodle/Coroutine/Page.hs
+++ b/src/Hoodle/Coroutine/Page.hs
@@ -7,9 +7,9 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.Page 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -19,9 +19,8 @@
 module Hoodle.Coroutine.Page where
 
 import           Control.Applicative
-import           Control.Concurrent
 import           Control.Concurrent.STM
-import           Control.Lens (view,set,over, (.~), (^.) )
+import           Control.Lens (view,set,(.~), (^.))
 import           Control.Monad
 import           Control.Monad.State
 import           Control.Monad.Trans.Reader (ask)
@@ -29,17 +28,11 @@
 import           Data.Function (on)
 import qualified Data.IntMap as M
 import           Data.List (sortBy)
-import           Data.UUID.V4
-import qualified Graphics.Rendering.Cairo as Cairo
-import qualified Graphics.UI.Gtk as Gtk
-import qualified Graphics.UI.Gtk.Poppler.Page as PopplerPage
 -- from hoodle-platform
 import           Data.Hoodle.Generic
 import           Data.Hoodle.Select
 import           Data.Hoodle.Simple (Dimension(..))
 import           Data.Hoodle.Zipper
-import           Graphics.Hoodle.Render
--- import           Graphics.Hoodle.Render.Background
 import           Graphics.Hoodle.Render.Type
 -- from this package
 import           Hoodle.Accessor
@@ -50,7 +43,6 @@
 import           Hoodle.Type.Alias
 import           Hoodle.Type.Coroutine
 import           Hoodle.Type.Canvas
-import           Hoodle.Type.Event
 import           Hoodle.Type.PageArrangement
 import           Hoodle.Type.HoodleState
 import           Hoodle.Type.Enum
@@ -60,35 +52,33 @@
 
 -- | change page of current canvas using a modify function
 changePage :: (Int -> Int) -> MainCoroutine () 
-changePage modifyfn = updateXState changePageAction 
-                      >> adjustScrollbarWithGeometryCurrent
-                      >> invalidateAllInBBox Nothing Efficient  
-  where changePageAction xst = unboxBiAct (fsingle xst) (fcont xst) 
-                               . (^. currentCanvasInfo) $ xst
-        fsingle xstate cvsInfo = do 
-          let xojst = view hoodleModeState $ xstate  
+changePage modifyfn = (view backgroundStyle <$> get) >>= \bsty -> 
+                         updateUhdl (changePageAction bsty) >>
+                         adjustScrollbarWithGeometryCurrent >>
+                         invalidateAllInBBox Nothing Efficient  
+  where changePageAction bsty uhdl = unboxBiAct (fsingle bsty uhdl) (fcont bsty uhdl) 
+                               . (^. currentCanvasInfo) $ uhdl
+        fsingle bsty uhdl cvsInfo = do 
+          let xojst = view hoodleModeState $ uhdl
               npgnum = modifyfn (cvsInfo ^. currentPageNum)
               cid = view canvasId cvsInfo
-              bsty = view backgroundStyle xstate 
           (b,npgnum',_,xojst') <- changePageInHoodleModeState bsty npgnum xojst
-          xstate' <- liftIO $ updatePageAll xojst' xstate 
-          ncvsInfo <- liftIO $ setPage xstate' (PageNum npgnum') cid
-          let xstatefinal = (currentCanvasInfo .~ ncvsInfo) xstate'
-          when b (commit xstatefinal)
-          return xstatefinal 
+          uhdl' <- liftIO $ updatePageAll xojst' uhdl
+          ncvsInfo <- liftIO $ setPage uhdl' (PageNum npgnum') cid
+          let uhdlfinal = (currentCanvasInfo .~ ncvsInfo) uhdl'
+          when b $ updateUhdl (const (return uhdlfinal)) >> commit_
+          return uhdlfinal 
         
-        fcont xstate cvsInfo = do 
-          let xojst = view hoodleModeState xstate  
+        fcont bsty uhdl cvsInfo = do 
+          let xojst = view hoodleModeState uhdl
               npgnum = modifyfn (cvsInfo ^. currentPageNum)
               cid  = cvsInfo ^. canvasId
-              bsty = xstate  ^. backgroundStyle
-          (b,npgnum',_selectedpage,xojst')
-            <- changePageInHoodleModeState bsty npgnum xojst
-          xstate' <- liftIO $ updatePageAll xojst' xstate 
-          ncvsInfo <- liftIO $ setPage xstate' (PageNum npgnum') cid
-          xstatefinal <- return . over currentCanvasInfo (const ncvsInfo) $ xstate'
-          when b (commit xstatefinal)
-          return xstatefinal 
+          (b,npgnum',_,xojst') <- changePageInHoodleModeState bsty npgnum xojst
+          uhdl' <- liftIO $ updatePageAll xojst' uhdl
+          ncvsInfo <- liftIO $ setPage uhdl' (PageNum npgnum') cid
+          let uhdlfinal = (currentCanvasInfo .~ ncvsInfo) uhdl'
+          when b $ updateUhdl (const (return uhdlfinal)) >> commit_
+          return uhdlfinal 
 
 
 -- | 
@@ -97,7 +87,7 @@
                             -> HoodleModeState 
                             -> MainCoroutine (Bool,Int,Page EditMode,HoodleModeState)
 changePageInHoodleModeState bsty npgnum hdlmodst = do
-    let ehdl = hoodleModeStateEither hdlmodst 
+    let ehdl = hoodleModeStateEither hdlmodst
         pgs = either (view gpages) (view gselAll) ehdl
         totnumpages = M.size pgs
         lpage = maybeError' "changePage" (M.lookup (totnumpages-1) pgs)
@@ -107,9 +97,8 @@
           let cbkg = view gbackground lpage
           nbkg <- newBkg bsty cbkg  
           npage <- set gbackground nbkg <$> (newPageFromOld lpage)
-          geometry <- liftIO . getGeometry4CurrCvs =<< get
-          callRenderer $ updateBkgCache geometry (PageNum (totnumpages-1),npage) >> return GotNone
-          waitSomeEvent (\case RenderEv GotNone -> True ; _ -> False )
+          geometry <- liftIO . getGeometry4CurrCvs . view (unitHoodles.currentUnit) =<< get
+          callRenderer_ $ updatePageCache geometry (PageNum (totnumpages-1),npage)
           let npages = M.insert totnumpages npage pgs  
           return  (True,totnumpages,npage,
                      either (Left . set gpages npages) (Right. set gselAll npages) ehdl ) 
@@ -127,18 +116,19 @@
                                   -> Maybe (PageNum,PageCoordinate) 
                                   -> MainCoroutine ()
 canvasZoomUpdateGenRenderCvsId renderfunc cid mzmode mcoord = do 
-    updateXState zoomUpdateAction 
+    updateUhdl zoomUpdateAction 
     adjustScrollbarWithGeometryCvsId cid
     xst <- get
-    let hdl = getHoodle xst
-    geometry <- liftIO (getGeometry4CurrCvs xst)
-    let cpn = view (unboxLens currentPageNum) .  getCanvasInfo cid $ xst
+    let uhdl = view (unitHoodles.currentUnit) xst
+        hdl = getHoodle uhdl
+    geometry <- liftIO (getGeometry4CurrCvs uhdl)
+    let cpn = view (unboxLens currentPageNum) .  getCanvasInfo cid $ uhdl
     let plst = sortBy ( compare `on` (\(n,_) -> abs (n - cpn)) ) . zip [0..] . F.toList $ hdl ^. gpages
-    forM_ plst $ \(pn,pg) -> callRenderer_ (updateBkgCache geometry (PageNum pn,pg))
+    forM_ plst $ \(pn,pg) -> callRenderer_ (updatePageCache geometry (PageNum pn,pg))
     renderfunc
-  where zoomUpdateAction xst =  
-          unboxBiAct (fsingle xst) (fcont xst) . getCanvasInfo cid $ xst 
-        fsingle xstate cinfo = do   
+  where zoomUpdateAction uhdl =  
+          unboxBiAct (fsingle uhdl) (fcont uhdl) . getCanvasInfo cid $ uhdl 
+        fsingle uhdl cinfo = do   
           geometry <- liftIO $ getCvsGeomFrmCvsInfo cinfo 
           page <- getCurrentPageCvsId cid
           let zmode = maybe (cinfo ^. viewInfo.zoomMode) id mzmode  
@@ -150,13 +140,13 @@
               ncinfobox = CanvasSinglePage
                           . (viewInfo.pageArrangement .~ narr)
                           . (viewInfo.zoomMode .~  zmode) $ cinfo
-          return . modifyCanvasInfo cid (const ncinfobox) $ xstate
-        fcont xstate cinfo = do   
+          return . modifyCanvasInfo cid (const ncinfobox) $ uhdl
+        fcont uhdl cinfo = do   
           geometry <- liftIO $ getCvsGeomFrmCvsInfo cinfo 
           let zmode = maybe (view (viewInfo.zoomMode) cinfo) id mzmode 
               cpn = PageNum $ view currentPageNum cinfo 
               cdim = canvasDim geometry 
-              hdl = getHoodle xstate 
+              hdl = getHoodle uhdl
               origcoord = case mcoord of
                             Just coord -> coord 
                             Nothing -> either (const (cpn,PageCoord (0,0))) id 
@@ -165,7 +155,7 @@
               ncinfobox = CanvasContPage
                           . (viewInfo.pageArrangement .~  narr)
                           . (viewInfo.zoomMode .~ zmode) $ cinfo
-          return . modifyCanvasInfo cid (const ncinfobox) $ xstate
+          return . modifyCanvasInfo cid (const ncinfobox) $ uhdl
 
 -- | 
 canvasZoomUpdateCvsId :: CanvasId 
@@ -177,7 +167,7 @@
 -- | 
 canvasZoomUpdateBufAll :: MainCoroutine () 
 canvasZoomUpdateBufAll = do 
-    klst <- liftM (M.keys . getCanvasInfoMap) get
+    klst <- M.keys . view cvsInfoMap . view (unitHoodles.currentUnit) <$> get
     mapM_ updatefunc klst 
   where 
     updatefunc cid 
@@ -187,14 +177,14 @@
 -- |
 canvasZoomUpdateAll :: MainCoroutine () 
 canvasZoomUpdateAll = do 
-  klst <- liftM (M.keys . getCanvasInfoMap) get
+  klst <- M.keys . view cvsInfoMap . view (unitHoodles.currentUnit) <$> get
   mapM_ (flip canvasZoomUpdateCvsId Nothing) klst 
 
 
 -- | 
 canvasZoomUpdate :: Maybe ZoomMode -> MainCoroutine () 
 canvasZoomUpdate mzmode = do  
-  cid <- (liftM (getCurrentCanvasId) get)
+  cid <- getCurrentCanvasId . view (unitHoodles.currentUnit) <$> get
   canvasZoomUpdateCvsId cid mzmode
 
 -- |
@@ -204,7 +194,7 @@
 -- | 
 pageZoomChangeRel :: ZoomModeRel -> MainCoroutine () 
 pageZoomChangeRel rzmode = do 
-    forBoth' unboxBiAct fsingle . view currentCanvasInfo =<< get 
+    forBoth' unboxBiAct fsingle . view currentCanvasInfo . view (unitHoodles.currentUnit) =<< get 
   where 
     fsingle :: CanvasInfo a -> MainCoroutine ()
     fsingle cinfo = do 
@@ -216,42 +206,45 @@
       pageZoomChange (Zoom nratio)
 
 -- |
-newPage :: AddDirection -> MainCoroutine () 
-newPage dir = updateXState npgBfrAct 
-              >> commit_ 
-              >> canvasZoomUpdateAll 
-              >> invalidateAll
+newPage :: Maybe Dimension -> AddDirection -> MainCoroutine () 
+newPage mdim dir = (view backgroundStyle <$> get) >>= \bsty ->
+                     updateUhdl (npgBfrAct bsty) >>
+                     commit_                     >>
+                     canvasZoomUpdateAll         >>
+                     invalidateAll
   where 
-    npgBfrAct xst = forBoth' unboxBiAct (fsimple xst) . view currentCanvasInfo $ xst
-    fsimple :: HoodleState -> CanvasInfo a -> MainCoroutine HoodleState
-    fsimple xstate cinfo = do 
-      case view hoodleModeState xstate of 
+    npgBfrAct bsty uhdl = forBoth' unboxBiAct (fsimple bsty uhdl) . view currentCanvasInfo $ uhdl
+    fsimple :: BackgroundStyle -> UnitHoodle -> CanvasInfo a -> MainCoroutine UnitHoodle
+    fsimple bsty uhdl cinfo = do 
+      case view hoodleModeState uhdl of 
         ViewAppendState hdl -> do 
-          let bsty = view backgroundStyle xstate 
-          hdl' <- addNewPageInHoodle bsty dir hdl (view currentPageNum cinfo)
-          return =<< liftIO . updatePageAll (ViewAppendState hdl')
-                     . set hoodleModeState  (ViewAppendState hdl') $ xstate 
+          hdl' <- addNewPageInHoodle mdim bsty dir hdl (view currentPageNum cinfo)
+          liftIO . updatePageAll (ViewAppendState hdl')
+                 . set hoodleModeState  (ViewAppendState hdl') $ uhdl
         SelectState _ -> do 
-          liftIO $ putStrLn " not implemented yet"
-          return xstate
+          msgShout  "newPage: not implemented yet"
+          return uhdl
       
 -- | delete current page of current canvas
 deleteCurrentPage :: MainCoroutine ()           
-deleteCurrentPage = do 
-    updateXState delpgact >> commit_ >> canvasZoomUpdateAll >> invalidateAll
+deleteCurrentPage = 
+    updateUhdl delpgact >> 
+    commit_               >> 
+    canvasZoomUpdateAll   >> 
+    invalidateAll
   where 
-    delpgact xst = forBoth' unboxBiAct (fsimple xst) . view currentCanvasInfo $ xst
-    fsimple :: HoodleState -> CanvasInfo a -> MainCoroutine HoodleState
-    fsimple xstate cinfo = do 
-      case view hoodleModeState xstate of 
+    delpgact uhdl = forBoth' unboxBiAct (fsimple uhdl) . view currentCanvasInfo $ uhdl
+    fsimple :: UnitHoodle -> CanvasInfo a -> MainCoroutine UnitHoodle
+    fsimple uhdl cinfo = do 
+      case view hoodleModeState uhdl of 
         ViewAppendState hdl -> do 
           hdl' <- liftIO $ deletePageInHoodle hdl 
                              (PageNum (view currentPageNum cinfo))
-          return =<< liftIO . updatePageAll (ViewAppendState hdl')
-                     . set hoodleModeState  (ViewAppendState hdl') $ xstate 
+          liftIO . updatePageAll (ViewAppendState hdl')
+                 . set hoodleModeState  (ViewAppendState hdl') $ uhdl
         SelectState _ -> do 
-          liftIO $ putStrLn " not implemented yet"
-          return xstate
+          msgShout "deleteCurrentPage: not implemented yet"
+          return uhdl
       
 -- | delete designated page
 deletePageInHoodle :: Hoodle EditMode -> PageNum -> IO (Hoodle EditMode)
@@ -264,19 +257,20 @@
 
 
 -- | 
-addNewPageInHoodle :: BackgroundStyle
+addNewPageInHoodle :: Maybe Dimension
+                   -> BackgroundStyle
                    -> AddDirection  
                    -> Hoodle EditMode
                    -> Int 
                    -> MainCoroutine (Hoodle EditMode)
-addNewPageInHoodle bsty dir hdl cpn = do
+addNewPageInHoodle mdim bsty dir hdl cpn = do
     let pagelst = M.elems . view gpages $ hdl
         (pagesbefore,cpage:pagesafter) = splitAt cpn pagelst
         cbkg = view gbackground cpage
     nbkg <- newBkg bsty cbkg
-    npage <- set gbackground nbkg <$> newPageFromOld cpage
-    geometry <- liftIO . getGeometry4CurrCvs =<< get
-    callRenderer_ (updateBkgCache geometry (PageNum cpn,npage))
+    npage <- maybe id (set gdimension) mdim . set gbackground nbkg <$> newPageFromOld cpage
+    geometry <- liftIO . getGeometry4CurrCvs . view (unitHoodles.currentUnit) =<< get
+    callRenderer_ (updatePageCache geometry (PageNum cpn,npage))
     let npagelst = case dir of 
                      PageBefore -> pagesbefore ++ (npage : cpage : pagesafter)
                      PageAfter -> pagesbefore ++ (cpage : npage : pagesafter)
@@ -286,40 +280,85 @@
 
 newBkg :: BackgroundStyle -> RBackground -> MainCoroutine RBackground 
 newBkg bsty bkg = do
+    xst <- get
+    let npmode = xst ^. settings.newPageMode
+        rhdl = (getHoodle . view (unitHoodles.currentUnit)) xst
+        mtotN = pdfNumPages <$> (rhdl ^. gembeddedpdf)  
     let bstystr = convertBackgroundStyleToByteString bsty 
-    case bkg of 
-      RBkgSmpl c _ _ -> RBkgSmpl c bstystr <$> liftIO nextRandom
-      _              -> RBkgSmpl "white" bstystr <$> liftIO nextRandom
+        defbkg = RBkgSmpl "white" bstystr <$> issueSurfaceID
+    case npmode of 
+      NPPlain -> defbkg
+      NPLast -> case bkg of 
+        RBkgSmpl c _ _ -> RBkgSmpl c bstystr <$> issueSurfaceID
+        RBkgPDF d f n pg _ -> RBkgPDF d f n pg <$> issueSurfaceID
+        RBkgEmbedPDF n pg _ -> RBkgEmbedPDF n pg <$> issueSurfaceID
+      NPCycle -> 
+        case mtotN of
+          Nothing -> defbkg
+          Just totN -> do
+            let n1 = maybe 1 id (xst ^. nextPdfBkgPageNum)
+            case findPDFBkg rhdl n1 of
+                 Nothing -> defbkg
+                 Just bkg' -> issueSurfaceID >>= \i -> do
+                                let n' = if n1 >= totN then 1 else (n1+1)
+                                put ((nextPdfBkgPageNum .~ Just n') xst)
+                                return bkg' { rbkg_surfaceid = i }
 
 
+findPDFBkg :: RHoodle -> Int -> Maybe RBackground
+findPDFBkg rhdl n1 = 
+    let bkgs = M.elems (rhdl ^. gpages)
+        pagematch n (RBkgPDF _ _ n' _ _) = n == n'
+        pagematch n (RBkgEmbedPDF n' _ _) = n == n'
+        pagematch _ _ = False
+        matched = (filter (pagematch n1) . map (^. gbackground)) bkgs
+    in case matched of 
+         [] -> Nothing
+         b:_ -> Just b
+
+
 -- | 
 newPageFromOld :: Page EditMode -> MainCoroutine (Page EditMode)
-newPageFromOld =
-    return . ( glayers .~ (fromNonEmptyList (emptyRLayer,[])))
+newPageFromOld pg = do
+    sfcid <- issueSurfaceID
+    return . ( glayers .~ (fromNonEmptyList (emptyRLayer sfcid,[]))) $ pg
 
 
-updateBkgCache :: CanvasGeometry -> (PageNum, Page EditMode) -> Renderer ()
-updateBkgCache geometry (pnum,page) = do
-  (handler,qvar) <- ask
-  let dim@(Dim w h) = page ^. gdimension 
+updatePageCache :: CanvasGeometry -> (PageNum, Page EditMode) -> Renderer ()
+updatePageCache geometry (pnum,page) = do
+  let Dim w h = page ^. gdimension 
       CvsCoord (x0,y0) = 
         (desktop2Canvas geometry . page2Desktop geometry) (pnum,PageCoord (0,0))
       CvsCoord (x1,y1) = 
         (desktop2Canvas geometry . page2Desktop geometry) (pnum,PageCoord (w,h))
-      s = (x1-x0) / w 
-      rbkg = page ^. gbackground
-      bkg = rbkg2Bkg rbkg
-      uuid = rbkg_uuid rbkg 
+  updateBkgCache (Dim w h) (Dim (x1-x0) (y1-y0)) (page ^. gbackground) 
+  mapM_ (updateLayerCache (Dim w h) (Dim (x1-x0) (y1-y0))) (F.toList (page ^. glayers))
+
+
+updateBkgCache :: Dimension -> Dimension -> RBackground -> Renderer ()
+updateBkgCache dimo dimv rbkg =  do
+  RendererState _handler qpdf qgen _ <- ask
+  let sfcid = rbkg_surfaceid rbkg 
   case rbkg of 
-    RBkgSmpl {..} -> do liftIO . forkIO $ do
-                          sfc <- Cairo.createImageSurface Cairo.FormatARGB32 (floor (x1-x0)) (floor (y1-y0))
-                          Cairo.renderWith sfc $ Cairo.scale s s >> renderBkg (bkg,dim)
-                          handler (uuid, (s,sfc))
-                        return ()
-  
+    RBkgSmpl {..} -> do
+      cmdid <- issueGenCommandID
+      (liftIO . atomically) (sendGenCommand qgen cmdid (BkgSmplScaled sfcid rbkg_color rbkg_style dimo dimv))
+      return ()
     _             -> F.forM_ (rbkg_popplerpage rbkg) $ \pg -> do
-                       (liftIO . atomically) (sendPDFCommand uuid qvar (RenderPageScaled pg (Dim w h) (Dim (x1-x0) (y1-y0))))
-                       return ()
+      cmdid <- issuePDFCommandID
+      (liftIO . atomically) (sendPDFCommand qpdf cmdid (RenderPageScaled sfcid pg dimo dimv))
+      return ()
+
+
+updateLayerCache :: Dimension -> Dimension -> RLayer -> Renderer ()
+updateLayerCache dimo dimv lyr =  do
+  RendererState _ _ qgen _ <- ask
+  case view gbuffer lyr of
+    LyBuf sfcid -> do
+      cmdid <- issueGenCommandID
+      (liftIO . atomically) (sendGenCommand qgen cmdid (LayerScaled sfcid (view gitems lyr) dimo dimv))
+      return ()
+
 
 
 
diff --git a/src/Hoodle/Coroutine/Pen.hs b/src/Hoodle/Coroutine/Pen.hs
--- a/src/Hoodle/Coroutine/Pen.hs
+++ b/src/Hoodle/Coroutine/Pen.hs
@@ -1,11 +1,15 @@
-{-# LANGUAGE Rank2Types, GADTs, ScopedTypeVariables, TupleSections #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TupleSections #-}
 
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.Pen 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -16,27 +20,31 @@
 
 -- from other packages
 import           Control.Applicative ((<$>),(<*>))
-import           Control.Lens (view,set,at)
+import           Control.Lens (at,over,set,view)
 import           Control.Monad hiding (mapM_,forM_)
 import           Control.Monad.State hiding (mapM_,forM_)
 -- import Control.Monad.Trans
 import           Data.Functor.Identity (Identity(..))
-import           Data.Foldable (forM_)
+import           Data.Foldable (toList)
 import           Data.Sequence hiding (filter)
+import qualified Data.IntMap as IM
 import           Data.Maybe 
+import           Data.Ratio
 import           Data.Time.Clock 
 import qualified Graphics.Rendering.Cairo as Cairo
 -- from hoodle-platform
 import           Data.Hoodle.BBox
-import           Data.Hoodle.Generic (gpages)
+import           Data.Hoodle.Generic (gitems,gpages)
 import           Data.Hoodle.Simple (Dimension(..))
-import           Graphics.Hoodle.Render (renderStrk)
+import           Graphics.Hoodle.Render (renderStrk,updateLayerBuf)
+import           Graphics.Hoodle.Render.Type
 -- from this package
--- import           Hoodle.Accessor
+import           Hoodle.Accessor
 import           Hoodle.Coroutine.Commit
 import           Hoodle.Coroutine.Draw
 import           Hoodle.Device 
 import           Hoodle.GUI.Reflect
+import           Hoodle.ModelAction.Layer
 import           Hoodle.ModelAction.Page
 import           Hoodle.ModelAction.Pen
 import           Hoodle.Type.Canvas
@@ -52,17 +60,40 @@
 --
 import Prelude hiding (mapM_)
 
+
+-- | 
+addPDraw :: CanvasId
+         -> PenInfo 
+         -> RHoodle
+         -> PageNum 
+         -> Seq (Double,Double,Double) 
+         -> MainCoroutine (RHoodle,BBox) -- ^ new hoodle and bbox in page coordinate
+addPDraw cid pinfo hdl (PageNum pgnum) pdraw = do 
+    let currpage = getPageFromGHoodleMap pgnum hdl
+        currlayer = getCurrentLayer currpage
+        newstroke = createNewStroke pinfo pdraw         
+        newstrokebbox = runIdentity (makeBBoxed newstroke)
+        bbox = getBBox newstrokebbox
+        newlayerbbox = over gitems (++[RItemStroke newstrokebbox]) currlayer
+    callRenderer_ $ updateLayerBuf cid newlayerbbox
+    let newpagebbox = adjustCurrentLayer newlayerbbox currpage 
+        newhdlbbox = set gpages (IM.adjust (const newpagebbox) pgnum (view gpages hdl) ) hdl 
+    return (newhdlbbox,bbox)
+
+
 -- |
 createTempRender :: CanvasGeometry -> a -> MainCoroutine (TempRender a) 
 createTempRender geometry x = do 
     xst <- get
-    let cinfobox = view currentCanvasInfo xst 
+    cache <- renderCache
+    let uhdl = view (unitHoodles.currentUnit) xst
+        cinfobox = view currentCanvasInfo uhdl
         mcvssfc = view (unboxLens mDrawSurface) cinfobox 
-        cache = view renderCache xst
-    let hdl = getHoodle xst
-    let Dim cw ch = unCanvasDimension . canvasDim $ geometry
+        cid = getCurrentCanvasId uhdl
+        hdl = getHoodle uhdl
+        Dim cw ch = unCanvasDimension . canvasDim $ geometry
     srcsfc <- liftIO $  
-      maybe (fst <$> canvasImageSurface cache Nothing geometry hdl)
+      maybe (fst <$> canvasImageSurface cache cid Nothing geometry hdl)
             (\cvssfc -> do 
               sfc <- Cairo.createImageSurface 
                        Cairo.FormatARGB32 (floor cw) (floor ch) 
@@ -83,72 +114,76 @@
 penPageSwitch :: PageNum -> MainCoroutine CanvasInfoBox 
 penPageSwitch pgn = do 
     xstate <- get
-    let cibox = view currentCanvasInfo xstate     
+    let uhdl = view (unitHoodles.currentUnit) xstate
+        cibox = view currentCanvasInfo uhdl    
         ncibox = (runIdentity . forBoth unboxBiXform (return . set currentPageNum (unPageNum pgn))) cibox 
-    put (set currentCanvasInfo ncibox xstate) 
+        uhdl' = set currentCanvasInfo ncibox uhdl
+    pureUpdateUhdl (const uhdl')
     invalidateAllInBBox Nothing Efficient
     return ncibox 
-        
-
+       
 -- | Common Pen Work starting point 
-commonPenStart :: (forall a. CanvasInfo a -> PageNum -> CanvasGeometry  
-                    -> (Double,Double) -> MainCoroutine () )
+commonPenStart :: forall b. 
+                  (forall a . CanvasInfo a -> PageNum -> CanvasGeometry  
+                    -> (Double,Double) -> UTCTime -> MainCoroutine b)
                -> CanvasId 
                -> PointerCoord 
-               -> MainCoroutine ()
+               -> MainCoroutine (Maybe b)
 commonPenStart action cid pcoord = do
     oxstate <- get 
-    let currcid = getCurrentCanvasId oxstate
+    let currcid = (getCurrentCanvasId . view (unitHoodles.currentUnit)) oxstate
+    ctime <- liftIO $ getCurrentTime
     when (cid /= currcid) (changeCurrentCanvasId cid >> invalidateAll)
     nxstate <- get
-    forBoth' unboxBiAct f . getCanvasInfo cid $ nxstate
-  where f :: forall b. CanvasInfo b -> MainCoroutine ()
-        f cvsInfo = do 
+    forBoth' unboxBiAct (f ctime) . getCanvasInfo cid . view (unitHoodles.currentUnit) $ nxstate
+  where f :: forall c. UTCTime -> CanvasInfo c -> MainCoroutine (Maybe b)
+        f ctime cvsInfo = do 
           let cpn = PageNum . view currentPageNum $ cvsInfo
               arr = view (viewInfo.pageArrangement) cvsInfo 
               canvas = view drawArea cvsInfo
           geometry <- liftIO $ makeCanvasGeometry cpn arr canvas
           let pagecoord = desktop2Page geometry . device2Desktop geometry $ pcoord 
-          maybeFlip pagecoord (return ()) 
+          maybeFlip pagecoord (return Nothing) 
             $ \(pgn,PageCoord (x,y)) -> do 
                  nCvsInfo <- if (cpn /= pgn) 
                                then do penPageSwitch pgn
                                     -- temporary dirty fix 
                                        return (set currentPageNum (unPageNum pgn) cvsInfo )
                                else return cvsInfo                   
-                 action nCvsInfo pgn geometry (x,y) 
+                 Just <$> action nCvsInfo pgn geometry (x,y) ctime 
       
 -- | enter pen drawing mode
 penStart :: CanvasId 
          -> PointerCoord 
-         -> MainCoroutine () 
+         -> MainCoroutine (Maybe (Maybe (Maybe ())))
 penStart cid pcoord = commonPenStart penAction cid pcoord
-  where penAction :: forall b. CanvasInfo b -> PageNum -> CanvasGeometry -> (Double,Double) -> MainCoroutine ()
-        penAction _cinfo pnum geometry (x,y) = do 
+  where penAction :: forall b. CanvasInfo b -> PageNum -> CanvasGeometry 
+                  -> (Double,Double) -> UTCTime 
+                  -> MainCoroutine (Maybe (Maybe ()))
+        penAction _cinfo pnum geometry (x,y) ctime = do 
           xstate <- get
+          let uhdl = view (unitHoodles.currentUnit) xstate
           let PointerCoord _ _ _ z = pcoord 
-          let currhdl = getHoodle  xstate 
+          let currhdl = getHoodle  uhdl
               pinfo = view penInfo xstate
               mpage = view (gpages . at (unPageNum pnum)) currhdl 
-              cache = view renderCache xstate
-          forM_ mpage $ \_page -> do 
+          maybeFlip mpage (return Nothing)  $ \_page -> do 
             trdr <- createTempRender geometry (empty |> (x,y,z)) 
-            pdraw <-penProcess cid pnum geometry trdr ((x,y),z) 
+            mpdraw <-penProcess cid pnum geometry trdr ((x,y),z) ctime
             Cairo.surfaceFinish (tempSurfaceSrc trdr)
-            Cairo.surfaceFinish (tempSurfaceTgt trdr)            
-            --
-            case viewl pdraw of 
-              EmptyL -> return ()
-              (x1,_y1,_z1) :< _rest -> do 
-                if x1 <= 1e-3      -- this is ad hoc but.. 
-                  then invalidateAll
-                  else do  
-                    (newhdl,bbox) <- liftIO $ addPDraw cache pinfo currhdl pnum pdraw
-                    commit . set hoodleModeState (ViewAppendState newhdl) 
-                      =<< (liftIO (updatePageAll (ViewAppendState newhdl) xstate))
-                    let f = unDeskCoord . page2Desktop geometry . (pnum,) . PageCoord
-                        nbbox = xformBBox f bbox 
-                    invalidateAllInBBox (Just nbbox) BkgEfficient 
+            Cairo.surfaceFinish (tempSurfaceTgt trdr)
+            maybeFlip mpdraw (return (Just Nothing)) $ \pdraw -> 
+              case viewl pdraw of 
+                EmptyL -> return (Just (Just ()))
+                (x1,_y1,_z1) :< _rest -> do 
+                  if x1 <= 1e-3      -- this is ad hoc but.. 
+                    then invalidateAll
+                    else do  
+                      (newhdl,_bbox) <- addPDraw cid pinfo currhdl pnum pdraw
+                      uhdl' <- liftIO (updatePageAll (ViewAppendState newhdl) uhdl)
+                      commit (set (unitHoodles.currentUnit) uhdl' xstate)
+                      return ()
+                  return (Just (Just ()))
           
 -- | main pen coordinate adding process
 -- | now being changed
@@ -157,19 +192,31 @@
            -> CanvasGeometry
            -> TempRender (Seq (Double,Double,Double))
            -> ((Double,Double),Double) 
-           -> MainCoroutine (Seq (Double,Double,Double))
-penProcess cid pnum geometry trdr ((x0,y0),z0) = do 
+           -> UTCTime
+           -> MainCoroutine (Maybe (Seq (Double,Double,Double)))
+penProcess cid pnum geometry trdr ((x0,y0),z0) ctime = do 
     r <- nextevent
-    xst <- get 
-    forBoth' unboxBiAct (fsingle r xst) . getCanvasInfo cid $ xst
+    ntime <- liftIO getCurrentTime
+    let ispressandhold = 
+          abs (toRational (diffUTCTime ctime ntime)) > 1 % 2
+        lst = (toList . tempInfo) trdr
+        deltax = let xlst = map (\(x,_,_)->x) lst
+                 in abs (maximum xlst - minimum xlst)
+        deltay = let ylst = map (\(_,y,_)->y) lst
+                 in abs (maximum ylst - minimum ylst)
+    -- temporarily fix the range
+    if (deltax < 20 && deltay < 20 && ispressandhold && Prelude.length lst < 20) 
+      then return Nothing 
+      else do xst <- get 
+              forBoth' unboxBiAct (fsingle r xst) . (getCanvasInfo cid . view (unitHoodles.currentUnit)) $ xst
   where 
     pdraw = tempInfo trdr 
     fsingle :: forall b.  
                UserEvent -> HoodleState -> CanvasInfo b 
-               -> MainCoroutine (Seq (Double,Double,Double))
+               -> MainCoroutine (Maybe (Seq (Double,Double,Double)))
     fsingle r xstate cvsInfo = 
       penMoveAndUpOnly r pnum geometry 
-        (penProcess cid pnum geometry trdr ((x0,y0),z0))
+        (penProcess cid pnum geometry trdr ((x0,y0),z0) ctime)
         (\(pcoord,(x,y)) -> do 
            let PointerCoord _ _ _ z = pcoord 
            let pinfo  = view penInfo xstate
@@ -183,8 +230,8 @@
            liftIO $ doubleBufferFlush tgtsfc cvsInfo
            ---                                
            let ntrdr = trdr { tempInfo = pdraw |> (x,y,z) }
-           penProcess cid pnum geometry ntrdr ((x,y),z) )
-        (\_ -> return pdraw )
+           penProcess cid pnum geometry ntrdr ((x,y),z) ctime)
+        (\_ -> return (Just pdraw))
 
 -- | 
 skipIfNotInSamePage :: Monad m => 
diff --git a/src/Hoodle/Coroutine/Scroll.hs b/src/Hoodle/Coroutine/Scroll.hs
--- a/src/Hoodle/Coroutine/Scroll.hs
+++ b/src/Hoodle/Coroutine/Scroll.hs
@@ -1,11 +1,14 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
+
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.Scroll 
 -- Copyright   : (c) 2011-2014 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -18,6 +21,7 @@
 import           Control.Monad
 import           Control.Monad.State 
 import           Control.Monad.Trans.Either
+-- import qualified Graphics.UI.Gtk as Gtk
 -- from hoodle-platform
 import           Control.Monad.Trans.Crtn
 import           Data.Functor.Identity (Identity(..))
@@ -36,15 +40,30 @@
 import           Hoodle.View.Coordinate
 --
 
+-- |
+updateCanvasInfo :: (forall a. CanvasInfo a -> CanvasInfo a) -> CanvasId -> MainCoroutine ()
+updateCanvasInfo f cid = pureUpdateUhdl $ \uhdl -> 
+                           let cinfobox = getCanvasInfo cid uhdl
+                               ncinfobox = (runIdentity . forBoth unboxBiXform (return . f)) cinfobox
+                           in setCanvasInfo (cid,ncinfobox) uhdl
+
+-- |
+updateCanvasInfo2 :: (CanvasInfo SinglePage -> CanvasInfo SinglePage) 
+                  -> (CanvasInfo ContinuousPage -> CanvasInfo ContinuousPage)
+                  -> CanvasId
+                  -> MainCoroutine ()
+updateCanvasInfo2 fs fc cid = 
+    pureUpdateUhdl $ \uhdl ->
+      let cinfobox = getCanvasInfo cid uhdl
+          ncinfobox = (runIdentity . unboxBiXform (return . fs) (return . fc)) cinfobox
+      in setCanvasInfo (cid,ncinfobox) uhdl
+
 -- | 
 moveViewPortBy :: MainCoroutine ()->CanvasId-> ((Double,Double)->(Double,Double))
                   -> MainCoroutine () 
 moveViewPortBy rndr cid f = 
-    updateXState (return . act) >> adjustScrollbarWithGeometryCvsId cid >> rndr 
+    updateCanvasInfo moveact cid >> adjustScrollbarWithGeometryCvsId cid >> rndr 
   where     
-    act xst = let cinfobox = getCanvasInfo cid xst 
-                  ncinfobox = (runIdentity . forBoth unboxBiXform (return . moveact)) cinfobox       
-              in setCanvasInfo (cid,ncinfobox) xst
     moveact :: CanvasInfo a -> CanvasInfo a 
     moveact cinfo = 
       let BBox (x0,y0) _ = 
@@ -60,25 +79,19 @@
 adjustScrollbarWithGeometryCvsId :: CanvasId -> MainCoroutine ()
 adjustScrollbarWithGeometryCvsId cid = do
   xstate <- get
-  let cinfobox = getCanvasInfo cid xstate
-  geometry <- liftIO (getCanvasGeometryCvsId cid xstate)
+  let uhdl = view (unitHoodles.currentUnit) xstate
+      cinfobox = getCanvasInfo cid uhdl
+  geometry <- liftIO (getCanvasGeometryCvsId cid uhdl)
   let (hadj,vadj) = view (unboxLens adjustments) cinfobox 
       connidh = view (unboxLens horizAdjConnId) cinfobox 
       connidv = view (unboxLens vertAdjConnId) cinfobox
-  liftIO $ A.adjustScrollbarWithGeometry geometry ((hadj,connidh),(vadj,connidv))  
+  doIOaction_ $ A.adjustScrollbarWithGeometry geometry ((hadj,connidh),(vadj,connidv))  
 
 
 -- | 
 adjustScrollbarWithGeometryCurrent :: MainCoroutine ()
-adjustScrollbarWithGeometryCurrent = adjustScrollbarWithGeometryCvsId . view (currentCanvas._1) =<<  get 
-{-  xstate <- get
-  geometry <- liftIO . getGeometry4CurrCvs $ xstate
-  let cinfobox = view currentCanvasInfo xstate
-  let (hadj,vadj) = unboxGet adjustments cinfobox 
-      connidh = unboxGet horizAdjConnId cinfobox 
-      connidv = unboxGet vertAdjConnId cinfobox
-  liftIO $ A.adjustScrollbarWithGeometry geometry ((hadj,connidh),(vadj,connidv))  
--}
+adjustScrollbarWithGeometryCurrent = adjustScrollbarWithGeometryCvsId . view (currentCanvas._1) 
+                                     . view (unitHoodles.currentUnit) =<< get 
 
 -- | 
 hscrollBarMoved :: CanvasId -> Double -> MainCoroutine ()         
@@ -97,13 +110,13 @@
   chkCvsIdNInvalidate cid 
   vscrollMove cid v
         
-
 -- |                   
 vscrollMove :: CanvasId -> Double -> MainCoroutine () 
 vscrollMove cid v0 = do    
     ev <- nextevent 
     xst <- get 
-    geometry <- liftIO (getCanvasGeometryCvsId cid xst)
+    let uhdl = view (unitHoodles.currentUnit) xst
+    geometry <- liftIO (getCanvasGeometryCvsId cid uhdl)
     case ev of
       VScrollBarMoved cid' v -> do 
         when (cid /= cid') $ 
@@ -119,37 +132,25 @@
       VScrollBarStart cid' v -> vscrollStart cid' v 
       _ -> return ()       
 
-
-
 -- | 
 smoothScroll :: CanvasId -> CanvasGeometry -> Double -> Double -> MainCoroutine () 
-smoothScroll cid geometry v0 v = do 
-    xst <- get 
-    let b = view (settings.doesSmoothScroll) xst 
-    let diff = (v - v0) 
-        lst'  | (diff < 20 && diff > -20) = [v]
-              | (diff < 5 &&diff > -5) = []
-              | otherwise = let m :: Int = floor (minimum [20, (abs diff) / 10.0])
-                                delta = diff / fromIntegral m            
-                            in [v0 + fromIntegral n*delta | n <- [1..m] ]
-        lst | b  = lst'                     
-            | otherwise = [v] 
+smoothScroll cid geometry _v0 v = do 
+    -- xst <- get 
+    let lst = [v]
     forM_ lst $ \v' -> do 
-      updateXState $ return . over currentCanvasInfo  
-                     (runIdentity 
-                    . unboxBiXform (Identity . scrollmovecanvas v) 
-                                   (Identity . scrollmovecanvasCont geometry v') )
+      -- updateXState $ return . updater 
+      updateCanvasInfo2 (scrollmovecanvas v) (scrollmovecanvasCont geometry v') cid
       invalidateInBBox Nothing Efficient cid 
-  where scrollmovecanvas vv cvsInfo = 
-          let BBox vm_orig _ = unViewPortBBox $ view (viewInfo.pageArrangement.viewPortBBox) cvsInfo
-          in over (viewInfo.pageArrangement.viewPortBBox) 
-                  (apply (moveBBoxULCornerTo (fst vm_orig,vv))) cvsInfo 
-        -- 
-        scrollmovecanvasCont geom vv cvsInfo = 
-          let BBox vm_orig _ = unViewPortBBox $ view (viewInfo.pageArrangement.viewPortBBox) cvsInfo
-              cpn = PageNum . view currentPageNum $ cvsInfo 
-              ncpn = maybe cpn fst $ desktop2Page geom (DeskCoord (0,vv))
-          in  over currentPageNum (const (unPageNum ncpn)) 
-              . over (viewInfo.pageArrangement.viewPortBBox) 
-                       (apply (moveBBoxULCornerTo (fst vm_orig,vv))) $ cvsInfo 
-
+  where 
+    scrollmovecanvas vv cvsInfo = 
+      let BBox vm_orig _ = unViewPortBBox $ view (viewInfo.pageArrangement.viewPortBBox) cvsInfo
+      in over (viewInfo.pageArrangement.viewPortBBox) 
+              (apply (moveBBoxULCornerTo (fst vm_orig,vv))) cvsInfo 
+    -- 
+    scrollmovecanvasCont geom vv cvsInfo = 
+      let BBox vm_orig _ = unViewPortBBox $ view (viewInfo.pageArrangement.viewPortBBox) cvsInfo
+          cpn = PageNum . view currentPageNum $ cvsInfo 
+          ncpn = maybe cpn fst $ desktop2Page geom (DeskCoord (0,vv))
+      in  over currentPageNum (const (unPageNum ncpn)) 
+          . over (viewInfo.pageArrangement.viewPortBBox) 
+                   (apply (moveBBoxULCornerTo (fst vm_orig,vv))) $ cvsInfo 
diff --git a/src/Hoodle/Coroutine/Select.hs b/src/Hoodle/Coroutine/Select.hs
--- a/src/Hoodle/Coroutine/Select.hs
+++ b/src/Hoodle/Coroutine/Select.hs
@@ -3,9 +3,9 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.Select 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -18,8 +18,8 @@
 
 -- from other package 
 import           Control.Applicative
-import           Control.Category
-import           Control.Lens (view,set)
+-- import           Control.Category
+import           Control.Lens (view,set,(.~),(^.))
 import           Control.Monad
 import           Control.Monad.Identity
 import           Control.Monad.State
@@ -47,6 +47,7 @@
 import           Hoodle.Coroutine.Draw
 import           Hoodle.Coroutine.Mode
 import           Hoodle.Coroutine.Pen
+import           Hoodle.Coroutine.Select.Clipboard
 import           Hoodle.ModelAction.Layer 
 import           Hoodle.ModelAction.Page
 import           Hoodle.ModelAction.Pen
@@ -62,21 +63,21 @@
 import           Hoodle.View.Coordinate
 import           Hoodle.View.Draw
 -- 
-import           Prelude hiding ((.), id)
+-- import           Prelude hiding ((.), id)
 
 -- | For Selection mode from pen mode with 2nd pen button
 dealWithOneTimeSelectMode :: MainCoroutine ()  -- ^ main action 
                           -> MainCoroutine ()  -- ^ terminating action
                           -> MainCoroutine ()
 dealWithOneTimeSelectMode action terminator = do 
-  xstate <- get 
-  case view isOneTimeSelectMode xstate of 
+  uhdl <- view (unitHoodles.currentUnit) <$> get 
+  case view isOneTimeSelectMode uhdl of 
     NoOneTimeSelectMode -> action 
     YesBeforeSelect -> 
-      action >> updateXState (return . set isOneTimeSelectMode YesAfterSelect)
+      action >> pureUpdateUhdl (isOneTimeSelectMode .~ YesAfterSelect)
     YesAfterSelect -> do 
       terminator 
-      updateXState (return . set isOneTimeSelectMode NoOneTimeSelectMode) 
+      pureUpdateUhdl (isOneTimeSelectMode .~ NoOneTimeSelectMode) 
       modeChange ToViewAppendMode
 
   
@@ -90,20 +91,23 @@
                      -> MainCoroutine ()
 commonSelectStart typ pbtn cid = case typ of 
                                    SelectHandToolWork -> (\_ -> return ())
-                                   _ -> commonPenStart selectaction cid
-  where selectaction cinfo pnum geometry (x,y) = do
+                                   _ -> commonPenStart selectaction cid >=> const (return ())
+
+  where selectaction cinfo pnum geometry (x,y) _ = do
           itms <- rItmsInCurrLyr
           ctime <- liftIO $ getCurrentTime
           let newSelectAction _page = 
                 dealWithOneTimeSelectMode 
                   (do tsel <- createTempRender geometry [] 
                       case typ of 
-                        SelectRectangleWork -> 
+                        SelectRectangleWork -> do
                           newSelectRectangle cid pnum geometry itms 
                             (x,y) ((x,y),ctime) tsel
-                        SelectLassoWork -> 
+                          return ()
+                        SelectLassoWork -> do
                           newSelectLasso cinfo pnum geometry itms 
                              (x,y) ((x,y),ctime) (Sq.empty |> (x,y)) tsel
+                          return ()
                         _ -> return ()
                       Cairo.surfaceFinish (tempSurfaceSrc tsel) 
                       showContextMenu (pnum,(x,y))
@@ -111,9 +115,9 @@
                   (return ())  
               action (Right tpage) | hitInHandle tpage (x,y) = do  
                 let doesKeepRatio = case pbtn of 
-                                          PenButton1 -> True
-                                          PenButton3 -> False
-                                          _ -> False
+                                      PenButton1 -> True
+                                      PenButton3 -> False
+                                      _ -> False
                 case getULBBoxFromSelected tpage of 
                   Middle bbox ->  
                     maybe (return ()) 
@@ -131,8 +135,8 @@
                   _ -> return () 
               action (Right tpage) | otherwise = newSelectAction (hPage2RPage tpage)
               action (Left page) = newSelectAction page
-          xstate <- get 
-          let hdlmodst = view hoodleModeState xstate 
+          uhdl <- view (unitHoodles.currentUnit) <$> get 
+          let hdlmodst = view hoodleModeState uhdl 
           let epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst 
           action epage
 
@@ -155,13 +159,12 @@
                    (prev,otime) tempselection = do  
     r <- nextevent
     xst <- get 
-    forBoth' unboxBiAct (fsingle r xst) . getCanvasInfo cid $ xst
+    cache <- renderCache
+    forBoth' unboxBiAct (fsingle r xst cache) . getCanvasInfo cid . view (unitHoodles.currentUnit) $ xst
   where 
-    fsingle r xstate cinfo = penMoveAndUpOnly r pnum geometry defact
-                               (moveact xstate cinfo) (upact xstate cinfo)
-    defact = newSelectRectangle cid pnum geometry itms orig 
-                         (prev,otime) tempselection 
-    moveact xstate _cinfo (_pcoord,(x,y)) = do 
+    fsingle r xstate cache cinfo = penMoveAndUpOnly r pnum geometry defact (moveact cache) (upact xstate cinfo)
+    defact = newSelectRectangle cid pnum geometry itms orig (prev,otime) tempselection 
+    moveact cache (_pcoord,(x,y)) = do 
       let bbox = BBox orig (x,y)
           hittestbbox = hltEmbeddedByBBox bbox itms
           hitteditms = takeHitted hittestbbox
@@ -171,17 +174,16 @@
       when ((not.null) fitms || (not.null) sitms) $ do 
         let xformfunc = cairoXform4PageCoordinate (mkXform4Page geometry pnum)
             ulbbox = unUnion . mconcat . fmap (Union .Middle . flip inflate 5 . getBBox) $ fitms
-            cache = view renderCache xstate
             xform = mkXform4Page geometry pnum
             renderfunc = do   
               xformfunc 
               case ulbbox of 
                 Top -> do                
-                  cairoRenderOption (InBBoxOption Nothing) cache (InBBox page, Just xform) 
+                  cairoRenderOption (InBBoxOption Nothing) cache cid (InBBox page, Just xform) 
                   mapM_ renderSelectedItem hitteditms
                 Middle sbbox -> do 
                   let redrawee = filter (do2BBoxIntersect sbbox.getBBox) hitteditms  
-                  cairoRenderOption (InBBoxOption (Just sbbox)) cache (InBBox page, Just xform)
+                  cairoRenderOption (InBBoxOption (Just sbbox)) cache cid (InBBox page, Just xform)
                   clipBBox (Just sbbox)
                   mapM_ renderSelectedItem redrawee 
                 Bottom -> return ()
@@ -197,12 +199,13 @@
       let (_,(x,y)) = runIdentity $ 
             skipIfNotInSamePage pnum geometry pcoord 
                                 (return (pcoord,prev)) return
-          epage = getCurrentPageEitherFromHoodleModeState cinfo (view hoodleModeState xstate)
+          uhdl = view (unitHoodles.currentUnit) xstate
+          epage = getCurrentPageEitherFromHoodleModeState cinfo (view hoodleModeState uhdl)
           cpn = view currentPageNum cinfo 
           bbox = BBox orig (x,y)
           hittestbbox = hltEmbeddedByBBox bbox itms
           selectitms = fmapAL unNotHitted id hittestbbox
-          SelectState thdl = view hoodleModeState xstate
+          SelectState thdl = view hoodleModeState uhdl
           newpage = case epage of 
                       Left pagebbox -> makePageSelectMode pagebbox selectitms 
                       Right tpage -> 
@@ -212,9 +215,10 @@
                         in npage
           newthdl = set gselSelected (Just (cpn,newpage)) thdl 
           ui = view gtkUIManager xstate
-      liftIO $ toggleCutCopyDelete ui (isAnyHitted  selectitms)
-      put . set hoodleModeState (SelectState newthdl) 
-            =<< (liftIO (updatePageAll (SelectState newthdl) xstate))
+      liftIO $ toggleCutCopyDelete ui (isAnyHitted selectitms)
+      uhdl' <- liftIO (updatePageAll (SelectState newthdl) uhdl)
+      pureUpdateUhdl (const ((hoodleModeState .~ SelectState newthdl) uhdl'))
+      commit_
       invalidateAllInBBox Nothing Efficient
 
 
@@ -226,8 +230,8 @@
                    -> Page SelectMode
                    -> MainCoroutine () 
 startMoveSelect cid pnum geometry ((x,y),ctime) tpage = do
-    cache <- view renderCache <$> get
-    itmimage <- liftIO $ mkItmsNImg cache tpage
+    cache <- renderCache
+    itmimage <- liftIO $ mkItmsNImg cache cid tpage
     tsel <- createTempRender geometry itmimage 
     moveSelect cid pnum geometry (x,y) ((x,y),ctime) tsel 
     Cairo.surfaceFinish (tempSurfaceSrc tsel)
@@ -246,21 +250,20 @@
 moveSelect cid pnum geometry orig@(x0,y0) 
            (prev,otime) tempselection = do
     xst <- get
+    let uhdl = view (unitHoodles.currentUnit) xst
     r <- nextevent 
-    forBoth' unboxBiAct (fsingle r xst) . getCanvasInfo cid $ xst 
+    forBoth' unboxBiAct (fsingle r uhdl) (getCanvasInfo cid uhdl)
   where 
-    fsingle r xstate cinfo = 
-      penMoveAndUpInterPage r pnum geometry defact (moveact xstate cinfo) (upact xstate cinfo) 
-    defact = moveSelect cid pnum geometry orig (prev,otime) 
-               tempselection
-    moveact _xstate _cinfo oldpgn pcpair@(newpgn,PageCoord (px,py)) = do 
+    fsingle r uhdl cinfo = 
+      penMoveAndUpInterPage r pnum geometry defact moveact (upact uhdl cinfo) 
+    defact = moveSelect cid pnum geometry orig (prev,otime) tempselection
+    moveact oldpgn pcpair@(newpgn,PageCoord (px,py)) = do 
       let (x,y) 
             | oldpgn == newpgn = (px,py) 
             | otherwise = 
               let DeskCoord (xo,yo) = page2Desktop geometry (oldpgn,PageCoord (0,0))
                   DeskCoord (xn,yn) = page2Desktop geometry pcpair 
               in (xn-xo,yn-yo)
-      
       (willUpdate,(ncoord,ntime)) <- liftIO $ getNewCoordTime (prev,otime) (x,y) 
       when willUpdate $ do 
         let sfunc = offsetFunc (x-x0,y-y0)
@@ -275,25 +278,25 @@
         invalidateTempBasePage cid (tempSurfaceSrc tempselection) pnum 
           (drawTempSelectImage geometry tempselection xformmat) 
       moveSelect cid pnum geometry orig (ncoord,ntime) tempselection
-    upact :: HoodleState -> CanvasInfo a -> PointerCoord -> MainCoroutine () 
-    upact xst cinfo pcoord =  
+    upact :: UnitHoodle -> CanvasInfo a -> PointerCoord -> MainCoroutine () 
+    upact uhdl cinfo pcoord = 
       switchActionEnteringDiffPage pnum geometry pcoord (return ()) 
-        (chgaction xst cinfo) 
-        (ordaction xst cinfo)
-    chgaction :: HoodleState -> CanvasInfo a -> PageNum -> (PageNum,PageCoordinate) -> MainCoroutine () 
-    chgaction xstate cinfo oldpgn (newpgn,PageCoord (x,y)) = do 
-      let hdlmodst@(SelectState thdl) = view hoodleModeState xstate
+        (chgaction uhdl cinfo) 
+        (ordaction uhdl cinfo)
+    chgaction :: UnitHoodle -> CanvasInfo a 
+              -> PageNum -> (PageNum,PageCoordinate) -> MainCoroutine () 
+    chgaction uhdl cinfo oldpgn (newpgn,PageCoord (x,y)) = do 
+      let hdlmodst@(SelectState thdl) = view hoodleModeState uhdl
           epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst
-          cache = view renderCache xstate
-      (xstate1,nthdl1,selecteditms) <- 
+          cvsid = view canvasId cinfo
+      (uhdl1,nthdl1,selecteditms) <- 
         case epage of 
           Right oldtpage -> do 
             let itms = getSelectedItms oldtpage
             let oldtpage' = deleteSelected oldtpage
-            nthdl <- liftIO $ updateTempHoodleSelectIO cache thdl oldtpage' (unPageNum oldpgn)
-            xst <- return . set hoodleModeState (SelectState nthdl)
-                     =<< (liftIO (updatePageAll (SelectState nthdl) xstate)) 
-            return (xst,nthdl,itms)       
+            nthdl <- updateTempHoodleSelectM cvsid thdl oldtpage' (unPageNum oldpgn)
+            uhdl' <- liftIO (updatePageAll (SelectState nthdl) uhdl)
+            return (uhdl',nthdl,itms)       
           Left _ -> error "this is impossible, in moveSelect" 
       let maction = do 
             page <- M.lookup (unPageNum newpgn) (view gselAll nthdl1)
@@ -303,35 +306,32 @@
                 alist = olditms :- Hitted newitms :- Empty 
                 ntpage = makePageSelectMode page alist  
                 coroutineaction = do 
-                  nthdl2 <- liftIO $ updateTempHoodleSelectIO cache nthdl1 ntpage (unPageNum newpgn)  
-                  let cibox = view currentCanvasInfo xstate1 
-                      ncibox = (runIdentity . forBoth unboxBiXform (return . set currentPageNum (unPageNum newpgn))) 
-                                 cibox 
-                      cmap = getCanvasInfoMap xstate1 
-                      cmap' = M.adjust (const ncibox) cid cmap 
-                      xst = maybe xstate1 id $ setCanvasInfoMap cmap' xstate1
-                  return . set hoodleModeState (SelectState nthdl2)
-                    =<< (liftIO (updatePageAll (SelectState nthdl2) xst)) 
+                  nthdl2 <- updateTempHoodleSelectM cvsid nthdl1 ntpage (unPageNum newpgn)  
+                  -- let cibox = view currentCanvasInfo uhdl1 
+                  --     ncibox = ( runIdentity 
+                  --             . forBoth unboxBiXform (return . set currentPageNum (unPageNum newpgn))) 
+                  --               cibox 
+                  liftIO (updatePageAll (SelectState nthdl2) uhdl1)
             return coroutineaction
-      xstate2 <- maybe (return xstate1) id maction 
-      commit xstate2
-      -- invalidateAll 
+      uhdl2 <- maybe (return uhdl1) id maction
+      pureUpdateUhdl (const uhdl2)
+      commit_
       invalidateAllInBBox Nothing Efficient
     ----
-    ordaction xstate cinfo _pgn (_cpn,PageCoord (x,y)) = do 
+    ordaction uhdl cinfo _pgn (_cpn,PageCoord (x,y)) = do 
       let offset = (x-x0,y-y0)
-          hdlmodst@(SelectState thdl) = view hoodleModeState xstate
+          hdlmodst@(SelectState thdl) = view hoodleModeState uhdl
           epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst
           pagenum = view currentPageNum cinfo
+          cvsid = view canvasId cinfo
       case epage of 
         Right tpage -> do 
           let newtpage = changeSelectionByOffset offset tpage
-              cache = view renderCache xstate
-          newthdl <- liftIO $ updateTempHoodleSelectIO cache thdl newtpage pagenum 
-          commit . set hoodleModeState (SelectState newthdl)
-                 =<< (liftIO (updatePageAll (SelectState newthdl) xstate))
+          newthdl <- updateTempHoodleSelectM cvsid thdl newtpage pagenum 
+          uhdl' <- liftIO (updatePageAll (SelectState newthdl) uhdl)
+          pureUpdateUhdl (const uhdl')
+          commit_ 
         Left _ -> error "this is impossible, in moveSelect" 
-      -- invalidateAll 
       invalidateAllInBBox Nothing Efficient 
       
 
@@ -347,8 +347,8 @@
                   -> MainCoroutine () 
 startResizeSelect doesKeepRatio handle cid pnum geometry bbox 
                   ((x,y),ctime) tpage = do
-    cache <- view renderCache <$> get  
-    itmimage <- liftIO $ mkItmsNImg cache tpage  
+    cache <- renderCache
+    itmimage <- liftIO $ mkItmsNImg cache cid tpage  
     tsel <- createTempRender geometry itmimage 
     resizeSelect doesKeepRatio 
       handle cid pnum geometry bbox ((x,y),ctime) tsel 
@@ -370,12 +370,12 @@
 resizeSelect doesKeepRatio handle cid pnum geometry origbbox 
              (prev,otime) tempselection = do
     xst <- get
+    let uhdl = view (unitHoodles.currentUnit) xst
     r <- nextevent 
-    forBoth' unboxBiAct (fsingle r xst) . getCanvasInfo cid $ xst
+    forBoth' unboxBiAct (fsingle r uhdl) . getCanvasInfo cid $ uhdl
   where
-    fsingle r xstate cinfo = penMoveAndUpOnly r pnum geometry defact moveact (upact xstate cinfo)
-    defact = resizeSelect doesKeepRatio handle cid pnum geometry 
-               origbbox (prev,otime) tempselection
+    fsingle r uhdl cinfo = penMoveAndUpOnly r pnum geometry defact moveact (upact uhdl cinfo)
+    defact = resizeSelect doesKeepRatio handle cid pnum geometry origbbox (prev,otime) tempselection
     moveact (_pcoord,(x,y)) = do 
       (willUpdate,(ncoord,ntime)) <- liftIO $ getNewCoordTime (prev,otime) (x,y) 
       when willUpdate $ do 
@@ -393,20 +393,16 @@
                          | otherwise -> newbbox'
               else newbbox' 
             sfunc = scaleFromToBBox origbbox newbbox
-            xform = unCvsCoord . desktop2Canvas geometry
-                    . page2Desktop geometry . (,) pnum . PageCoord
+            xform = unCvsCoord . desktop2Canvas geometry . page2Desktop geometry . (,) pnum . PageCoord
             (c1,c2) = xform (sfunc (0,0))
             (a1',a2') = xform (sfunc (1,0))
             (a1,a2) = (a1'-c1,a2'-c2)
             (b1',b2') = xform (sfunc (0,1))
             (b1,b2) = (b1'-c1,b2'-c2)
             xformmat = Mat.Matrix a1 a2 b1 b2 c1 c2 
-        invalidateTemp cid (tempSurfaceSrc tempselection) 
-                           (drawTempSelectImage geometry tempselection 
-                              xformmat)
-      resizeSelect doesKeepRatio handle cid pnum geometry 
-                   origbbox (ncoord,ntime) tempselection
-    upact xstate cinfo pcoord = do 
+        invalidateTemp cid (tempSurfaceSrc tempselection) (drawTempSelectImage geometry tempselection xformmat)
+      resizeSelect doesKeepRatio handle cid pnum geometry origbbox (ncoord,ntime) tempselection
+    upact uhdl cinfo pcoord = do 
       let (_,(x,y)) = runIdentity $ 
             skipIfNotInSamePage pnum geometry pcoord 
                                 (return (pcoord,prev)) return
@@ -423,19 +419,19 @@
                        | handle == HandleBR -> BBox (x0,y0) (x1,y0+(x1-x0)*r)
                        | otherwise -> newbbox'
             else newbbox' 
-          hdlmodst@(SelectState thdl) = view hoodleModeState xstate
+          hdlmodst@(SelectState thdl) = view hoodleModeState uhdl
           epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst
           pagenum = view currentPageNum cinfo
+          cvsid = view canvasId cinfo
       case epage of 
         Right tpage -> do 
           let sfunc = scaleFromToBBox origbbox newbbox
               newtpage = changeSelectionBy sfunc tpage 
-              cache = view renderCache xstate
-          newthdl <- liftIO $ updateTempHoodleSelectIO cache thdl newtpage pagenum 
-          commit . set hoodleModeState (SelectState newthdl)
-                 =<< (liftIO (updatePageAll (SelectState newthdl) xstate))
+          newthdl <- updateTempHoodleSelectM cvsid thdl newtpage pagenum 
+          uhdl' <- liftIO (updatePageAll (SelectState newthdl) uhdl)
+          pureUpdateUhdl (const uhdl')
+          commit_
         Left _ -> error "this is impossible, in resizeSelect" 
-      -- invalidateAll
       invalidateAllInBBox Nothing Efficient
       return ()    
 
@@ -443,50 +439,50 @@
 -- | 
 selectPenColorChanged :: PenColor -> MainCoroutine () 
 selectPenColorChanged pcolor = do 
-  xstate <- get
-  let SelectState thdl = view hoodleModeState xstate 
-      Just (n,tpage) = view gselSelected thdl
-      slayer = view (glayers.selectedLayer) tpage
-  case unTEitherAlterHitted . view gitems $ slayer of 
-    Left _ -> return () 
-    Right alist -> do 
-      let alist' = fmapAL id 
-                     (Hitted . map (changeItemStrokeColor pcolor) . unHitted) alist
-          newlayer = Right alist'
-          newpage = set (glayers.selectedLayer) (GLayer (view gbuffer slayer) (TEitherAlterHitted newlayer)) tpage 
-          cache = view renderCache xstate
-      newthdl <- liftIO $ updateTempHoodleSelectIO cache thdl newpage n
-      commit =<< liftIO (updatePageAll (SelectState newthdl)
-                        . set hoodleModeState (SelectState newthdl) $ xstate )
-      -- invalidateAll 
-      invalidateAllInBBox Nothing Efficient
+    uhdl <- view (unitHoodles.currentUnit) <$> get 
+    let cid = getCurrentCanvasId uhdl
+        SelectState thdl = view hoodleModeState uhdl
+        Just (n,tpage) = view gselSelected thdl
+        slayer = view (glayers.selectedLayer) tpage
+    case unTEitherAlterHitted . view gitems $ slayer of 
+      Left _ -> return () 
+      Right alist -> do 
+        let alist' = fmapAL id (Hitted . map (changeItemStrokeColor pcolor) . unHitted) alist
+            newlayer = Right alist'
+            newpage = (glayers.selectedLayer .~ (GLayer (slayer^.gbuffer) (TEitherAlterHitted newlayer))) tpage 
+        newthdl <- updateTempHoodleSelectM cid thdl newpage n
+        uhdl' <- liftIO (updatePageAll (SelectState newthdl) uhdl)
+        pureUpdateUhdl (const uhdl')
+        commit_
+        invalidateAllInBBox Nothing Efficient
           
 -- | 
 selectPenWidthChanged :: Double -> MainCoroutine () 
 selectPenWidthChanged pwidth = do 
-  xstate <- get
-  let SelectState thdl = view hoodleModeState xstate 
+  xst <- get
+  let uhdl = view (unitHoodles.currentUnit) xst
+      cid = getCurrentCanvasId uhdl
+      SelectState thdl = view hoodleModeState uhdl
       Just (n,tpage) = view gselSelected thdl
       slayer = view (glayers.selectedLayer) tpage
-      cache = view renderCache xstate
-  case unTEitherAlterHitted . view gitems $ slayer  of 
+  case (unTEitherAlterHitted . view gitems) slayer of 
     Left _ -> return () 
     Right alist -> do 
       let alist' = fmapAL id 
                      (Hitted . map (changeItemStrokeWidth pwidth) . unHitted) alist
           newlayer = Right alist'
           newpage = set (glayers.selectedLayer) (GLayer (view gbuffer slayer) (TEitherAlterHitted newlayer)) tpage
-      newthdl <- liftIO $ updateTempHoodleSelectIO cache thdl newpage n          
-      commit =<< liftIO (updatePageAll (SelectState newthdl) 
-                         . set hoodleModeState (SelectState newthdl) $ xstate )
-      -- invalidateAll 
+      newthdl <- updateTempHoodleSelectM cid thdl newpage n          
+      uhdl' <- liftIO (updatePageAll (SelectState newthdl) uhdl)
+      pureUpdateUhdl (const uhdl')
+      commit_
       invalidateAllInBBox Nothing Efficient 
 
 -- | main mouse pointer click entrance in lasso selection mode. 
 --   choose either starting new rectangular selection or move previously 
 --   selected selection. 
 selectLassoStart :: PenButton -> CanvasId -> PointerCoord -> MainCoroutine ()
-selectLassoStart = commonSelectStart SelectLassoWork
+selectLassoStart p cid coord = commonSelectStart SelectLassoWork p cid coord >> return ()
           
 
 -- | 
@@ -501,23 +497,19 @@
                   -> MainCoroutine ()
 newSelectLasso cvsInfo pnum geometry itms orig (prev,otime) lasso tsel = nextevent >>= flip fsingle cvsInfo 
   where  
-    fsingle r cinfo = penMoveAndUpOnly r pnum geometry defact
-                        (moveact cinfo) (upact cinfo)
+    fsingle r cinfo = penMoveAndUpOnly r pnum geometry defact (moveact cinfo) (upact cinfo)
     defact = newSelectLasso cvsInfo pnum geometry itms orig 
                (prev,otime) lasso tsel
     moveact cinfo (_pcoord,(x,y)) = do 
       let nlasso = lasso |> (x,y)
       (willUpdate,(ncoord,ntime)) <- liftIO $ getNewCoordTime (prev,otime) (x,y)
-      when willUpdate $ do 
-        invalidateTemp (view canvasId cinfo) (tempSurfaceSrc tsel) (renderLasso geometry nlasso) 
+      when willUpdate $ invalidateTemp (view canvasId cinfo) (tempSurfaceSrc tsel) (renderLasso geometry nlasso) 
       newSelectLasso cinfo pnum geometry itms orig (ncoord,ntime) nlasso tsel
     upact cinfo pcoord = do 
-      xstate <- get 
-      let (_,(x,y)) = runIdentity $ 
-            skipIfNotInSamePage pnum geometry pcoord 
-                                (return (pcoord,prev)) return
+      uhdl <- view (unitHoodles.currentUnit) <$> get 
+      let (_,(x,y)) = runIdentity $ skipIfNotInSamePage pnum geometry pcoord (return (pcoord,prev)) return
           nlasso = lasso |> (x,y)
-          hdlmodst = view hoodleModeState xstate 
+          hdlmodst = view hoodleModeState uhdl
           epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst
           cpn = view currentPageNum cinfo 
           hittestlasso1 = hltFilteredBy (hitLassoItem (nlasso |> orig)) itms
@@ -530,7 +522,7 @@
           selectitms 
             | (not.null) selecteditms1 = selectitms1 
             | otherwise = selectitms2
-          SelectState thdl = view hoodleModeState xstate
+          SelectState thdl = view hoodleModeState uhdl
           newpage = case epage of 
                       Left pagebbox -> 
                         let currlayer= getCurrentLayer pagebbox
@@ -544,11 +536,11 @@
                             npage = set (glayers.selectedLayer) newlayer tpage 
                         in npage
           newthdl = set gselSelected (Just (cpn,newpage)) thdl 
-      let ui = view gtkUIManager xstate
+      ui <- view gtkUIManager <$> get
       liftIO $ toggleCutCopyDelete ui (isAnyHitted  selectitms)
-      put . set hoodleModeState (SelectState newthdl) 
-            =<< (liftIO (updatePageAll (SelectState newthdl) xstate))
-      -- invalidateAll 
+      uhdl' <- liftIO (updatePageAll (SelectState newthdl) uhdl)
+      pureUpdateUhdl (const ((hoodleModeState .~ SelectState newthdl) uhdl'))
+      commit_
       invalidateAllInBBox Nothing Efficient
 
 
diff --git a/src/Hoodle/Coroutine/Select/Clipboard.hs b/src/Hoodle/Coroutine/Select/Clipboard.hs
--- a/src/Hoodle/Coroutine/Select/Clipboard.hs
+++ b/src/Hoodle/Coroutine/Select/Clipboard.hs
@@ -3,9 +3,9 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.Select.Clipboard 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -18,14 +18,17 @@
 
 -- from other packages
 import           Control.Applicative
-import           Control.Lens (view,set,(%~))
-import           Control.Monad.State 
-import           Graphics.UI.Gtk hiding (get,set)
+import           Control.Lens (view,set,(.~))
+import           Control.Monad.State
+import           Control.Monad.Trans.Maybe
+import qualified Data.Foldable as F
+import           Data.Maybe (fromMaybe)
+import qualified Graphics.UI.Gtk as Gtk
 -- from hoodle-platform 
-import           Control.Monad.Trans.Crtn.Queue 
 import           Data.Hoodle.Generic 
 import           Data.Hoodle.Select
-import           Data.Hoodle.Simple
+import           Data.Hoodle.Simple (Item(..))
+import           Graphics.Hoodle.Render
 import           Graphics.Hoodle.Render.Item
 import           Graphics.Hoodle.Render.Type 
 import           Graphics.Hoodle.Render.Type.HitTest
@@ -33,22 +36,38 @@
 import           Hoodle.Accessor
 import           Hoodle.Coroutine.Draw
 import           Hoodle.Coroutine.Commit 
-import           Hoodle.Coroutine.Mode 
+import           Hoodle.Coroutine.Mode
+import           Hoodle.Coroutine.Page
 import           Hoodle.ModelAction.Page
 import           Hoodle.ModelAction.Select
 import           Hoodle.ModelAction.Select.Transform
 import           Hoodle.ModelAction.Clipboard
+import           Hoodle.Type.Alias
 import           Hoodle.Type.Canvas 
 import           Hoodle.Type.Coroutine
 import           Hoodle.Type.Event 
 import           Hoodle.Type.PageArrangement 
 import           Hoodle.Type.HoodleState 
+
+-- |
+updateTempHoodleSelectM :: CanvasId
+                       -> Hoodle SelectMode 
+                       -> Page SelectMode 
+                       -> Int
+                       -> MainCoroutine (Hoodle SelectMode)
+updateTempHoodleSelectM cid thdl tpage pagenum = do   
+  let newpage = hPage2RPage tpage
+  callRenderer_ $ updatePageBuf cid newpage
+  return (updateTempHoodleSelect thdl tpage pagenum)
+
  
 -- |
 deleteSelection :: MainCoroutine ()
 deleteSelection = do 
-  xstate <- get
-  case view hoodleModeState xstate of
+  xst <- get
+  let uhdl = view (unitHoodles.currentUnit) xst
+      cid = getCurrentCanvasId uhdl
+  case view hoodleModeState uhdl of
     SelectState thdl -> do 
       let Just (n,tpage) = view gselSelected thdl
           slayer = view (glayers.selectedLayer) tpage
@@ -57,14 +76,11 @@
         Right alist -> do 
           let newlayer = Left . concat . getA $ alist
               newpage = set (glayers.selectedLayer) (GLayer (view gbuffer slayer) (TEitherAlterHitted newlayer)) tpage 
-              cache = view renderCache xstate
-          newthdl <- liftIO $ updateTempHoodleSelectIO cache thdl newpage n          
-          newxstate <- liftIO $ updatePageAll (SelectState newthdl) 
-                              . set hoodleModeState (SelectState newthdl)
-                              $ xstate 
-          commit newxstate 
-          let ui = view gtkUIManager newxstate
+          newthdl <- updateTempHoodleSelectM cid thdl newpage n
+          newuhdl <- liftIO . updatePageAll (SelectState newthdl) $ uhdl 
+          let ui = view gtkUIManager xst
           liftIO $ toggleCutCopyDelete ui False 
+          commit ((unitHoodles.currentUnit .~ newuhdl) xst)
           modeChange ToViewAppendMode 
           invalidateAll 
     _ -> return ()
@@ -80,53 +96,54 @@
 copySelection = do 
     updateXState copySelectionAction >> invalidateAll 
   where copySelectionAction xst = 
-          forBoth' unboxBiAct (fsingle xst) . view currentCanvasInfo $ xst
-        fsingle xstate cinfo = maybe (return xstate) id $ do  
-          let hdlmodst = view hoodleModeState xstate
-          let epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst
-          eitherMaybe epage `pipe` rItmsInActiveLyr 
-                            `pipe` (Right . liftIO . updateClipboard xstate . map rItem2Item . takeHitted)
+          forBoth' unboxBiAct (fsingle xst) . view (unitHoodles.currentUnit.currentCanvasInfo) $ xst
+        fsingle xst cinfo = do
+            r <- runMaybeT $ do 
+              let uhdl = view (unitHoodles.currentUnit) xst
+                  hdlmodst = view hoodleModeState uhdl
+                  epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst
+              pg <- (MaybeT . return . eitherMaybe) epage
+              hitted <- (MaybeT . return . eitherMaybe) (rItmsInActiveLyr pg)
+              (liftIO . updateClipboard xst . map rItem2Item . takeHitted) hitted
+            return (fromMaybe xst r)
           where eitherMaybe (Left _) = Nothing
                 eitherMaybe (Right a) = Just a 
-                x `pipe` a = x >>= eitherMaybe . a 
-                infixl 6 `pipe`
 
 -- |
 getClipFromGtk :: MainCoroutine (Maybe [Item])
 getClipFromGtk = do 
-    let action = mkIOaction $ 
-                   \evhandler -> do 
-                       hdltag <- liftIO $ atomNew "hoodle"
-                       clipbd <- liftIO $ clipboardGet hdltag
-                       liftIO $ clipboardRequestText clipbd (callback4Clip evhandler)
-                       return (UsrEv ActionOrdered)
-    modify (tempQueue %~ enqueue action) 
-    go 
-  where go = do r <- nextevent 
-                case r of 
-                  GotClipboardContent cnt' -> return cnt' 
-                  _ -> go 
+    doIOaction $ \evhandler -> do 
+      hdltag <- liftIO $ Gtk.atomNew "hoodle"
+      clipbd <- liftIO $ Gtk.clipboardGet hdltag
+      liftIO $ Gtk.clipboardRequestText clipbd (callback4Clip evhandler)
+      return (UsrEv ActionOrdered)
+    waitSomeEvent (\case GotClipboardContent _ -> True; _ -> False ) >>= \(GotClipboardContent cnt') -> return cnt'
 
 
 -- | 
 pasteToSelection :: MainCoroutine () 
 pasteToSelection = do 
-    mitms <- getClipFromGtk 
-    case mitms of 
-      Nothing -> return () 
-      Just itms -> do 
-        -- 
-        callRenderer $ GotRItems <$> mapM cnstrctRItem itms
-        RenderEv (GotRItems ritms) <- 
-          waitSomeEvent (\case RenderEv (GotRItems _) -> True; _ -> False)
-        --
-        modeChange ToSelectMode >>updateXState (pasteAction ritms) >> invalidateAll  
+    mitms <- getClipFromGtk
+    F.forM_ mitms $ \itms -> do
+      callRenderer $ GotRItems <$> mapM cnstrctRItem itms
+      RenderEv (GotRItems ritms) <- 
+        waitSomeEvent (\case RenderEv (GotRItems _) -> True; _ -> False)
+      xst <- get
+      cache <- renderCache 
+      let ui = view gtkUIManager xst
+      modeChange ToSelectMode 
+      updateUhdl (pasteAction cache ui ritms)
+      commit_ 
+      canvasZoomUpdateAll
+      invalidateAll  
   where 
-    pasteAction itms xst = forBoth' unboxBiAct (fsimple itms xst) . view currentCanvasInfo $ xst
-    fsimple itms xstate cinfo = do 
-      geometry <- liftIO (getGeometry4CurrCvs xstate)
-      let pagenum = view currentPageNum cinfo 
-          hdlmodst@(SelectState thdl) = view hoodleModeState xstate
+    pasteAction cache ui itms uhdl = forBoth' unboxBiAct (fsimple cache ui itms uhdl) 
+                                     . view currentCanvasInfo $ uhdl
+    fsimple _cache ui itms uhdl cinfo = do 
+      geometry <- liftIO (getGeometry4CurrCvs uhdl)
+      let cid = view canvasId cinfo
+          pagenum = view currentPageNum cinfo 
+          hdlmodst@(SelectState thdl) = view hoodleModeState uhdl
           nclipitms = adjustItemPosition4Paste geometry (PageNum pagenum) itms
           epage = getCurrentPageEitherFromHoodleModeState cinfo hdlmodst 
           tpage = either mkHPage id epage
@@ -139,12 +156,7 @@
                             :- Hitted nclipitms 
                             :- Empty )
           tpage' = set (glayers.selectedLayer) newlayerselect tpage
-          cache = view renderCache xstate
-      thdl' <- liftIO $ updateTempHoodleSelectIO cache thdl tpage' pagenum 
-      xstate' <- liftIO $ updatePageAll (SelectState thdl') 
-                 . set hoodleModeState (SelectState thdl') 
-                 $ xstate 
-      commit xstate' 
-      let ui = view gtkUIManager xstate' 
+      thdl' <- updateTempHoodleSelectM cid thdl tpage' pagenum 
+      uhdl' <- liftIO $ updatePageAll (SelectState thdl') uhdl
       liftIO $ toggleCutCopyDelete ui True
-      return xstate' 
+      return uhdl'
diff --git a/src/Hoodle/Coroutine/Select/ManipulateImage.hs b/src/Hoodle/Coroutine/Select/ManipulateImage.hs
--- a/src/Hoodle/Coroutine/Select/ManipulateImage.hs
+++ b/src/Hoodle/Coroutine/Select/ManipulateImage.hs
@@ -4,9 +4,9 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.Select.ManipulateImage
--- Copyright   : (c) 2013, 2014 Ian-Woo Kim
+-- Copyright   : (c) 2013-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -17,7 +17,7 @@
 
 module Hoodle.Coroutine.Select.ManipulateImage where
 
-import           Control.Lens (set, view, _2)
+import           Control.Lens (set, view, _2, (.~))
 import           Control.Monad (when)
 import           Control.Monad.State (get)
 import           Control.Monad.Trans (liftIO)
@@ -37,6 +37,7 @@
 import           Hoodle.Coroutine.Commit
 import           Hoodle.Coroutine.Draw
 import           Hoodle.Coroutine.Pen
+import           Hoodle.Coroutine.Select.Clipboard
 import           Hoodle.Device
 import           Hoodle.ModelAction.Page
 import           Hoodle.ModelAction.Pen
@@ -55,10 +56,10 @@
 
 cropImage :: BBoxed Image -> MainCoroutine ()
 cropImage imgbbx = do 
-    liftIO $ putStrLn "cropImage called"
     xst <- get
-    let (cid,cinfobox) = view currentCanvas xst 
-        hdlmodst = view hoodleModeState xst
+    let uhdl = view (unitHoodles.currentUnit) xst
+        (cid,cinfobox) = view currentCanvas uhdl
+        hdlmodst = view hoodleModeState uhdl
         epage = forBoth' unboxBiAct (flip getCurrentPageEitherFromHoodleModeState hdlmodst) cinfobox
     case hdlmodst of 
       ViewAppendState _ -> return ()
@@ -81,7 +82,8 @@
               -> MainCoroutine ()
 startCropRect cid imgbbx (thdl,tpage) pcoord0 = do 
     xst <- get
-    geometry <- liftIO $ getGeometry4CurrCvs xst
+    let uhdl = view (unitHoodles.currentUnit) xst
+    geometry <- liftIO $ getGeometry4CurrCvs uhdl
     forM_ ((desktop2Page geometry . device2Desktop geometry) pcoord0) $ \(p0,c0) -> do
       tsel <- createTempRender geometry (p0, BBox (unPageCoord c0) (unPageCoord c0))
       ctime <- liftIO $ getCurrentTime
@@ -91,7 +93,7 @@
       let pnum = (fst . tempInfo) tsel
           img = bbxed_content imgbbx
           obbox = getBBox imgbbx
-          cache = view renderCache xst
+          cvsid = getCurrentCanvasId uhdl
       when (isBBox2InBBox1 obbox nbbox) $ do
         mimg' <- liftIO $ createCroppedImage img obbox nbbox 
         forM_ mimg' $ \img' -> do
@@ -101,8 +103,9 @@
             waitSomeEvent (\case RenderEv (GotRItem _) -> True; _ -> False)
           --
           let ntpage = replaceSelection rimg' tpage
-          nthdl <- liftIO $ updateTempHoodleSelectIO cache thdl ntpage (unPageNum pnum)
-          commit . set hoodleModeState (SelectState nthdl) =<< (liftIO (updatePageAll (SelectState nthdl) xst))
+          nthdl <- updateTempHoodleSelectM cvsid thdl ntpage (unPageNum pnum)
+          uhdl' <- liftIO (updatePageAll (SelectState nthdl) uhdl)
+          commit $ (unitHoodles.currentUnit .~ uhdl') xst  
       invalidateAllInBBox Nothing Efficient      
       return ()
     
@@ -156,11 +159,11 @@
 rotateImage :: RotateDir -> BBoxed Image -> MainCoroutine ()
 rotateImage dir imgbbx = do 
     xst <- get
-    let (_cid,cinfobox) = view currentCanvas xst 
-        hdlmodst = view hoodleModeState xst
+    let uhdl = view (unitHoodles.currentUnit) xst
+    let (cid,cinfobox) = view currentCanvas uhdl
+        hdlmodst = view hoodleModeState uhdl
         pnum = (PageNum . forBoth' unboxBiAct (view currentPageNum)) cinfobox        
         epage = forBoth' unboxBiAct (flip getCurrentPageEitherFromHoodleModeState hdlmodst) cinfobox
-        cache = view renderCache xst
     case hdlmodst of 
       ViewAppendState _ -> return ()
       SelectState thdl -> do 
@@ -170,14 +173,13 @@
             let img = bbxed_content imgbbx 
             mimg' <- liftIO (createRotatedImage dir img (getBBox imgbbx))
             forM_ mimg' $ \img' -> do 
-              --
               callRenderer $ return . GotRItem =<< cnstrctRItem (ItemImage img')
               RenderEv (GotRItem rimg') <- 
                 waitSomeEvent (\case RenderEv (GotRItem _) -> True; _ -> False)
-              --
               let ntpage = replaceSelection rimg' tpage
-              nthdl <- liftIO $ updateTempHoodleSelectIO cache thdl ntpage (unPageNum pnum)
-              commit . set hoodleModeState (SelectState nthdl) =<< (liftIO (updatePageAll (SelectState nthdl) xst))
+              nthdl <- updateTempHoodleSelectM cid thdl ntpage (unPageNum pnum)
+              uhdl' <- liftIO (updatePageAll (SelectState nthdl) uhdl)
+              commit $ (unitHoodles.currentUnit .~ uhdl') xst
             invalidateAllInBBox Nothing Efficient      
             return ()
 
diff --git a/src/Hoodle/Coroutine/Socket.hs b/src/Hoodle/Coroutine/Socket.hs
new file mode 100644
--- /dev/null
+++ b/src/Hoodle/Coroutine/Socket.hs
@@ -0,0 +1,141 @@
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Hoodle.Coroutine.Socket
+-- Copyright   : (c) 2014, 2015 Ian-Woo Kim
+--
+-- License     : BSD3
+-- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
+-- Stability   : experimental
+-- Portability : GHC
+--
+-----------------------------------------------------------------------------
+
+module Hoodle.Coroutine.Socket where
+
+import           Control.Applicative
+import           Control.Concurrent
+import qualified Control.Exception as E
+import           Control.Lens (view)
+import           Control.Monad.IO.Class
+import           Control.Monad.State
+import           Control.Monad.Trans.Either
+import           Control.Monad.Trans.Maybe
+import           Data.Aeson.Parser
+import           Data.Aeson.Types
+import qualified Data.Attoparsec.ByteString as A
+import qualified Data.CaseInsensitive as CI
+import           Data.Monoid ((<>))
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as TE
+import           Data.Time.Clock
+import qualified Graphics.UI.Gtk as Gtk
+import Network.HTTP.Client.Internal (computeCookieString)
+import Network.HTTP.Conduit
+import qualified Network.WebSockets as WS
+import System.Directory
+import System.FilePath ((</>))
+--
+import Hoodle.Coroutine.Dialog
+import Hoodle.Coroutine.Hub.Common
+import Hoodle.Script.Hook
+import Hoodle.Type.Coroutine
+import Hoodle.Type.Event
+import Hoodle.Type.Hub
+import Hoodle.Type.HoodleState
+import Hoodle.Type.Synchronization
+import Hoodle.Util
+--
+
+data Permission = Owner | Editor | Viewer | Stranger deriving (Show,Eq,Ord,Read)
+
+instance ToJSON Permission where
+  toJSON Owner    = String "owner"
+  toJSON Editor   = String "editor"
+  toJSON Viewer   = String "viewer"
+  toJSON Stranger = String "stranger"
+
+instance FromJSON Permission where
+  parseJSON (String t) =
+    case t of
+      "owner"    -> return Owner
+      "editor"   -> return Editor
+      "viewer"   -> return Viewer
+      "stranger" -> return Stranger
+      _ -> fail "error in parsing Permission"
+  parseJSON _ = fail "error in parsing Permission"
+
+data HoodleWSEvent = HWSOpen { hws_permission :: Permission
+                             , hws_fileuuid   :: T.Text
+                             , hws_filepath   :: T.Text }
+                   | HWSSync { hws_clientuuid :: T.Text
+                             , hws_filesyncstatus :: FileSyncStatus
+                             } 
+               deriving Show
+
+instance ToJSON HoodleWSEvent where
+  toJSON HWSOpen {..} = object [ "eventType"  .= toJSON ("open" :: T.Text)
+                               , "permission" .= toJSON hws_permission
+                               , "fileuuid"   .= toJSON hws_fileuuid
+                               , "filepath"   .= toJSON hws_filepath ]
+  toJSON HWSSync {..} = object [ "eventType"  .= toJSON ("sync" :: T.Text)
+                               , "clientuuid" .= toJSON hws_clientuuid
+                               , "filesyncstatus"   .= toJSON hws_filesyncstatus
+                               ]
+
+instance FromJSON HoodleWSEvent where
+  parseJSON (Object v) = do
+      typ :: T.Text <- v .: "eventType"
+      case typ of
+        "open" -> HWSOpen <$> v .: "permission" <*> v .: "fileuuid" <*> v .: "filepath" 
+        "sync" -> HWSSync <$> v .: "clientuuid" <*> v .: "filesyncstatus"
+        _ -> fail "error in parsing HoodleWSEvent"
+  parseJSON _ = fail "error in parsing HoodleWSEvent"
+
+-- |
+socketConnect :: MainCoroutine ()
+socketConnect = do
+    xst <- get
+    r <- runMaybeT $ do 
+      hset <- (MaybeT . return) $ view hookSet xst
+      hinfo <- (MaybeT . return) (hubInfo hset)
+      lift (hoodleWSStart hinfo)
+    case r of 
+      Nothing -> okMessageBox "socket connect not successful" >> return ()
+      Just _ -> return ()  
+
+
+hoodleWSStart :: HubInfo -> MainCoroutine ()
+hoodleWSStart hinfo@HubInfo {..} = do
+    hdir <- liftIO $ getHomeDirectory
+    let tokfile = hdir </> ".hoodle.d" </> "token.txt"
+    prepareToken hinfo tokfile 
+    doIOaction $ \evhandler -> do 
+      forkIO $ (`E.catch` (\(err:: E.SomeException)-> print err >> return ())) $ 
+        withHub hinfo tokfile $ \_manager coojar -> do
+          request2' <- parseUrl ("http://" <> hubSocketURL <> ":" <> show hubSocketPort </> hubSocketPath)
+          ctime <- liftIO getCurrentTime
+          let (bstr,_) = computeCookieString request2' coojar ctime True
+              newheaders = [(CI.mk "Cookie",bstr)] 
+          liftIO $ WS.runClientWith hubSocketURL hubSocketPort hubSocketPath WS.defaultConnectionOptions newheaders $ \conn -> forever $ do 
+            txt <- WS.receiveData conn
+            runEitherT $ do
+              v <- hoistEither $ A.parseOnly json (TE.encodeUtf8 txt)
+              o :: HoodleWSEvent <- hoistEither $ parseEither parseJSON v
+              lift $ hoodleWSDispatchEvent evhandler hinfo o 
+      return (UsrEv ActionOrdered)
+
+hoodleWSDispatchEvent :: (AllEvent -> IO ()) -> HubInfo -> HoodleWSEvent -> IO ()
+hoodleWSDispatchEvent evhandler HubInfo {..} HWSOpen {..} = do
+    let urlpath = FileUrl (hubFileRoot </> T.unpack hws_filepath)
+        uuid = read (T.unpack hws_fileuuid)
+    case hws_permission of
+      Owner  -> (Gtk.postGUIAsync . evhandler . UsrEv) (OpenLink urlpath Nothing)
+      Editor -> (Gtk.postGUIAsync . evhandler . UsrEv) (OpenShared uuid)
+      _ -> return ()
+hoodleWSDispatchEvent evhandler HubInfo {..} HWSSync {..} = 
+    let clientuuid = read (T.unpack hws_clientuuid) 
+    in (Gtk.postGUIAsync . evhandler . UsrEv) (GotSyncEvent False clientuuid hws_filesyncstatus)
diff --git a/src/Hoodle/Coroutine/TextInput.hs b/src/Hoodle/Coroutine/TextInput.hs
--- a/src/Hoodle/Coroutine/TextInput.hs
+++ b/src/Hoodle/Coroutine/TextInput.hs
@@ -1,14 +1,15 @@
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE MultiWayIf #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TupleSections #-}
 
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.TextInput 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -18,18 +19,16 @@
 module Hoodle.Coroutine.TextInput where
 
 import           Control.Applicative
--- import           Control.Concurrent.STM (atomically, newTVar)
-import           Control.Lens (_1,_2,_3,view,set,(%~),(^.),(.~))
+import qualified Control.Exception
+import           Control.Lens (_2,_3,view,(%~),(^.),(.~))
 import           Control.Monad.State hiding (mapM_, forM_)
 import           Control.Monad.Trans.Either
 import           Control.Monad.Trans.Maybe
--- import           Data.Attoparsec
-import           Data.Attoparsec.Char8
+import           Data.Attoparsec.ByteString.Char8
 import qualified Data.ByteString.Char8 as B 
 import           Data.Foldable (mapM_, forM_)
 import           Data.List (sortBy)
-import qualified Data.Map as M
-import           Data.Maybe (catMaybes)
+import qualified Data.HashMap.Strict as M
 import           Data.Monoid ((<>))
 import qualified Data.Text as T
 import qualified Data.Text.Encoding as TE
@@ -37,12 +36,14 @@
 import           Data.UUID.V4 (nextRandom)
 import qualified Graphics.Rendering.Cairo as Cairo
 import qualified Graphics.Rendering.Cairo.SVG as RSVG
--- import qualified Graphics.Rendering.Pango.Cairo as Pango
 import qualified Graphics.UI.Gtk as Gtk
 import           System.Directory 
 import           System.Exit (ExitCode(..))
 import           System.FilePath 
 import           System.Process (readProcessWithExitCode)
+#ifdef HUB
+import           Control.Concurrent (killThread)
+#endif
 -- 
 import           Control.Monad.Trans.Crtn
 import           Control.Monad.Trans.Crtn.Event 
@@ -61,8 +62,9 @@
 import           Hoodle.Coroutine.Commit
 import           Hoodle.Coroutine.Dialog
 import           Hoodle.Coroutine.Draw 
+import           Hoodle.Coroutine.LaTeX
 import           Hoodle.Coroutine.Mode
-import           Hoodle.Coroutine.Network
+import           Hoodle.Coroutine.Page
 import           Hoodle.Coroutine.Select.Clipboard
 import           Hoodle.ModelAction.Layer 
 import           Hoodle.ModelAction.Page
@@ -76,44 +78,24 @@
 import           Hoodle.Type.HoodleState 
 import           Hoodle.Type.PageArrangement
 import           Hoodle.Util
+#ifdef HUB
+import           Hoodle.Coroutine.Network
+#endif
 -- 
 import Prelude hiding (readFile,mapM_)
 
 
--- | single line text input : almost abandoned now
-textInputDialog :: MainCoroutine (Maybe String) 
-textInputDialog = do 
-  doIOaction $ \_evhandler -> do 
-                 dialog <- Gtk.messageDialogNew Nothing [Gtk.DialogModal]
-                   Gtk.MessageQuestion Gtk.ButtonsOkCancel "text input"
-                 vbox <- Gtk.dialogGetUpper dialog
-                 txtvw <- Gtk.textViewNew
-                 Gtk.boxPackStart vbox txtvw Gtk.PackGrow 0 
-                 Gtk.widgetShowAll dialog
-                 res <- Gtk.dialogRun dialog 
-                 case res of 
-                   Gtk.ResponseOk -> do 
-                     buf <- Gtk.textViewGetBuffer txtvw 
-                     (istart,iend) <- (,) <$> Gtk.textBufferGetStartIter buf
-                                          <*> Gtk.textBufferGetEndIter buf
-                     l <- Gtk.textBufferGetText buf istart iend True
-                     Gtk.widgetDestroy dialog
-                     return (UsrEv (TextInput (Just l)))
-                   _ -> do 
-                     Gtk.widgetDestroy dialog
-                     return (UsrEv (TextInput Nothing))
-  let go = do r <- nextevent
-              case r of 
-                TextInput input -> return input 
-                UpdateCanvas cid -> invalidateInBBox Nothing Efficient cid >> go 
-                _ -> go 
-  go 
-
 -- | common dialog with multiline edit input box 
-multiLineDialog :: T.Text -> Either (ActionOrder AllEvent) AllEvent
-multiLineDialog str = mkIOaction $ \evhandler -> do
+multiLineDialog :: T.Text -> (AllEvent -> IO ()) -> IO AllEvent
+multiLineDialog str evhandler = do
     dialog <- Gtk.dialogNew
+#ifdef GTK3    
+    upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)
+    vbox <- Gtk.vBoxNew False 0
+    Gtk.containerAdd upper vbox
+#else 
     vbox <- Gtk.dialogGetUpper dialog
+#endif
     textbuf <- Gtk.textBufferNew Nothing
     Gtk.textBufferSetByteString textbuf (TE.encodeUtf8 str)
     textbuf `Gtk.on` Gtk.bufferChanged $ do 
@@ -125,7 +107,7 @@
     hscrbar <- Gtk.hScrollbarNew =<< Gtk.textViewGetHadjustment textarea 
     textarea `Gtk.on` Gtk.sizeRequest $ return (Gtk.Requisition 500 600)
     fdesc <- Gtk.fontDescriptionNew
-    Gtk.fontDescriptionSetFamily fdesc "Mono"
+    Gtk.fontDescriptionSetFamily fdesc ("Mono" :: String)
     Gtk.widgetModifyFont textarea (Just fdesc)
     -- 
     table <- Gtk.tableNew 2 2 False
@@ -134,16 +116,20 @@
     Gtk.tableAttachDefaults table hscrbar 0 1 1 2 
     Gtk.boxPackStart vbox table Gtk.PackNatural 0
     -- 
-    _btnOk <- Gtk.dialogAddButton dialog "Ok" Gtk.ResponseOk
-    _btnCancel <- Gtk.dialogAddButton dialog "Cancel" Gtk.ResponseCancel
-    _btnNetwork <- Gtk.dialogAddButton dialog "Network" (Gtk.ResponseUser 1)
+    _btnOk <- Gtk.dialogAddButton dialog ("Ok" :: String) Gtk.ResponseOk
+    _btnCancel <- Gtk.dialogAddButton dialog ("Cancel" :: String) Gtk.ResponseCancel
+#ifdef HUB
+    _btnNetwork <- Gtk.dialogAddButton dialog ("Network" :: String) (Gtk.ResponseUser 1)
+#endif
     Gtk.widgetShowAll dialog
     res <- Gtk.dialogRun dialog
     Gtk.widgetDestroy dialog
     case res of 
       Gtk.ResponseOk -> return (UsrEv (OkCancel True))
       Gtk.ResponseCancel -> return (UsrEv (OkCancel False))
+#ifdef HUB
       Gtk.ResponseUser 1 -> return (UsrEv (NetworkProcess NetworkDialog))
+#endif
       _ -> return (UsrEv (OkCancel False))
 
 -- | main event loop for multiline edit box
@@ -155,7 +141,9 @@
                           >> multiLineLoop txt
       OkCancel True -> (return . Just) txt
       OkCancel False -> return Nothing
+#ifdef HUB
       NetworkProcess NetworkDialog -> networkTextInput txt
+#endif
       MultiLine (MultiLineChanged txt') -> multiLineLoop txt'
       _ -> multiLineLoop txt
 
@@ -164,21 +152,21 @@
 textInput mpos str = do 
     case mpos of 
       Just (x0,y0) -> do 
-        modify (tempQueue %~ enqueue (multiLineDialog str))  
+        doIOaction (multiLineDialog str)
         multiLineLoop str >>= 
           mapM_ (\result -> deleteSelection
                             >> liftIO (makePangoTextSVG (x0,y0) result) 
                             >>= svgInsert (result,"pango"))
-      Nothing -> liftIO $ putStrLn "textInput: not implemented"
+      Nothing -> msgShout "textInput: not implemented"
   
 -- | insert latex
 laTeXInput :: Maybe (Double,Double) -> T.Text -> MainCoroutine ()
 laTeXInput mpos str = do 
     case mpos of 
       Just (x0,y0) -> do 
-        modify (tempQueue %~ enqueue (multiLineDialog str))  
+        doIOaction (multiLineDialog str)
         multiLineLoop str >>= 
-          mapM_ (\result -> liftIO (makeLaTeXSVG (x0,y0) result) >>= \case 
+          mapM_ (\result -> liftIO (makeLaTeXSVG (x0,y0) Nothing result) >>= \case 
                   Right r -> deleteSelection >> svgInsert (result,"latex") r
                   Left err -> okMessageBox err >> laTeXInput mpos result
                 )
@@ -216,12 +204,13 @@
 
 
 -- | 
+#ifdef HUB
 laTeXInputNetwork :: Maybe (Double,Double) -> T.Text -> MainCoroutine ()
 laTeXInputNetwork mpos str =  
     case mpos of 
       Just (x0,y0) -> do 
         networkTextInput str >>=
-          mapM_ (\result -> liftIO (makeLaTeXSVG (x0,y0) result) 
+          mapM_ (\result -> liftIO (makeLaTeXSVG (x0,y0) Nothing result) 
                             >>= \case Right r -> deleteSelection >> svgInsert (result,"latex") r
                                       Left err -> okMessageBox err >> laTeXInput mpos result
                 )
@@ -230,41 +219,38 @@
         autoPosText >>=
           maybe (laTeXInputNetwork (Just (100,100)) str) 
                 (\y'->laTeXInputNetwork (Just (100,y')) str) 
-
+#endif
 
 dbusNetworkInput :: T.Text -> MainCoroutine ()
 dbusNetworkInput txt = do 
     modeChange ToViewAppendMode     
     mpos <- autoPosText 
     let pos = maybe (100,100) (100,) mpos 
-    rsvg <- liftIO (makeLaTeXSVG pos txt) 
+    rsvg <- liftIO (makeLaTeXSVG pos Nothing txt) 
     case rsvg of 
       Right r -> deleteSelection >> svgInsert (txt,"latex") r
       Left err -> okMessageBox err >> laTeXInput (Just pos) txt
 
 
-laTeXHeader :: T.Text
-laTeXHeader = "\\documentclass{article}\n\
-              \\\pagestyle{empty}\n\
-              \\\begin{document}\n"
-                                
-laTeXFooter :: T.Text
-laTeXFooter = "\\end{document}\n"
+check :: String -> IO (ExitCode,String) -> EitherT String IO ()
+check msg act = do
+    er <- liftIO $ Control.Exception.try act
+    case er of 
+      Left (Control.Exception.SomeException excp) -> left (show excp)
+      Right (ecode,str) -> case ecode of ExitSuccess -> right () ; _ -> left (msg ++ ":" ++ str)
 
-makeLaTeXSVG :: (Double,Double) -> T.Text 
+
+makeLaTeXSVG :: (Double,Double) -> Maybe Dimension -> T.Text 
              -> IO (Either String (B.ByteString,BBox))
-makeLaTeXSVG (x0,y0) txt = do
+makeLaTeXSVG (x0,y0) mdim txt = do
     cdir <- getCurrentDirectory
     tdir <- getTemporaryDirectory
     tfilename <- show <$> nextRandom
-    
     setCurrentDirectory tdir
-    let check msg act = liftIO act >>= \(ecode,str) -> case ecode of ExitSuccess -> right () ; _ -> left (msg ++ ":" ++ str)
-        
     B.writeFile (tfilename <.> "tex") (TE.encodeUtf8 txt)
     r <- runEitherT $ do 
       check "error during xelatex" $ do 
-        (ecode,ostr,estr) <- readProcessWithExitCode "xelatex" [tfilename <.> "tex"] ""
+        (ecode,ostr,estr) <- readProcessWithExitCode "xelatex" ["-shell-escape", tfilename <.> "tex"] ""
         return (ecode,ostr++estr)
       check "error during pdfcrop" $ do 
         (ecode,ostr,estr) <- readProcessWithExitCode "pdfcrop" [tfilename <.> "pdf",tfilename ++ "_crop" <.> "pdf"] ""       
@@ -274,8 +260,13 @@
         return (ecode,ostr++estr)
       bstr <- liftIO $ B.readFile (tfilename <.> "svg")
       rsvg <- liftIO $ RSVG.svgNewFromString (B.unpack bstr) 
-      let (w,h) = RSVG.svgGetSize rsvg
-      return (bstr,BBox (x0,y0) (x0+fromIntegral w,y0+fromIntegral h)) 
+      let ow, oh :: Int
+          (ow,oh) = RSVG.svgGetSize rsvg
+          ow', oh' :: Double
+          (ow',oh') = (fromIntegral ow, fromIntegral oh)
+          w, h :: Double
+          (w,h) = maybe (ow',oh') (\(Dim w' _)->(w',oh'*w'/ow')) mdim 
+      return (bstr,BBox (x0,y0) (x0+w,y0+h)) 
     setCurrentDirectory cdir
     return r
     
@@ -283,9 +274,11 @@
 -- |
 svgInsert :: (T.Text,String) -> (B.ByteString,BBox) -> MainCoroutine () 
 svgInsert (txt,cmd) (svgbstr,BBox (x0,y0) (x1,y1)) = do 
-    xstate <- get 
-    let pgnum = view (unboxLens currentPageNum) . view currentCanvasInfo $ xstate
-        hdl = getHoodle xstate 
+    xst <- get 
+    let uhdl = view (unitHoodles.currentUnit) xst
+        cid = getCurrentCanvasId uhdl
+        pgnum = view (unboxLens currentPageNum) . view currentCanvasInfo $ uhdl
+        hdl = getHoodle uhdl
         currpage = getPageFromGHoodleMap pgnum hdl
         currlayer = getCurrentLayer currpage
     --
@@ -298,15 +291,15 @@
     let otheritems = view gitems currlayer  
     let ntpg = makePageSelectMode currpage 
                  (otheritems :- (Hitted [newitem]) :- Empty)  
-        cache = view renderCache xstate
     modeChange ToSelectMode 
-    nxstate <- get 
-    thdl <- case view hoodleModeState nxstate of
-              SelectState thdl' -> return thdl'
-              _ -> (lift . EitherT . return . Left . Other) "svgInsert"
-    nthdl <- liftIO $ updateTempHoodleSelectIO cache thdl ntpg pgnum 
-    put (set hoodleModeState (SelectState nthdl) nxstate)
+    updateUhdl $ \nuhdl -> do
+      thdl <- case view hoodleModeState nuhdl of
+                SelectState thdl' -> return thdl'
+                _ -> (lift . EitherT . return . Left . Other) "svgInsert"
+      nthdl <- updateTempHoodleSelectM cid thdl ntpg pgnum 
+      return $ (hoodleModeState .~ SelectState nthdl) nuhdl
     commit_
+    canvasZoomUpdateAll
     invalidateAll 
   
 -- |     
@@ -336,8 +329,9 @@
               -> (B.ByteString,BBox) 
               -> MainCoroutine ()
 linkInsert _typ (uuidbstr,fname) str (svgbstr,BBox (x0,y0) (x1,y1)) = do 
-    xstate <- get 
-    let pgnum = view (currentCanvasInfo . unboxLens currentPageNum) xstate 
+    xst <- get 
+    let uhdl = view (unitHoodles.currentUnit) xst 
+    let pgnum = view (currentCanvasInfo . unboxLens currentPageNum) uhdl
         lnk = Link uuidbstr "simple" (B.pack fname) (Just (B.pack str)) Nothing svgbstr 
                   (x0,y0) (Dim (x1-x0) (y1-y0))
     nlnk <- liftIO $ convertLinkFromSimpleToDocID lnk >>= maybe (return lnk) return
@@ -389,31 +383,12 @@
 -- | combine all LaTeX texts into a text file 
 combineLaTeXText :: MainCoroutine ()
 combineLaTeXText = do
-    hdl <- rHoodle2Hoodle . getHoodle <$> get  
-    let mlatex_components = do 
-          (pgnum,pg) <- (zip ([1..] :: [Int]) . view pages) hdl  
-          l <- view layers pg
-          i <- view items l
-          case i of 
-            ItemSVG svg ->  
-              case svg_command svg of
-                Just "latex" -> do 
-                  let (_,y) = svg_pos svg  
-                  return ((pgnum,y,) <$> svg_text svg) 
-                _ -> []
-            _ -> []
-    let cfunc :: (Ord a,Ord b,Ord c) => (a,b,c) -> (a,b,c) -> Ordering 
-        cfunc x y | view _1 x > view _1 y = GT
-                  | view _1 x < view _1 y = LT
-                  | otherwise = if | view _2 x > view _2 y -> GT
-                                   | view _2 x < view _2 y -> LT
-                                   | otherwise -> EQ
-    let latex_components = catMaybes  mlatex_components
-        sorted = sortBy cfunc latex_components 
-        resulttxt = (B.intercalate "%%%%%%%%%%%%\n\n%%%%%%%%%%\n" . map (view _3)) sorted
+    hdl <- rHoodle2Hoodle . getHoodle . view (unitHoodles.currentUnit) <$> get  
+    let sorted = getLaTeXComponentsFromHdl hdl
+   
+        resulttxt = (T.intercalate "%%%%%%%%%%%%\n\n%%%%%%%%%%\n" . map (view (_2._3))) sorted
     mfilename <- fileChooser Gtk.FileChooserActionSave Nothing
-    forM_ mfilename (\filename -> liftIO (B.writeFile filename resulttxt) >> return ())
-
+    forM_ mfilename (\filename -> liftIO (TIO.writeFile filename resulttxt) >> return ())
 
 
 insertItemAt :: Maybe (PageNum,PageCoordinate) 
@@ -421,11 +396,13 @@
                 -> MainCoroutine () 
 insertItemAt mpcoord ritm = do 
     xst <- get   
-    geometry <- liftIO (getGeometry4CurrCvs xst) 
-    let hdl = getHoodle xst 
+    let uhdl = view (unitHoodles.currentUnit) xst
+    geometry <- liftIO (getGeometry4CurrCvs uhdl) 
+    let cid = getCurrentCanvasId uhdl
+        hdl = getHoodle uhdl
         (pgnum,mpos) = case mpcoord of 
           Just (PageNum n,pos) -> (n,Just pos)
-          Nothing -> (view (currentCanvasInfo . unboxLens currentPageNum) xst,Nothing)
+          Nothing -> (view (currentCanvasInfo . unboxLens currentPageNum) uhdl,Nothing)
         (ulx,uly) = (bbox_upperleft.getBBox) ritm
         nitms = 
           case mpos of 
@@ -438,14 +415,15 @@
         oitms = view gitems lyr  
         ntpg = makePageSelectMode pg (oitms :- (Hitted nitms) :- Empty)  
     modeChange ToSelectMode 
-    nxst <- get 
-    let cache = view renderCache nxst
-    thdl <- case view hoodleModeState nxst of
-      SelectState thdl' -> return thdl'
-      _ -> (lift . EitherT . return . Left . Other) "insertItemAt"
-    nthdl <- liftIO $ updateTempHoodleSelectIO cache thdl ntpg pgnum 
-    put ( ( set hoodleModeState (SelectState nthdl) 
-          . set isOneTimeSelectMode YesAfterSelect) nxst)
+    updateUhdl $ \uhdl' -> do 
+      thdl <- case view hoodleModeState uhdl' of
+        SelectState thdl' -> return thdl'
+        _ -> (lift . EitherT . return . Left . Other) "insertItemAt"
+      nthdl <- updateTempHoodleSelectM cid thdl ntpg pgnum 
+      return . (hoodleModeState .~ SelectState nthdl)
+             . (isOneTimeSelectMode .~ YesAfterSelect) $ uhdl' 
+    commit_
+    canvasZoomUpdateAll
     invalidateAll  
 
 embedTextSource :: MainCoroutine ()
@@ -453,53 +431,59 @@
     mfilename <- fileChooser Gtk.FileChooserActionOpen Nothing
     forM_ mfilename $ \filename -> do 
       txt <- liftIO $ TIO.readFile filename
-      xst <- get
-      let nhdlmodst = case xst ^. hoodleModeState of
-            ViewAppendState hdl -> (ViewAppendState . (gembeddedtext .~ Just txt) $ hdl)
-            SelectState thdl    -> (SelectState     . (gselEmbeddedText .~ Just txt) $ thdl)
-          nxst = (hoodleModeState .~ nhdlmodst) xst
-      put nxst
+      pureUpdateUhdl $ \uhdl ->
+        let nhdlmodst = case uhdl ^. hoodleModeState of
+              ViewAppendState hdl -> (ViewAppendState . (gembeddedtext .~ Just txt) $ hdl)
+              SelectState thdl    -> (SelectState     . (gselEmbeddedText .~ Just txt) $ thdl)
+        in (hoodleModeState .~ nhdlmodst) uhdl
       commit_ 
 
 -- |
 editEmbeddedTextSource :: MainCoroutine ()
 editEmbeddedTextSource = do 
-    hdl <- getHoodle <$> get
+    hdl <- getHoodle . view (unitHoodles.currentUnit) <$> get
     let mtxt = hdl ^. gembeddedtext 
     forM_ mtxt $ \txt -> do 
-      modify (tempQueue %~ enqueue (multiLineDialog txt))  
+      doIOaction (multiLineDialog txt)
       multiLineLoop txt >>= \case 
         Nothing -> return ()
         Just ntxt -> do 
-          modify $ \xst ->
-            let nhdlmodst = case xst ^. hoodleModeState of
-                  ViewAppendState hdl -> (ViewAppendState . (gembeddedtext .~ Just ntxt) $ hdl)
+          pureUpdateUhdl $ \uhdl ->
+            let nhdlmodst = case uhdl ^. hoodleModeState of
+                  ViewAppendState hdl' -> (ViewAppendState . (gembeddedtext .~ Just ntxt) $ hdl')
                   SelectState thdl    -> (SelectState     . (gselEmbeddedText .~ Just ntxt) $ thdl)
-            in (hoodleModeState .~ nhdlmodst) xst
+            in (hoodleModeState .~ nhdlmodst) uhdl
           commit_
 
+
 -- |
+#ifdef HUB
 editNetEmbeddedTextSource :: MainCoroutine ()
 editNetEmbeddedTextSource = do 
-    hdl <- getHoodle <$> get
+    hdl <- getHoodle . view (unitHoodles.currentUnit) <$> get
     let mtxt = hdl ^. gembeddedtext 
     forM_ mtxt $ \txt -> do 
-      -- modify (tempQueue %~ enqueue (multiLineDialog txt))  
       networkTextInput txt >>= \case 
         Nothing -> return ()
-        Just ntxt -> do 
-          modify $ \xst ->
-            let nhdlmodst = case xst ^. hoodleModeState of
-                  ViewAppendState hdl -> (ViewAppendState . (gembeddedtext .~ Just ntxt) $ hdl)
-                  SelectState thdl    -> (SelectState     . (gselEmbeddedText .~ Just ntxt) $ thdl)
-            in (hoodleModeState .~ nhdlmodst) xst
-          commit_
+        Just ntxt -> networkReceived ntxt
+#endif
 
+#ifdef HUB
+networkReceived :: T.Text -> MainCoroutine ()
+networkReceived txt = do
+    pureUpdateUhdl $ \uhdl -> 
+      let nhdlmodst = case uhdl ^. hoodleModeState of
+            ViewAppendState hdl -> (ViewAppendState . (gembeddedtext .~ Just txt) $ hdl)
+            SelectState thdl    -> (SelectState     . (gselEmbeddedText .~ Just txt) $ thdl)
+      in (hoodleModeState .~ nhdlmodst) uhdl
+    commit_
+#endif
+
 -- | insert text 
 textInputFromSource :: (Double,Double) -> MainCoroutine ()
 textInputFromSource (x0,y0) = do
     runMaybeT $ do 
-      txtsrc <- MaybeT $ (^. gembeddedtext) . getHoodle <$> get
+      txtsrc <- MaybeT $ (^. gembeddedtext) . getHoodle . view (unitHoodles.currentUnit) <$> get
       lift $ modify (tempQueue %~ enqueue linePosDialog)  
       (l1,l2) <- MaybeT linePosLoop
       let txt = getLinesFromText (l1,l2) txtsrc
@@ -510,23 +494,29 @@
 
 -- | common dialog with line position 
 linePosDialog :: Either (ActionOrder AllEvent) AllEvent
-linePosDialog = mkIOaction $ \evhandler -> do
+linePosDialog = mkIOaction $ \_evhandler -> do
     dialog <- Gtk.dialogNew
+#ifdef GTK3
+    upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)
+    vbox <- Gtk.vBoxNew False 0 
+    Gtk.containerAdd upper vbox
+#else 
     vbox <- Gtk.dialogGetUpper dialog
+#endif
 
     hbox <- Gtk.hBoxNew False 0
     Gtk.boxPackStart vbox hbox Gtk.PackNatural 0
 
-    line1buf <- Gtk.entryBufferNew Nothing
+    line1buf <- Gtk.entryBufferNew (Nothing :: Maybe String)
     line1 <- Gtk.entryNewWithBuffer line1buf
     Gtk.boxPackStart hbox line1 Gtk.PackNatural 2
 
-    line2buf <- Gtk.entryBufferNew Nothing
+    line2buf <- Gtk.entryBufferNew (Nothing :: Maybe String)
     line2 <- Gtk.entryNewWithBuffer line2buf
     Gtk.boxPackStart hbox line2 Gtk.PackNatural 2
     -- 
-    _btnOk <- Gtk.dialogAddButton dialog "Ok" Gtk.ResponseOk
-    _btnCancel <- Gtk.dialogAddButton dialog "Cancel" Gtk.ResponseCancel
+    _btnOk <- Gtk.dialogAddButton dialog ("Ok" :: String) Gtk.ResponseOk
+    _btnCancel <- Gtk.dialogAddButton dialog ("Cancel" :: String) Gtk.ResponseCancel
     Gtk.widgetShowAll dialog
     res <- Gtk.dialogRun dialog
     Gtk.widgetDestroy dialog
@@ -551,57 +541,59 @@
       _ -> linePosLoop
 
 -- | insert text 
-laTeXInputKeyword :: (Double,Double) -> T.Text -> MaybeT MainCoroutine ()
-laTeXInputKeyword (x0,y0) keyword = do
-    txtsrc <- MaybeT $ (^. gembeddedtext) . getHoodle <$> get
+laTeXInputKeyword :: (Double,Double) -> Maybe Dimension -> T.Text 
+                  -> MaybeT MainCoroutine ()
+laTeXInputKeyword (x0,y0) mdim keyword = do
+    txtsrc <- MaybeT $ (^. gembeddedtext) . getHoodle . view (unitHoodles.currentUnit) <$> get
     subpart <- (MaybeT . return . M.lookup keyword . getKeywordMap) txtsrc
     let subpart' = laTeXHeader <> "\n"  <> subpart <> laTeXFooter
-    liftIO (makeLaTeXSVG (x0,y0) subpart') >>= \case
+    liftIO (makeLaTeXSVG (x0,y0) mdim subpart') >>= \case
       Right r  -> lift $ do 
                     deleteSelection 
                     svgInsert ("embedlatex:keyword:"<>keyword,"latex") r
       Left err -> lift $ do
-                    okMessageBox err
+                    longTextMessageBox err
+                    -- okMessageBox err
                     return ()
 
--- | insert text 
+-- | 
 laTeXInputFromSource :: (Double,Double) -> MainCoroutine ()
 laTeXInputFromSource (x0,y0) = do
     runMaybeT $ do 
-      txtsrc <- MaybeT $ (^. gembeddedtext) . getHoodle <$> get
-      lift $ modify (tempQueue %~ enqueue keywordDialog)  
-      keyword <- MaybeT keywordLoop
-      laTeXInputKeyword (x0,y0) keyword
+      txtsrc <- MaybeT $ (^. gembeddedtext) . getHoodle . view (unitHoodles.currentUnit) <$> get
+      let keylst = (map fst . M.toList . getKeywordMap) txtsrc
+      when ((not.null) keylst) $ do 
+        keyword <- MaybeT (keywordDialog keylst)
+        laTeXInputKeyword (x0,y0) Nothing keyword
     return ()
-
--- | common dialog with line position 
-keywordDialog :: Either (ActionOrder AllEvent) AllEvent
-keywordDialog = mkIOaction $ \evhandler -> do
-    dialog <- Gtk.dialogNew
-    vbox <- Gtk.dialogGetUpper dialog
-    hbox <- Gtk.hBoxNew False 0
-    Gtk.boxPackStart vbox hbox Gtk.PackNatural 0
-    keybuf <- Gtk.entryBufferNew Nothing
-    key <- Gtk.entryNewWithBuffer keybuf
-    Gtk.boxPackStart hbox key Gtk.PackNatural 2
-    -- 
-    _btnOk <- Gtk.dialogAddButton dialog "Ok" Gtk.ResponseOk
-    _btnCancel <- Gtk.dialogAddButton dialog "Cancel" Gtk.ResponseCancel
-    Gtk.widgetShowAll dialog
-    res <- Gtk.dialogRun dialog
-    Gtk.widgetDestroy dialog
-    case res of 
-      Gtk.ResponseOk -> do
-        keystr <- T.pack <$> Gtk.get keybuf Gtk.entryBufferText
-        (return . UsrEv . Keyword . Just) keystr
-      Gtk.ResponseCancel -> return (UsrEv (Keyword Nothing))
-      _ -> return (UsrEv (Keyword Nothing))
+    
+-- | 
+#ifdef HUB
+toggleNetworkEditSource :: MainCoroutine ()
+toggleNetworkEditSource = do 
+    xst <- get
+    let uhdl = view (unitHoodles.currentUnit) xst
+        hdl = getHoodle uhdl
+        mtxt = hdl ^. gembeddedtext
+    b <- updateFlagFromToggleUI "TOGGLENETSRCA" (settings.doesUseXInput)
+    forM_ (xst ^. statusBar) $ \stbar -> 
+      if b 
+        then do
+          (ip,tid,_done) <- networkTextInputBody (maybe " " id mtxt)
+          doIOaction_ $ do
+            let msg = ("networkedit " ++ ip ++ " 4040")
+            ctxt <- Gtk.statusbarGetContextId stbar ("networkedit" :: String)
+            Gtk.statusbarPush stbar ctxt msg
+          (put . ((settings.networkEditSourceInfo) .~ (Just tid))) xst
+        else do
+          case xst ^. (settings.networkEditSourceInfo) of
+            Nothing -> return ()
+            Just tid -> do
+              doIOaction_ $ do
+                killThread tid
+                ctxt <- Gtk.statusbarGetContextId stbar ("networkedit" :: String)
+                Gtk.statusbarPush stbar ctxt ("Now no networkedit" :: String)
+              (put . ((settings.networkEditSourceInfo) .~ Nothing)) xst
+#endif
+      
 
--- | main event loop for line position dialog
-keywordLoop :: MainCoroutine (Maybe T.Text)
-keywordLoop = do 
-    r <- nextevent
-    case r of 
-      UpdateCanvas cid -> invalidateInBBox Nothing Efficient cid >> keywordLoop
-      Keyword x -> return x
-      _ -> keywordLoop
diff --git a/src/Hoodle/Coroutine/VerticalSpace.hs b/src/Hoodle/Coroutine/VerticalSpace.hs
--- a/src/Hoodle/Coroutine/VerticalSpace.hs
+++ b/src/Hoodle/Coroutine/VerticalSpace.hs
@@ -1,9 +1,11 @@
+{-# LANGUAGE CPP #-}
+
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.VerticalSpace
--- Copyright   : (c) 2013, 2014 Ian-Woo Kim
+-- Copyright   : (c) 2013-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -14,7 +16,7 @@
 
 import           Control.Applicative
 import           Control.Category
-import           Control.Lens (view,set,at)
+import           Control.Lens (view,set,at,(.~))
 import           Control.Monad hiding (mapM_)
 import           Control.Monad.State (get)
 import           Control.Monad.Trans (liftIO)
@@ -22,16 +24,15 @@
 import           Data.Monoid
 import           Data.Time.Clock
 import qualified Graphics.Rendering.Cairo as Cairo
-import           Graphics.UI.Gtk hiding (get,set) 
+import qualified Graphics.UI.Gtk as Gtk
 -- from hoodle-platform
 import           Data.Hoodle.BBox
 import           Data.Hoodle.Generic
 import           Data.Hoodle.Simple (Dimension(..))
 import           Data.Hoodle.Zipper (SeqZipper,toSeq) 
 import           Graphics.Hoodle.Render
+import           Graphics.Hoodle.Render.Type
 import           Graphics.Hoodle.Render.Type.HitTest
-import           Graphics.Hoodle.Render.Type.Hoodle
-import           Graphics.Hoodle.Render.Type.Item 
 import           Graphics.Hoodle.Render.Util.HitTest
 -- from this package
 import           Hoodle.Accessor
@@ -52,6 +53,7 @@
 import           Hoodle.Type.Predefined 
 import           Hoodle.View.Coordinate
 import           Hoodle.View.Draw
+import           Hoodle.Util
 --
 import Prelude hiding ((.), id, concat,concatMap,mapM_)
 
@@ -73,12 +75,12 @@
     bboxabove (BBox (_,y0) _) = y0 > y 
 
 -- |
-verticalSpaceStart :: CanvasId -> PointerCoord -> MainCoroutine () 
-verticalSpaceStart cid = commonPenStart verticalSpaceAction cid  
+verticalSpaceStart :: CanvasId -> PointerCoord -> MainCoroutine ()
+verticalSpaceStart cid = commonPenStart verticalSpaceAction cid >=> const (return ())
   where 
-    verticalSpaceAction _cinfo pnum@(PageNum n) geometry (x,y) = do 
-      hdl <- liftM getHoodle get 
-      cache <- view renderCache <$> get
+    verticalSpaceAction _cinfo pnum@(PageNum n) geometry (x,y) _ = do 
+      hdl <- getHoodle . view (unitHoodles.currentUnit) <$> get 
+      cache <- renderCache
       cpg <- getCurrentPageCurr 
       let (itms,npg,hltedLayers) = splitPageByHLine y cpg 
           nhdl = set (gpages.at n) (Just npg) hdl 
@@ -86,7 +88,7 @@
       case mbbx of
         Nothing -> return ()   
         Just bbx -> do 
-          (sfcbkg,Dim w h) <- liftIO $ canvasImageSurface cache Nothing geometry nhdl 
+          (sfcbkg,Dim w h) <- liftIO $ canvasImageSurface cache cid Nothing geometry nhdl 
           sfcitm <- liftIO $ Cairo.createImageSurface 
                                Cairo.FormatARGB32 (floor w) (floor h)
           sfctot <- liftIO $ Cairo.createImageSurface 
@@ -94,7 +96,7 @@
           liftIO $ Cairo.renderWith sfcitm $ do 
             Cairo.identityMatrix 
             cairoXform4PageCoordinate (mkXform4Page geometry pnum)
-            mapM_ (renderRItem cache) itms
+            mapM_ (renderRItem cache cid) itms
           ctime <- liftIO getCurrentTime 
           verticalSpaceProcess cid geometry (bbx,hltedLayers,pnum,cpg) (x,y) 
             (sfcbkg,sfcitm,sfctot) ctime 
@@ -103,31 +105,30 @@
 -- |
 addNewPageAndMoveBelow :: (PageNum,SeqZipper RItemHitted,BBox) 
                           -> MainCoroutine () 
-addNewPageAndMoveBelow (pnum,hltedLyrs,bbx) = 
-    updateXState npgBfrAct 
-    >> commit_ 
-    >> canvasZoomUpdateAll >> invalidateAll
+addNewPageAndMoveBelow (pnum,hltedLyrs,bbx) = do
+    bsty <- view backgroundStyle <$> get
+    updateUhdl (npgact bsty) >> commit_  >> canvasZoomUpdateAll >> invalidateAll
   where
-    npgBfrAct xst = forBoth' unboxBiAct (fsimple xst) . view currentCanvasInfo $ xst
-    fsimple :: HoodleState -> CanvasInfo a -> MainCoroutine HoodleState
-    fsimple xstate _cinfo = do 
-      case view hoodleModeState xstate of 
+    npgact :: BackgroundStyle -> UnitHoodle -> MainCoroutine UnitHoodle
+    npgact bsty uhdl = do 
+      case view hoodleModeState uhdl of 
         ViewAppendState hdl -> do 
-          let bsty = view backgroundStyle xstate 
-          hdl' <- addNewPageInHoodle bsty PageAfter hdl (unPageNum pnum)
-          let hdl'' = moveBelowToNewPage (pnum,hltedLyrs,bbx) hdl' 
-              nhdlmodst = ViewAppendState hdl''
-          return =<< liftIO . updatePageAll nhdlmodst
-                     . set hoodleModeState nhdlmodst $ xstate 
+          hdl' <- addNewPageInHoodle Nothing bsty PageAfter hdl (unPageNum pnum)
+          sfcid <- issueSurfaceID
+          sfcid2 <- issueSurfaceID
+          let nhdlmodst = ViewAppendState (moveBelowToNewPage (sfcid,sfcid2) (pnum,hltedLyrs,bbx) hdl') 
+          liftIO . updatePageAll nhdlmodst . (hoodleModeState .~ nhdlmodst) $ uhdl
         SelectState _ -> do 
-          liftIO $ putStrLn " not implemented yet"
-          return xstate
+          msgShout "addNewPageAndMoveBelow: not implemented yet"
+          return uhdl
             
 -- |             
-moveBelowToNewPage :: (PageNum,SeqZipper RItemHitted,BBox) 
-                      -> Hoodle EditMode
-                      -> Hoodle EditMode
-moveBelowToNewPage (PageNum n,hltedLayers,BBox (_,y0) _) hdl = 
+moveBelowToNewPage :: (SurfaceID,SurfaceID)   
+                      -- ^ sfcid: old page, sfcid2: new page
+                   -> (PageNum,SeqZipper RItemHitted,BBox) 
+                   -> Hoodle EditMode
+                   -> Hoodle EditMode
+moveBelowToNewPage (sfcid,sfcid2) (PageNum n,hltedLayers,BBox (_,y0) _) hdl = 
     let mpg = view (gpages.at n) hdl 
         mpg2 = view (gpages.at (n+1)) hdl 
     in case (,) <$> mpg <*> mpg2 of    
@@ -137,15 +138,14 @@
               fmap (fmapAL id 
                      (fmap (changeItemBy (\(x',y')->(x',y'+10-y0)))))
                    hltedLayers
-            nlyrs = fmap ((\x -> set gitems x emptyRLayer) 
+            nlyrs = fmap ((\x -> set gitems x (emptyRLayer sfcid)) 
                           . concatMap unNotHitted 
                           . getA ) nhlyrs 
             npg = set glayers nlyrs pg 
-            nnlyrs = fmap ((\x -> set gitems x emptyRLayer)
+            nnlyrs = fmap ((\x -> set gitems x (emptyRLayer sfcid2))
                           . concatMap unHitted
                           . getB ) nhlyrs
             npg2 = set glayers nnlyrs pg2
-            
             nhdl = ( set (gpages.at (n+1)) (Just npg2)
                    . set (gpages.at n) (Just npg) ) hdl 
         in nhdl 
@@ -163,18 +163,15 @@
 verticalSpaceProcess cid geometry pinfo@(bbx,hltedLayers,pnum@(PageNum n),pg) 
                      (x0,y0) sfcs@(sfcbkg,sfcitm,sfctot) otime = do 
     r <- nextevent 
-    xst <- get
-    forBoth' unboxBiAct (f r xst) . getCanvasInfo cid $ xst 
+    uhdl <- view (unitHoodles.currentUnit) <$> get
+    forBoth' unboxBiAct (f r) . getCanvasInfo cid $ uhdl
   where 
     Dim w h = view gdimension pg    
     CvsCoord (_,y0_cvs) = (desktop2Canvas geometry . page2Desktop geometry) (pnum,PageCoord (x0,y0))
     -------------------------------------------------------------
-    f :: UserEvent -> HoodleState -> CanvasInfo a -> MainCoroutine ()
-    f r xstate cvsInfo = penMoveAndUpOnly r pnum geometry defact 
-                           (moveact xstate cvsInfo) upact
-    -------------------------------------------------------------  
+    f :: UserEvent -> CanvasInfo a -> MainCoroutine ()
+    f r cvsInfo = penMoveAndUpOnly r pnum geometry defact (moveact cvsInfo) upact
     defact = verticalSpaceProcess cid geometry pinfo (x0,y0) sfcs otime
-    -------------------------------------------------------------    
     upact pcoord = do 
       let mpgcoord = (desktop2Page geometry . device2Desktop geometry) pcoord
       case mpgcoord of 
@@ -187,25 +184,24 @@
             let BBox _ (_,by1) = bbx
             if by1 + y - y0 < h 
               then do 
-                xst <- get 
-                let hdl = getHoodle xst 
-                let nhlyrs = 
-                      fmap (fmapAL id 
-                            (fmap (changeItemBy (\(x',y')->(x',y'+y-y0)))))
-                                  hltedLayers
-                    nlyrs = fmap 
-                              ((\is -> set gitems is emptyRLayer) 
-                                      . concat
-                                      . interleave unNotHitted unHitted) 
-                              nhlyrs 
-                    npg = set glayers nlyrs pg 
-                    nhdl = set (gpages.at n) (Just npg) hdl 
-                commit (set hoodleModeState (ViewAppendState nhdl) xst)
+                sfcid <- issueSurfaceID
+                pureUpdateUhdl $ \uhdl -> do
+                  let hdl = getHoodle uhdl
+                      nhlyrs = fmap (fmapAL id (fmap (changeItemBy (\(x',y')->(x',y'+y-y0))))) hltedLayers
+                      nlyrs = fmap ( (\is -> set gitems is (emptyRLayer sfcid)) 
+                                     . concat . interleave unNotHitted unHitted ) 
+                                nhlyrs 
+                      npg = set glayers nlyrs pg 
+                      nhdl = set (gpages.at n) (Just npg) hdl 
+                      nhdlmodst = ViewAppendState nhdl
+                      nuhdl = (hoodleModeState .~ nhdlmodst) uhdl
+                   in nuhdl
+                commit_
+                canvasZoomUpdateAll
                 invalidateAll 
-              else do 
-                addNewPageAndMoveBelow (pnum,hltedLayers,bbx)
+              else addNewPageAndMoveBelow (pnum,hltedLayers,bbx)
     -------------------------------------------------------------
-    moveact _xstate cvsInfo (_,(x,y)) = 
+    moveact cvsInfo (_,(x,y)) = 
       processWithDefTimeInterval 
         (verticalSpaceProcess cid geometry pinfo (x0,y0) sfcs)
         (\ctime -> do 
@@ -247,8 +243,16 @@
              Cairo.paint
              drawguide 
            let canvas = view drawArea cvsInfo 
-           win <- liftIO $ widgetGetDrawWindow canvas
-           liftIO $ renderWithDrawable win $ do 
+#ifdef GTK3
+           Just win <- liftIO $ Gtk.widgetGetWindow canvas
+#else 
+           win <- liftIO $ Gtk.widgetGetDrawWindow canvas
+#endif
+#ifdef GTK3
+           liftIO $ Gtk.renderWithDrawWindow win $ do 
+#else 
+           liftIO $ Gtk.renderWithDrawable win $ do 
+#endif
              Cairo.setSourceSurface sfctot 0 0 
              Cairo.setOperator Cairo.OperatorSource 
              Cairo.paint 
diff --git a/src/Hoodle/Coroutine/Window.hs b/src/Hoodle/Coroutine/Window.hs
--- a/src/Hoodle/Coroutine/Window.hs
+++ b/src/Hoodle/Coroutine/Window.hs
@@ -1,11 +1,13 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Coroutine.Window 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -14,16 +16,21 @@
 
 module Hoodle.Coroutine.Window where
 
-import           Control.Lens (view,set,over)
+import           Control.Applicative
+import           Control.Lens (view,set,over,(^.),(.~),_2)
 import           Control.Monad.State 
 import qualified Data.IntMap as M
-import           Graphics.UI.Gtk hiding (get,set)
+import qualified Data.List as L
+import           Data.UUID (UUID)
+import qualified Graphics.UI.Gtk as Gtk
 --
 import           Data.Hoodle.Generic
 import           Data.Hoodle.Simple (Dimension(..))
 --
 import           Hoodle.Accessor
 import           Hoodle.Coroutine.Draw
+import           Hoodle.Coroutine.File
+import           Hoodle.Coroutine.Mode
 import           Hoodle.Coroutine.Page
 import           Hoodle.GUI.Reflect
 import           Hoodle.ModelAction.Page
@@ -34,7 +41,9 @@
 import           Hoodle.Type.Event
 import           Hoodle.Type.HoodleState
 import           Hoodle.Type.PageArrangement
+import           Hoodle.Type.Undo
 import           Hoodle.Type.Window
+import           Hoodle.Util
 --
 
 -- | canvas configure with general zoom update func
@@ -43,17 +52,15 @@
                             -> CanvasDimension 
                             -> MainCoroutine () 
 canvasConfigureGenUpdate updatefunc cid cdim 
-  = updateXState (unboxBiAct fsingle fcont . getCanvasInfo cid ) >> updatefunc 
-  where fsingle cinfo = do 
-          xstate <- get 
+  = updateUhdl (\uhdl -> unboxBiAct (fsingle uhdl) (fcont uhdl) (getCanvasInfo cid uhdl)) >> updatefunc 
+  where fsingle uhdl cinfo = do 
           cinfo' <- liftIO $ updateCanvasDimForSingle cdim cinfo 
-          return $ setCanvasInfo (cid,CanvasSinglePage cinfo') xstate
-        fcont cinfo = do 
-          xstate <- get
+          return $ setCanvasInfo (cid,CanvasSinglePage cinfo') uhdl
+        fcont uhdl cinfo = do 
           page <- getCurrentPageCvsId cid
           let pdim = PageDimension (view gdimension page)
           cinfo' <- liftIO $ updateCanvasDimForContSingle pdim cdim cinfo 
-          return $ setCanvasInfo (cid,CanvasContPage cinfo') xstate 
+          return $ setCanvasInfo (cid,CanvasContPage cinfo') uhdl 
   
 -- | 
 doCanvasConfigure :: CanvasId -> CanvasDimension -> MainCoroutine () 
@@ -62,42 +69,40 @@
 -- | 
 eitherSplit :: SplitType -> MainCoroutine () 
 eitherSplit stype = do
-    xstate <- get
-    let cmap = getCanvasInfoMap xstate
-        currcid = getCurrentCanvasId xstate
+    xst <- get
+    let uhdl = view (unitHoodles.currentUnit) xst
+    let cmap = view cvsInfoMap uhdl
+        currcid = getCurrentCanvasId uhdl
         newcid = newCanvasId cmap 
-        fstate = view frameState xstate
+        fstate = view frameState uhdl
         enewfstate = splitWindow currcid (newcid,stype) fstate 
     case enewfstate of 
       Left _ -> return ()
       Right fstate' -> do 
         cinfobox <- maybeError "eitherSplit" . M.lookup currcid $ cmap 
-        let rtwin = view rootWindow xstate
-            rtcntr = view rootContainer xstate 
-            rtrwin = view rootOfRootWindow xstate 
-        liftIO $ containerRemove rtcntr rtwin
-        (xstate'',win,fstate'') <- 
-          liftIO $ constructFrame' cinfobox xstate fstate'
-        let xstate3 = set frameState fstate'' 
-                      . set rootWindow win 
-                      $ xstate''
-        put xstate3 
-        liftIO $ boxPackEnd rtcntr win PackGrow 0 
-        liftIO $ widgetShowAll rtcntr  
-        liftIO $ widgetQueueDraw rtrwin
-        (xstate4,_wconf) <- liftIO $ eventConnect xstate3 (view frameState xstate3)
-        xstate5 <- liftIO $ updatePageAll (view hoodleModeState xstate4) xstate4
-        put xstate5 
+        let callback = view callBack xst
+            rtwin = view rootWindow uhdl
+            rtcntr = view rootContainer uhdl
+            rtrwin = view rootOfRootWindow xst 
+        liftIO $ Gtk.containerRemove rtcntr rtwin
+        (uhdl',win,fstate'') <- liftIO $ constructFrame' callback cinfobox uhdl fstate'
+        let uhdl'' = ((frameState .~ fstate'') . (rootWindow .~ win)) uhdl'
+        let xst3 = (unitHoodles.currentUnit .~ uhdl'') xst
+        put xst3 
+        liftIO $ registerFrameToContainer rtrwin rtcntr win
+        (uhdl3,_wconf) <- liftIO $ eventConnect xst3 uhdl'' (view frameState uhdl'')
+        updateUhdl $ const (liftIO $ updatePageAll (view hoodleModeState uhdl3) uhdl3)
         canvasZoomUpdateAll
         invalidateAll 
 
 -- | 
 deleteCanvas :: MainCoroutine () 
 deleteCanvas = do 
-    xstate <- get
-    let cmap = getCanvasInfoMap xstate
-        currcid = getCurrentCanvasId xstate
-        fstate = view frameState xstate
+    xst <- get
+    let uhdl = view (unitHoodles.currentUnit) xst
+        cmap = view cvsInfoMap uhdl
+        currcid = getCurrentCanvasId uhdl
+        fstate = view frameState uhdl
         enewfstate = removeWindow currcid fstate 
     case enewfstate of 
       Left _ -> return ()
@@ -105,25 +110,23 @@
       Right (Just fstate') -> do 
         let cmap' = M.delete currcid cmap
             newcurrcid = maximum (M.keys cmap')
-        xstate0 <- changeCurrentCanvasId newcurrcid 
-        let xstate1 = maybe xstate0 id $ setCanvasInfoMap cmap' xstate0
-        put xstate1
-        let rtwin = view rootWindow xstate1
-            rtcntr = view rootContainer xstate1 
-            rtrwin = view rootOfRootWindow xstate1 
-        liftIO $ containerRemove rtcntr rtwin
-        (xstate'',win,fstate'') <- liftIO $ constructFrame xstate1 fstate'
-        let xstate3 = set frameState fstate'' 
-                      . set rootWindow win 
-                      $ xstate''
-        put xstate3
-        liftIO $ boxPackEnd rtcntr win PackGrow 0 
-        liftIO $ widgetShowAll rtcntr  
-        liftIO $ widgetQueueDraw rtrwin
-        (xstate4,_wconf) <- liftIO $ eventConnect xstate3 (view frameState xstate3)
+        updateUhdl $ \_uhdl -> do
+          uhdl' <- changeCurrentCanvasId newcurrcid 
+          maybe (return uhdl') return $ setCanvasInfoMap cmap' uhdl'
+        xst1 <- get
+        let uhdl1 = view (unitHoodles.currentUnit) xst1
+        let rtwin = view rootWindow uhdl1
+            rtcntr = view rootContainer uhdl1 
+            rtrwin = view rootOfRootWindow xst1 
+        liftIO $ Gtk.containerRemove rtcntr rtwin
+        (uhdl2,win,fstate'') <- liftIO $ constructFrame xst1 uhdl1 fstate'
+        pureUpdateUhdl (const (((frameState .~ fstate'') . (rootWindow .~ win)) uhdl2))
+        xst3 <- get
+        liftIO $ registerFrameToContainer rtrwin rtcntr win
+        updateUhdl $ \uhdl' -> do
+          (uhdl'',_wconf) <- liftIO $ eventConnect xst3 uhdl' (view frameState uhdl')
+          liftIO $ updatePageAll (view hoodleModeState uhdl'') uhdl''
         canvasZoomUpdateAll
-        xstate5 <- liftIO $ updatePageAll (view hoodleModeState xstate4) xstate4
-        put xstate5 
         invalidateAll 
 
             
@@ -133,35 +136,116 @@
     ev <- nextevent 
     case ev of 
       UpdateCanvas cid -> invalidateInBBox Nothing Efficient cid >> paneMoveStart 
-      PaneMoveEnd -> do 
-        return () 
-      CanvasConfigure cid w' h'-> do 
-        canvasConfigureGenUpdate canvasZoomUpdateBufAll cid (CanvasDimension (Dim w' h')) 
-        >> paneMoveStart
+      PaneMoveEnd -> return () 
+      CanvasConfigure cid w' h'->
+        canvasConfigureGenUpdate canvasZoomUpdateBufAll cid (CanvasDimension (Dim w' h')) >> paneMoveStart
       _ -> paneMoveStart
        
-
 -- | not yet implemented?
 paneMoved :: MainCoroutine () 
-paneMoved = do 
-    liftIO $ putStrLn "pane moved called"
+paneMoved = msgShout "paneMoved: not implemented"
     
--- |
+-- | start full screen mode
 fullScreen :: MainCoroutine ()
 fullScreen = do 
     xst <- get 
-    let b = view isFullScreen xst
-        rwin = view rootOfRootWindow xst 
-    if b 
-      then do 
-        liftIO $ windowUnfullscreen rwin
-        modify (over isFullScreen (const False))
-      else do 
-        liftIO $ windowFullscreen rwin 
-        modify (over isFullScreen (const True))
+    let rwin = view rootOfRootWindow xst 
+    if view isFullScreen xst 
+      then liftIO (Gtk.windowUnfullscreen rwin) >> modify (over isFullScreen (const False))
+      else liftIO (Gtk.windowFullscreen rwin) >> modify (over isFullScreen (const True))
 
-           
-    
-  
-  
+-- |
+addTab :: FileStore -> MainCoroutine ()
+addTab filestore = do
+    xst <- get
+    let notebook = xst ^. rootNotebook
+        callback = xst ^. callBack
+        btnold = xst ^. (unitHoodles.currentUnit.unitButton)
+    liftIO $ Gtk.widgetSetSensitive btnold False
+    vboxcvs <- liftIO $ Gtk.vBoxNew False 0
+    (tabnum,uuid,btn) <- liftIO $ createTab callback notebook vboxcvs
+    let wconf = Node 1
+        initcvs = defaultCvsInfoSinglePage { _canvasId = 1 }
+        initcvsbox = CanvasSinglePage initcvs
+        -- mfp = fileStore2Maybe filestore
+    uhdl' <- (undoTable .~ emptyUndo 50)   -- (undo = 50 for the time being) 
+             . (frameState .~ wconf) 
+             . updateFromCanvasInfoAsCurrentCanvas initcvsbox
+             . (cvsInfoMap .~ M.empty)
+             . (isSaved .~ True)
+             . (hoodleFileControl.hoodleFileName .~ filestore) 
+             . (unitKey .~ tabnum) 
+             . (unitUUID .~ uuid) 
+             . (unitButton .~ btn)
+             <$> liftIO emptyUnitHoodle
+    modify . set (unitHoodles.currentUnit) =<< (liftIO $ do
+      (uhdl'',wdgt,_) <- constructFrame xst uhdl' wconf
+      let uhdl3 = (rootWindow .~ wdgt) . (rootContainer .~ Gtk.castToBox vboxcvs) $ uhdl''
+      (uhdl4,_wconf) <- eventConnect xst uhdl3 (view frameState uhdl3)
+      registerFrameToContainer (xst^.rootOfRootWindow) (Gtk.castToBox vboxcvs) wdgt
+      Gtk.widgetShowAll notebook
+      return uhdl4)
 
+    doIOaction_ $ 
+      blockWhile (view (uiComponentSignalHandler.switchTabSignal) xst) $
+        Gtk.set notebook [Gtk.notebookPage Gtk.:= tabnum]
+    getFileContent filestore
+    updateUhdl $ \uhdl -> do
+      liftIO (updatePageAll (view hoodleModeState uhdl) uhdl)
+      unboxBiAct (sing2ContPage uhdl) (const (return uhdl)) . view currentCanvasInfo $ uhdl
+    pageZoomChange FitWidth
+    canvasZoomUpdateAll
+    invalidateAll 
+    reflectCursor True
+
+-- | 
+findTab :: UUID -> MainCoroutine (Maybe Int)
+findTab uuid = do
+    uhdlmap <- view (unitHoodles._2) <$> get
+    let assoc = (map (\x -> (view unitUUID x,view unitKey x)) . M.elems) uhdlmap
+    return (L.lookup uuid assoc)
+
+-- |
+switchTab :: Int -> MainCoroutine ()
+switchTab tabnum = do
+    xst <- get
+    let notebook = view rootNotebook xst
+    doIOaction_ $ Gtk.set notebook [Gtk.notebookPage Gtk.:= tabnum ]
+    uhdls <- view unitHoodles <$> get
+
+    let current = fst uhdls
+    when (tabnum /= current) $ do 
+      let uhdl = fromJustError "switchTab"  (M.lookup tabnum (snd uhdls))
+      liftIO $ Gtk.widgetSetSensitive (uhdls^.(currentUnit.unitButton)) False
+      liftIO $ Gtk.widgetSetSensitive (uhdl^.unitButton) True
+      modify $ (unitHoodles.currentUnit .~ uhdl)
+      updateUhdl $ \uhdl' -> liftIO (updatePageAll (view hoodleModeState uhdl') uhdl')
+#ifndef GTK3
+      view currentCanvasInfo uhdl # 
+        forBoth' unboxBiAct $ \cinfo -> do
+          (w,h) <- liftIO $ Gtk.widgetGetSize (cinfo^.drawArea) 
+          doCanvasConfigure (cinfo^.canvasId) (CanvasDimension (Dim (fromIntegral w) (fromIntegral h)))
+#endif
+      invalidateAll 
+      liftIO $ reflectUIToggle (xst ^. gtkUIManager) "SAVEA" (not (uhdl ^. isSaved))
+      reflectPenModeUI
+      reflectCursor True
+
+-- |
+closeTab :: MainCoroutine ()
+closeTab = do 
+  xst <- get
+  let (currk,uhdlmap) = xst ^. unitHoodles
+      uhdlmap' = M.delete currk uhdlmap 
+      uhdllst'' = (map (\(x,y)-> (x,(unitKey .~ x) y)) . zip [0..] . M.elems) uhdlmap'
+      uhdlmap'' = M.fromList uhdllst''
+      sz = M.size uhdlmap
+  if (sz > 1) 
+    then do
+      let notebook = xst ^. rootNotebook
+      doIOaction_ $ Gtk.notebookRemovePage notebook currk
+      modify $ (unitHoodles .~ (0,uhdlmap''))
+      canvasZoomUpdateAll
+      switchTab 0
+    else liftIO $ Gtk.mainQuit
+      
diff --git a/src/Hoodle/Device.hsc b/src/Hoodle/Device.hsc
--- a/src/Hoodle/Device.hsc
+++ b/src/Hoodle/Device.hsc
@@ -1,9 +1,11 @@
-{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables #-}
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Device 
--- Copyright   : (c) 2011-2013 Ian-Woo Kim
+-- Copyright   : (c) 2011-2014 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
@@ -72,12 +74,11 @@
   -> CString  -- ^ touch 
   -> IO ()
 
-
+{-
 -- | 
 foreign import ccall "c_initdevice.h find_wacom" c_find_wacom
   :: CString -> CString -> IO ()
-
-{- 
+ 
 -- | 
 foreign import ccall "c_initdevice.h enable_touch" c_enable_touch
   :: CString -> IO ()
@@ -97,9 +98,6 @@
   ptouchname_detect <- newCString "touch"
   -- c_find_wacom pstylusname_detect perasername_detect
   (mcore,mstylus,meraser,mtouch) <- getPenDevConfig cfg 
-  -- putStrLn $ show mstylus 
-  -- putStrLn $ show meraser
-  -- putStrLn $ show mtouch
   with 0 $ \pcore -> 
     with 0 $ \pstylus -> 
       with 0 $ \peraser -> do 
@@ -217,7 +215,11 @@
                      -> (Double,Double) 
                      -> IO (Double,Double)
 wacomCoordConvert canvas (x,y)= do 
+#ifdef GTK3  
+  Just win <- widgetGetWindow canvas -- partial function for the time being 
+#else // GTK3
   win <- widgetGetDrawWindow canvas
+#endif // GTK3
   (x0,y0) <- drawWindowGetOrigin win
   screen <- widgetGetScreen canvas
   (ws,hs) <- (,) <$> screenGetWidth screen <*> screenGetHeight screen
diff --git a/src/Hoodle/GUI.hs b/src/Hoodle/GUI.hs
--- a/src/Hoodle/GUI.hs
+++ b/src/Hoodle/GUI.hs
@@ -1,9 +1,11 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.GUI 
--- Copyright   : (c) 2011-2013 Ian-Woo Kim
+-- Copyright   : (c) 2011-2014 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
@@ -16,14 +18,14 @@
 
 import           Control.Concurrent (threadDelay, forkIO)
 import           Control.Exception (SomeException(..),catch)
-import           Control.Lens (view)
-import           Control.Monad hiding (mapM_)
+import           Control.Lens
+import           Control.Monad hiding (mapM_,forM_)
 import           Control.Monad.Trans 
-import           Data.Foldable (mapM_)
+import           Data.Foldable (mapM_,forM_)
 import qualified Data.IntMap as M
 import           Data.IORef
 import           Data.Maybe
-import           Graphics.UI.Gtk hiding (get,set)
+import qualified Graphics.UI.Gtk as Gtk
 import           System.Directory
 import           System.Environment
 import           System.FilePath
@@ -40,92 +42,99 @@
 import           Hoodle.Type.Event
 import           Hoodle.Type.HoodleState 
 --
-import           Prelude ((.),($),String,Bool(..),const,error,flip,id,map) 
+import           Prelude ((.),($),String,Bool(..),error,flip,id,map) 
 
 -- |
 startGUI :: Maybe FilePath -> Maybe Hook -> IO () 
 startGUI mfname mhook = do 
-  initGUI
-  window <- windowNew   
-  windowSetDefaultSize window 800 400
-  cfg <- loadConfigFile   
-  devlst <- initDevice cfg 
-  maxundo <- getMaxUndo cfg >>= 
-               \mmax -> maybe (return 50) (return . id) mmax
-  xinputbool <- getXInputConfig cfg 
-  (usepz,uselyr) <- getWidgetConfig cfg 
-  statusbar <- statusbarNew 
-  (tref,st0,ui,vbox) <- initCoroutine devlst window mhook maxundo (xinputbool,usepz,uselyr) statusbar 
-  setTitleFromFileName st0
-  -- need for refactoring
-  setToggleUIForFlag "UXINPUTA" (settings.doesUseXInput) st0 
-  setToggleUIForFlag "HANDA" (settings.doesUseTouch) st0   
-  setToggleUIForFlag "POPMENUA" (settings.doesUsePopUpMenu) st0 
-  setToggleUIForFlag "EBDIMGA" (settings.doesEmbedImage) st0 
-  setToggleUIForFlag "EBDPDFA" (settings.doesEmbedPDF) st0
-  -- 
-  let canvases = map (getDrawAreaFromBox) . M.elems . getCanvasInfoMap $ st0
-  if xinputbool
-      then mapM_ (flip widgetSetExtensionEvents [ExtensionEventsAll]) canvases
-      else mapM_ (flip widgetSetExtensionEvents [ExtensionEventsNone]) canvases
-  -- 
-  menubar <- uiManagerGetWidget ui "/ui/menubar" 
-             >>= maybe (error "GUI.hs:no menubar") return 
-  toolbar1 <- uiManagerGetWidget ui "/ui/toolbar1" 
-              >>= maybe (error "GUI.hs:no toolbar1") return 
-  toolbar2 <- uiManagerGetWidget ui "/ui/toolbar2"
-              >>= maybe (error "GUI.hs:no toolbar2") return 
-  -- 
-  ebox <- eventBoxNew
-  label <- labelNew (Just "drag me")
-  containerAdd ebox label 
-  dragSourceSet ebox [Button1] [ActionCopy]
-  dragSourceSetIconStock ebox stockIndex
-  dragSourceAddTextTargets ebox
-  ebox `on` dragBegin $ \_dc -> do 
-      liftIO $ putStrLn "dragging"
-  ebox `on` dragDataGet $ \_dc _iid _ts -> do 
+    Gtk.initGUI
+    window <- Gtk.windowNew   
+    Gtk.windowSetDefaultSize window 800 400
+    cfg <- loadConfigFile   
+    devlst <- initDevice cfg 
+    maxundo <- getMaxUndo cfg >>= maybe (return 50) (return . id)
+    xinputbool <- getXInputConfig cfg 
+    varcsr <- getPenConfig cfg
+    (usepz,uselyr) <- getWidgetConfig cfg 
+    (tref,st0,ui,vbox) <- initCoroutine devlst window mhook maxundo (xinputbool,usepz,uselyr,varcsr) 
+    setTitleFromFileName st0
+    -- need for refactoring
+    mapM_ (\(x,y :: Simple Lens Settings Bool) -> lensSetToggleUIForFlag x (settings.y) st0 )
+      [ ("UXINPUTA", doesUseXInput) 
+      , ("HANDA"   , doesUseTouch)
+      , ("POPMENUA", doesUsePopUpMenu)
+      , ("EBDIMGA" , doesEmbedImage)
+      , ("EBDPDFA" , doesEmbedPDF)
+      ] 
+    setToggleUIForFlag "TOGGLENETSRCA" False st0
+    -- 
+    let canvases = map (getDrawAreaFromBox) . M.elems . view (unitHoodles.currentUnit.cvsInfoMap) $ st0
+#ifndef GTK3      
+    if xinputbool
+        then mapM_ (flip Gtk.widgetSetExtensionEvents [Gtk.ExtensionEventsAll]) canvases
+        else mapM_ (flip Gtk.widgetSetExtensionEvents [Gtk.ExtensionEventsNone]) canvases
+#endif
+    --
+    outerLayout ui vbox st0 
+    window `Gtk.on` Gtk.deleteEvent $ do
+      liftIO $ eventHandler tref (UsrEv (Menu MenuQuit))
+      return True
+    Gtk.widgetShowAll window
+
+    forkIO $ clock (eventHandler tref)
+    let mainaction = eventHandler tref (UsrEv (Initialized mfname)) >> Gtk.mainGUI 
+    mainaction `catch` \(_e :: SomeException) -> do 
+      homepath <- getEnv "HOME"
+      let dir = homepath </> ".hoodle.d"
+      createDirectoryIfMissing False dir
+      outh <- openFile (dir </> "error.log") WriteMode 
+      hPutStrLn outh "error occured"
+      hClose outh 
+    return ()
+
+
+clock :: (AllEvent -> IO ()) -> IO ()
+clock evhandler = forever $ do 
+    threadDelay 1000000
+    Gtk.postGUIAsync (evhandler (SysEv ClockUpdateEvent))
+
+
+
+outerLayout :: Gtk.UIManager -> Gtk.VBox -> HoodleState -> IO ()
+outerLayout ui vbox xst = do 
+    let notebook = view rootNotebook xst
+        mstatusbar = view statusBar xst
+    menubar <- Gtk.uiManagerGetWidget ui "/ui/menubar" 
+               >>= maybe (error "GUI.hs:no menubar") return 
+    toolbar1 <- Gtk.uiManagerGetWidget ui "/ui/toolbar1" 
+                >>= maybe (error "GUI.hs:no toolbar1") return 
+    toolbar2 <- Gtk.uiManagerGetWidget ui "/ui/toolbar2"
+                >>= maybe (error "GUI.hs:no toolbar2") return 
+    -- 
+    ebox <- Gtk.eventBoxNew
+    label <- Gtk.labelNew (Just "drag me")
+    Gtk.containerAdd ebox label 
+    Gtk.dragSourceSet ebox [Gtk.Button1] [Gtk.ActionCopy]
+    Gtk.dragSourceSetIconStock ebox Gtk.stockIndex
+    Gtk.dragSourceAddTextTargets ebox
+    -- ebox `on` dragBegin $ \_dc -> do 
+    --   liftIO $ putStrLn "dragging"
+    ebox `Gtk.on` Gtk.dragDataGet $ \_dc _iid _ts -> do 
       -- very dirty solution but.. 
       minfo <- liftIO $ do 
         ref <- newIORef (Nothing :: Maybe String)
-        view callBack st0 (UsrEv (GetHoodleFileInfo ref))
+        view callBack xst (UsrEv (GetHoodleFileInfo ref))
         readIORef ref
-      mapM_ (selectionDataSetText >=> const (return ())) minfo
-  --
-  -- 
-  hbox <- hBoxNew False 0 
-  boxPackStart hbox toolbar1 PackGrow 0
-  boxPackStart hbox ebox PackNatural 0
-  containerAdd window vbox
-  boxPackStart vbox menubar PackNatural 0 
-  boxPackStart vbox hbox PackNatural 0
-  boxPackStart vbox toolbar2 PackNatural 0  
-  boxPackEnd vbox statusbar PackNatural 0 
-  boxPackStart vbox (view rootWindow st0) PackGrow 0 
-  window `on` deleteEvent $ do
-    liftIO $ eventHandler tref (UsrEv (Menu MenuQuit))
-    return True
-  widgetShowAll window
-  -- 
-  -- this is a test for asynchronous events
-  -- 
-  forkIO $ forever $ do 
-    threadDelay 1000000
-    -- putStrLn "event!"
-    postGUIAsync (eventHandler tref (SysEv ClockUpdateEvent))
-  
-  -- 
-  -- test end
-  -- 
-  let mainaction = do eventHandler tref (UsrEv (Initialized mfname))
-                      mainGUI 
-  mainaction `catch` \(_e :: SomeException) -> do 
-    homepath <- getEnv "HOME"
-    let dir = homepath </> ".hoodle.d"
-    createDirectoryIfMissing False dir
-    outh <- openFile (dir </> "error.log") WriteMode 
-    hPutStrLn outh "error occured"
-    hClose outh 
-  return ()
+      traverse Gtk.selectionDataSetText minfo >> return ()
 
+    -- 
+    hbox <- Gtk.hBoxNew False 0 
+    Gtk.boxPackStart hbox toolbar1 Gtk.PackGrow 0
+    Gtk.boxPackStart hbox ebox Gtk.PackNatural 0
+    Gtk.boxPackStart vbox menubar Gtk.PackNatural 0 
+    Gtk.boxPackStart vbox hbox Gtk.PackNatural 0
+    Gtk.boxPackStart vbox toolbar2 Gtk.PackNatural 0  
+    forM_ mstatusbar $ \statusbar-> Gtk.boxPackEnd vbox statusbar Gtk.PackNatural 0
+    --
+    Gtk.boxPackStart vbox notebook Gtk.PackGrow 0 
 
diff --git a/src/Hoodle/GUI/Menu.hs b/src/Hoodle/GUI/Menu.hs
--- a/src/Hoodle/GUI/Menu.hs
+++ b/src/Hoodle/GUI/Menu.hs
@@ -1,11 +1,13 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE QuasiQuotes #-}
 
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.GUI.Menu 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -19,8 +21,8 @@
 -- from other packages
 import           Control.Lens (set)
 import           Control.Monad
-import           Graphics.UI.Gtk hiding (set,get)
-import qualified Graphics.UI.Gtk as Gtk (set)
+import qualified Data.Foldable as F (forM_)
+import qualified Graphics.UI.Gtk as Gtk
 import           System.FilePath
 -- from hoodle-platform 
 import           Data.Hoodle.Predefined 
@@ -34,7 +36,7 @@
 justMenu = Just . Menu 
 
 
-iconList :: [ (String,String) ]
+iconList :: [ (String,Gtk.StockId) ]
 iconList = [ ("fullscreen.png" , "myfullscreen")
            , ("pencil.png"     , "mypen")
            , ("eraser.png"     , "myeraser")
@@ -66,102 +68,108 @@
            ]
 
 -- | 
-viewmods :: [RadioActionEntry] 
-viewmods = [ RadioActionEntry "CONTA" "Continuous" Nothing Nothing Nothing 0
-           , RadioActionEntry "ONEPAGEA" "One Page" Nothing Nothing Nothing 1
+viewmods :: [Gtk.RadioActionEntry] 
+viewmods = [ Gtk.RadioActionEntry "CONTA" "Continuous" Nothing Nothing Nothing 0
+           , Gtk.RadioActionEntry "ONEPAGEA" "One Page" Nothing Nothing Nothing 1
            ]
            
 -- | 
-pointmods :: [RadioActionEntry] 
-pointmods = [ RadioActionEntry "PENVERYFINEA" "Very fine" Nothing Nothing Nothing 0
-            , RadioActionEntry "PENFINEA" "Fine" (Just "mythin") Nothing Nothing 1
+pointmods :: [Gtk.RadioActionEntry] 
+pointmods = [ Gtk.RadioActionEntry "PENVERYFINEA" "Very fine" Nothing Nothing Nothing 0
+            , Gtk.RadioActionEntry "PENFINEA" "Fine" (Just "mythin") Nothing Nothing 1
             
-            , RadioActionEntry "PENTHICKA" "Thick" (Just "mythick") Nothing Nothing 3 
-            , RadioActionEntry "PENVERYTHICKA" "Very Thick" Nothing Nothing Nothing 4 
-            , RadioActionEntry "PENULTRATHICKA" "Ultra Thick" Nothing Nothing Nothing 5   
-            , RadioActionEntry "PENMEDIUMA" "Medium" (Just "mymedium") Nothing Nothing 2              
---             , RadioActionEntry "NOWIDTH" "Unknown" Nothing Nothing Nothing 999 
+            , Gtk.RadioActionEntry "PENTHICKA" "Thick" (Just "mythick") Nothing Nothing 3 
+            , Gtk.RadioActionEntry "PENVERYTHICKA" "Very Thick" Nothing Nothing Nothing 4 
+            , Gtk.RadioActionEntry "PENULTRATHICKA" "Ultra Thick" Nothing Nothing Nothing 5   
+            , Gtk.RadioActionEntry "PENMEDIUMA" "Medium" (Just "mymedium") Nothing Nothing 2              
+--             , Gtk.RadioActionEntry "NOWIDTH" "Unknown" Nothing Nothing Nothing 999 
             ]            
 
 -- | 
 
-penmods :: [RadioActionEntry] 
-penmods = [ RadioActionEntry "PENA"    "Pen"         (Just "mypen")         Nothing Nothing 0 
-          , RadioActionEntry "ERASERA" "Eraser"      (Just "myeraser")      Nothing Nothing 1
-          , RadioActionEntry "HIGHLTA" "Highlighter" (Just "myhighlighter") Nothing Nothing 2
---           , RadioActionEntry "TEXTA"   "Text"        (Just "mytext")        Nothing Nothing 3 
-          , RadioActionEntry "SELREGNA" "Select Region"     (Just "mylasso")        Nothing Nothing 4
-          , RadioActionEntry "SELRECTA" "Select Rectangle" (Just "myrectselect")        Nothing Nothing 5
-          , RadioActionEntry "VERTSPA" "Vertical Space"    (Just "mystretch")        Nothing Nothing 6
+penmods :: [Gtk.RadioActionEntry] 
+penmods = [ Gtk.RadioActionEntry "PENA"    "Pen"         (Just "mypen")         Nothing Nothing 0 
+          , Gtk.RadioActionEntry "ERASERA" "Eraser"      (Just "myeraser")      Nothing Nothing 1
+          , Gtk.RadioActionEntry "HIGHLTA" "Highlighter" (Just "myhighlighter") Nothing Nothing 2
+--           , Gtk.RadioActionEntry "TEXTA"   "Text"        (Just "mytext")        Nothing Nothing 3 
+          , Gtk.RadioActionEntry "SELREGNA" "Select Region"     (Just "mylasso")        Nothing Nothing 4
+          , Gtk.RadioActionEntry "SELRECTA" "Select Rectangle" (Just "myrectselect")        Nothing Nothing 5
+          , Gtk.RadioActionEntry "VERTSPA" "Vertical Space"    (Just "mystretch")        Nothing Nothing 6
           ]            
 
---          , RadioActionEntry "HANDA"   "Hand Tool"         (Just "myhand")        Nothing Nothing 7
+--          , Gtk.RadioActionEntry "HANDA"   "Hand Tool"         (Just "myhand")        Nothing Nothing 7
 
 
 -- | 
 
-colormods :: [RadioActionEntry]
-colormods = [ RadioActionEntry "BLUEA"       "Blue"       (Just "myblue")       Nothing Nothing 1
-            , RadioActionEntry "REDA"        "Red"        (Just "myred")        Nothing Nothing 2
-            , RadioActionEntry "GREENA"      "Green"      (Just "mygreen")      Nothing Nothing 3
-            , RadioActionEntry "GRAYA"       "Gray"       (Just "mygray")       Nothing Nothing 4
-            , RadioActionEntry "LIGHTBLUEA"  "Lightblue"  (Just "mylightblue")  Nothing Nothing 5     
-            , RadioActionEntry "LIGHTGREENA" "Lightgreen" (Just "mylightgreen") Nothing Nothing 6
-            , RadioActionEntry "MAGENTAA"    "Magenta"    (Just "mymagenta")    Nothing Nothing 7
-            , RadioActionEntry "ORANGEA"     "Orange"     (Just "myorange")     Nothing Nothing 8
-            , RadioActionEntry "YELLOWA"     "Yellow"     (Just "myyellow")     Nothing Nothing 9
-            , RadioActionEntry "WHITEA"      "White"      (Just "mywhite")      Nothing Nothing 10
-            , RadioActionEntry "BLACKA"      "Black"      (Just "myblack")      Nothing Nothing 0              
----             , RadioActionEntry "NOCOLOR"     "Unknown"    Nothing Nothing Nothing 999 
+colormods :: [Gtk.RadioActionEntry]
+colormods = [ Gtk.RadioActionEntry "BLUEA"       "Blue"       (Just "myblue")       Nothing Nothing 1
+            , Gtk.RadioActionEntry "REDA"        "Red"        (Just "myred")        Nothing Nothing 2
+            , Gtk.RadioActionEntry "GREENA"      "Green"      (Just "mygreen")      Nothing Nothing 3
+            , Gtk.RadioActionEntry "GRAYA"       "Gray"       (Just "mygray")       Nothing Nothing 4
+            , Gtk.RadioActionEntry "LIGHTBLUEA"  "Lightblue"  (Just "mylightblue")  Nothing Nothing 5     
+            , Gtk.RadioActionEntry "LIGHTGREENA" "Lightgreen" (Just "mylightgreen") Nothing Nothing 6
+            , Gtk.RadioActionEntry "MAGENTAA"    "Magenta"    (Just "mymagenta")    Nothing Nothing 7
+            , Gtk.RadioActionEntry "ORANGEA"     "Orange"     (Just "myorange")     Nothing Nothing 8
+            , Gtk.RadioActionEntry "YELLOWA"     "Yellow"     (Just "myyellow")     Nothing Nothing 9
+            , Gtk.RadioActionEntry "WHITEA"      "White"      (Just "mywhite")      Nothing Nothing 10
+            , Gtk.RadioActionEntry "BLACKA"      "Black"      (Just "myblack")      Nothing Nothing 0              
+---             , Gtk.RadioActionEntry "NOCOLOR"     "Unknown"    Nothing Nothing Nothing 999 
             ]
 
 -- | 
-bkgstyles :: [RadioActionEntry] 
-bkgstyles = [ RadioActionEntry "BKGGRAPHA" "Graph" Nothing Nothing Nothing 3 
-            , RadioActionEntry "BKGPLAINA" "Plain" Nothing Nothing Nothing 0
-            , RadioActionEntry "BKGLINEDA" "Lined" Nothing Nothing Nothing 1
-            , RadioActionEntry "BKGRULEDA" "Ruled" Nothing Nothing Nothing 2 
+bkgstyles :: [Gtk.RadioActionEntry] 
+bkgstyles = [ Gtk.RadioActionEntry "BKGGRAPHA" "Graph" Nothing Nothing Nothing 3 
+            , Gtk.RadioActionEntry "BKGPLAINA" "Plain" Nothing Nothing Nothing 0
+            , Gtk.RadioActionEntry "BKGLINEDA" "Lined" Nothing Nothing Nothing 1
+            , Gtk.RadioActionEntry "BKGRULEDA" "Ruled" Nothing Nothing Nothing 2 
             ]
 
+newpagemods :: [Gtk.RadioActionEntry] 
+newpagemods = [ Gtk.RadioActionEntry "NEWPAGEPLAINA" "Plain page" Nothing Nothing Nothing 0 
+              , Gtk.RadioActionEntry "NEWPAGELASTA"  "Last page"  Nothing Nothing Nothing 1
+              , Gtk.RadioActionEntry "NEWPAGECYCLEA" "Cycle page" Nothing Nothing Nothing 2
+              ]
+
+
 -- | 
-iconResourceAdd :: IconFactory -> FilePath -> (FilePath, StockId) 
-                   -> IO ()
+iconResourceAdd :: Gtk.IconFactory -> FilePath -> (FilePath, Gtk.StockId) -> IO ()
 iconResourceAdd iconfac resdir (fp,stid) = do 
-  myIconSource <- iconSourceNew 
-  iconSourceSetFilename myIconSource (resdir </> fp)
-  iconSourceSetSize myIconSource IconSizeLargeToolbar
-  myIconSourceSmall <- iconSourceNew 
-  iconSourceSetFilename myIconSourceSmall (resdir </> fp)
-  iconSourceSetSize myIconSource IconSizeMenu
-  myIconSet <- iconSetNew 
-  iconSetAddSource myIconSet myIconSource 
-  iconSetAddSource myIconSet myIconSourceSmall
-  iconFactoryAdd iconfac stid myIconSet
+  myIconSource <- Gtk.iconSourceNew 
+  Gtk.iconSourceSetFilename myIconSource (resdir </> fp)
+  Gtk.iconSourceSetSize myIconSource Gtk.IconSizeLargeToolbar
+  myIconSourceSmall <- Gtk.iconSourceNew 
+  Gtk.iconSourceSetFilename myIconSourceSmall (resdir </> fp)
+  Gtk.iconSourceSetSize myIconSource Gtk.IconSizeMenu
+  myIconSet <- Gtk.iconSetNew 
+  Gtk.iconSetAddSource myIconSet myIconSource 
+  Gtk.iconSetAddSource myIconSet myIconSourceSmall
+  Gtk.iconFactoryAdd iconfac stid myIconSet
 
 -- | 
 
 actionNewAndRegisterRef :: EventVar                            
                            -> String -> String 
-                           -> Maybe String -> Maybe StockId
+                           -> Maybe String -> Maybe Gtk.StockId
                            -> Maybe UserEvent 
-                           -> IO Action
+                           -> IO Gtk.Action
 actionNewAndRegisterRef evar name label tooltip stockId myevent = do 
-    a <- actionNew name label tooltip stockId 
+    a <- Gtk.actionNew name label tooltip stockId 
     case myevent of 
       Nothing -> return a 
       Just ev -> do 
-        a `on` actionActivated $ do 
+        a `Gtk.on` Gtk.actionActivated $ do 
           eventHandler evar (UsrEv ev)
         return a
 
 -- | 
 
-getMenuUI :: EventVar -> IO (UIManager,UIComponentSignalHandler)
+getMenuUI :: EventVar -> IO (Gtk.UIManager,UIComponentSignalHandler)
 getMenuUI evar = do 
   let actionNewAndRegister = actionNewAndRegisterRef evar  
   -- icons   
-  myiconfac <- iconFactoryNew 
-  iconFactoryAddDefault myiconfac 
+  myiconfac <- Gtk.iconFactoryNew 
+  Gtk.iconFactoryAddDefault myiconfac 
   resDir <- getDataDir >>= return . (</> "resource") 
   mapM_ (iconResourceAdd myiconfac resDir) iconList 
   fma     <- actionNewAndRegister "FMA"   "File" Nothing Nothing Nothing
@@ -173,15 +181,16 @@
   tma     <- actionNewAndRegister "TMA"   "Tool" Nothing Nothing Nothing
   verma   <- actionNewAndRegister "VERMA" "Version" Nothing Nothing Nothing
   oma     <- actionNewAndRegister "OMA"   "Option" Nothing Nothing Nothing
+  wma     <- actionNewAndRegister "WMA"   "Window" Nothing Nothing Nothing
   hma     <- actionNewAndRegister "HMA"   "Help" Nothing Nothing Nothing
 
   ---------------
   -- file menu --
   ---------------
-  newa    <- actionNewAndRegister "NEWA"  "New" (Just "Just a Stub") (Just stockNew) (justMenu MenuNew)
-  opena   <- actionNewAndRegister "OPENA" "Open" (Just "Just a Stub") (Just stockOpen) (justMenu MenuOpen)
-  savea   <- actionNewAndRegister "SAVEA" "Save" (Just "Just a Stub") (Just stockSave) (justMenu MenuSave)
-  saveasa <- actionNewAndRegister "SAVEASA" "Save As" (Just "Just a Stub") (Just stockSaveAs) (justMenu MenuSaveAs)
+  newa    <- actionNewAndRegister "NEWA"  "New" (Just "Just a Stub") (Just Gtk.stockNew) (justMenu MenuNew)
+  opena   <- actionNewAndRegister "OPENA" "Open" (Just "Just a Stub") (Just Gtk.stockOpen) (justMenu MenuOpen)
+  savea   <- actionNewAndRegister "SAVEA" "Save" (Just "Just a Stub") (Just Gtk.stockSave) (justMenu MenuSave)
+  saveasa <- actionNewAndRegister "SAVEASA" "Save As" (Just "Just a Stub") (Just Gtk.stockSaveAs) (justMenu MenuSaveAs)
   printa  <- actionNewAndRegister "PRINTA" "Print" (Just "Just a Stub") Nothing (justMenu MenuPrint)
   --
   exporta <- actionNewAndRegister "EXPORTA" "Export to PDF" (Just "Just a Stub") Nothing (justMenu MenuExport)
@@ -192,37 +201,38 @@
   reloada <- actionNewAndRegister "RELOADA" "Reload File" (Just "Just a Stub") Nothing (justMenu MenuReload)
   recenta <- actionNewAndRegister "RECENTA" "Recent Document" (Just "Just a Stub") Nothing (justMenu MenuRecentDocument)
   --
-  quita   <- actionNewAndRegister "QUITA" "Quit" (Just "Just a Stub") (Just stockQuit) (justMenu MenuQuit)
+  quita   <- actionNewAndRegister "QUITA" "Quit" (Just "Just a Stub") (Just Gtk.stockQuit) (justMenu MenuQuit)
 
   ---------------
   -- edit menu --
   ---------------
-  undoa   <- actionNewAndRegister "UNDOA"   "Undo" (Just "Just a Stub") (Just stockUndo) (justMenu MenuUndo)
-  redoa   <- actionNewAndRegister "REDOA"   "Redo" (Just "Just a Stub") (Just stockRedo) (justMenu MenuRedo)
-  cuta    <- actionNewAndRegister "CUTA"    "Cut" (Just "Just a Stub")  (Just stockCut) (justMenu MenuCut)
-  copya   <- actionNewAndRegister "COPYA"   "Copy" (Just "Just a Stub") (Just stockCopy) (justMenu MenuCopy)
-  pastea  <- actionNewAndRegister "PASTEA"  "Paste" (Just "Just a Stub") (Just stockPaste) (justMenu MenuPaste)
-  deletea <- actionNewAndRegister "DELETEA" "Delete" (Just "Just a Stub") (Just stockDelete) (justMenu MenuDelete)
+  undoa   <- actionNewAndRegister "UNDOA"   "Undo" (Just "Just a Stub") (Just Gtk.stockUndo) (justMenu MenuUndo)
+  redoa   <- actionNewAndRegister "REDOA"   "Redo" (Just "Just a Stub") (Just Gtk.stockRedo) (justMenu MenuRedo)
+  cuta    <- actionNewAndRegister "CUTA"    "Cut" (Just "Just a Stub")  (Just Gtk.stockCut) (justMenu MenuCut)
+  copya   <- actionNewAndRegister "COPYA"   "Copy" (Just "Just a Stub") (Just Gtk.stockCopy) (justMenu MenuCopy)
+  pastea  <- actionNewAndRegister "PASTEA"  "Paste" (Just "Just a Stub") (Just Gtk.stockPaste) (justMenu MenuPaste)
+  deletea <- actionNewAndRegister "DELETEA" "Delete" (Just "Just a Stub") (Just Gtk.stockDelete) (justMenu MenuDelete)
 
   ---------------
   -- view menu --
   ---------------
   togpanzooma <- actionNewAndRegister "TOGPANZOOMA" "Show/Hide Zoom Widget"  (Just "Just a stub") Nothing (justMenu MenuTogglePanZoomWidget)
+  togscra <- actionNewAndRegister "TOGSCRA" "Show/Hide Scroll Widget"  (Just "Just a stub") Nothing (justMenu MenuToggleScrollWidget)
   -- 
   zooma     <- actionNewAndRegister "ZOOMA"     "Zoom" (Just "Just a Stub") Nothing Nothing -- (justMenu MenuZoom)
-  zmina     <- actionNewAndRegister "ZMINA"     "Zoom In" (Just "Zoom In") (Just stockZoomIn) (justMenu MenuZoomIn)
-  zmouta    <- actionNewAndRegister "ZMOUTA"    "Zoom Out" (Just "Zoom Out") (Just stockZoomOut) (justMenu MenuZoomOut)
-  nrmsizea  <- actionNewAndRegister "NRMSIZEA"  "Normal Size" (Just "Normal Size") (Just stockZoom100) (justMenu MenuNormalSize)
-  pgwdtha   <- actionNewAndRegister "PGWDTHA" "Page Width" (Just "Page Width") (Just stockZoomFit) (justMenu MenuPageWidth)
+  zmina     <- actionNewAndRegister "ZMINA"     "Zoom In" (Just "Zoom In") (Just Gtk.stockZoomIn) (justMenu MenuZoomIn)
+  zmouta    <- actionNewAndRegister "ZMOUTA"    "Zoom Out" (Just "Zoom Out") (Just Gtk.stockZoomOut) (justMenu MenuZoomOut)
+  nrmsizea  <- actionNewAndRegister "NRMSIZEA"  "Normal Size" (Just "Normal Size") (Just Gtk.stockZoom100) (justMenu MenuNormalSize)
+  pgwdtha   <- actionNewAndRegister "PGWDTHA" "Page Width" (Just "Page Width") (Just Gtk.stockZoomFit) (justMenu MenuPageWidth)
   pgheighta <- actionNewAndRegister "PGHEIGHTA" "Page Height" (Just "Page Height") Nothing (justMenu MenuPageHeight)
-  setzma    <- actionNewAndRegister "SETZMA"  "Set Zoom" (Just "Set Zoom") (Just stockFind) (justMenu MenuSetZoom)
+  setzma    <- actionNewAndRegister "SETZMA"  "Set Zoom" (Just "Set Zoom") (Just Gtk.stockFind) (justMenu MenuSetZoom)
   -- 
   fscra     <- actionNewAndRegister "FSCRA"     "Full Screen" (Just "Just a Stub") (Just "myfullscreen") (justMenu MenuFullScreen)
   --
-  fstpagea  <- actionNewAndRegister "FSTPAGEA"  "First Page" (Just "Just a Stub") (Just stockGotoFirst) (justMenu MenuFirstPage)
-  prvpagea  <- actionNewAndRegister "PRVPAGEA"  "Previous Page" (Just "Just a Stub") (Just stockGoBack) (justMenu MenuPreviousPage)
-  nxtpagea  <- actionNewAndRegister "NXTPAGEA"  "Next Page" (Just "Just a Stub") (Just stockGoForward) (justMenu MenuNextPage)
-  lstpagea  <- actionNewAndRegister "LSTPAGEA"  "Last Page" (Just "Just a Stub") (Just stockGotoLast) (justMenu MenuLastPage)
+  fstpagea  <- actionNewAndRegister "FSTPAGEA"  "First Page" (Just "Just a Stub") (Just Gtk.stockGotoFirst) (justMenu MenuFirstPage)
+  prvpagea  <- actionNewAndRegister "PRVPAGEA"  "Previous Page" (Just "Just a Stub") (Just Gtk.stockGoBack) (justMenu MenuPreviousPage)
+  nxtpagea  <- actionNewAndRegister "NXTPAGEA"  "Next Page" (Just "Just a Stub") (Just Gtk.stockGoForward) (justMenu MenuNextPage)
+  lstpagea  <- actionNewAndRegister "LSTPAGEA"  "Last Page" (Just "Just a Stub") (Just Gtk.stockGotoLast) (justMenu MenuLastPage)
   -- 
   hsplita <- actionNewAndRegister "HSPLITA" "Clone View Horizontally" (Just "horizontal split") Nothing (justMenu MenuHSplit)
   vsplita <- actionNewAndRegister "VSPLITA" "Clone View Vertically" (Just "vertical split") Nothing (justMenu MenuVSplit)
@@ -240,16 +250,13 @@
   gotolayera <- actionNewAndRegister "GOTOLAYERA" "Goto Layer" (Just "Just a Stub") Nothing (justMenu MenuGotoLayer)
   dellyra <- actionNewAndRegister "DELLYRA" "Delete Layer"    (Just "Just a Stub") Nothing (justMenu MenuDeleteLayer)
 
-  -- shwlayera <- actionNewAndRegister "SHWLAYERA" "Show Layer" (Just "Just a Stub") Nothing (justMenu MenuShowLayer)
-  -- hidlayera <- actionNewAndRegister "HIDLAYERA" "Hide Layer" (Just "Just a Stub") Nothing (justMenu MenuHideLayer)
-
-
   ----------------
-  -- image menu --
+  -- embed menu --
   ----------------
 
   ldpnga <- actionNewAndRegister "LDIMGA" "Load PNG or JPG Image" (Just "Just a Stub") Nothing (justMenu MenuLoadPNGorJPG)
   ldsvga <- actionNewAndRegister "LDSVGA" "Load SVG Image" (Just "Just a Stub") Nothing (justMenu MenuLoadSVG)
+  ldimgbkga <- actionNewAndRegister "LDIMGBKGA" "Make Title Page from Image" (Just "Just a Stub") Nothing (justMenu MenuLoadImageBackground)
   ldpreimga <- actionNewAndRegister "LDPREIMGA" "Embed Predefined Image File" (Just "Just a Stub") Nothing (justMenu MenuEmbedPredefinedImage)
   ldpreimg2a <- actionNewAndRegister "LDPREIMG2A" "Embed Predefined Image File 2" (Just "Just a Stub") Nothing (justMenu MenuEmbedPredefinedImage2)
   ldpreimg3a <- actionNewAndRegister "LDPREIMG3A" "Embed Predefined Image File 3" (Just "Just a Stub") Nothing (justMenu MenuEmbedPredefinedImage3)
@@ -257,17 +264,37 @@
   texta <- actionNewAndRegister "TEXTA" "Text" (Just "Text") (Just "mytext") (justMenu MenuText)
   textsrca <- actionNewAndRegister "TEXTSRCA" "Embed Text Source" (Just "Just a Stub") Nothing (justMenu MenuEmbedTextSource)
   editsrca <- actionNewAndRegister "EDITSRCA" "Edit text source" (Just "Just a Stub") Nothing (justMenu MenuEditEmbedTextSource)
+#ifdef HUB
   editnetsrca <- actionNewAndRegister "EDITNETSRCA" "Network edit text source" (Just "Just a Stub") Nothing (justMenu MenuEditNetEmbedTextSource)
-
+#else
+  editnetsrca <- actionNewAndRegister "EDITNETSRCA" "Network edit text source" (Just "Just a Stub") Nothing (justMenu MenuDefault)
+#endif
   textfromsrca <- actionNewAndRegister "TEXTFROMSRCA" "Text From Source" (Just "Just a Stub") Nothing (justMenu MenuTextFromSource)
 
+
+  togglenetsrca <- Gtk.toggleActionNew ("TOGGLENETSRCA" :: String) "Toggle network edit text source" (Just "Just a Stub") Nothing
+#ifdef HUB
+  togglenetsrca `Gtk.on` Gtk.actionToggled $ do
+    eventHandler evar (UsrEv (Menu MenuToggleNetworkEditSource))
+#else
+  togglenetsrca `Gtk.on` Gtk.actionToggled $ do
+    eventHandler evar (UsrEv (Menu MenuDefault))
+#endif
   latexa <- actionNewAndRegister "LATEXA" "LaTeX" (Just "Just a Stub") (Just "mylatex") (justMenu MenuLaTeX)
+#ifdef HUB
   latexneta <- actionNewAndRegister "LATEXNETA" "LaTeX Network" (Just "Just a Stub") (Just "mylatex") (justMenu MenuLaTeXNetwork)  
+#else
+  latexneta <- actionNewAndRegister "LATEXNETA" "LaTeX Network" (Just "Just a Stub") (Just "mylatex") (justMenu MenuDefault)  
+#endif
   combinelatexa <- actionNewAndRegister "COMBINELATEXA" "Combine LaTeX texts to ..." (Just "Just a Stub") Nothing (justMenu MenuCombineLaTeX)  
   latexfromsrca <- actionNewAndRegister "LATEXFROMSRCA" "LaTeX From Source" (Just "Just a Stub") Nothing (justMenu MenuLaTeXFromSource)   
+  updatelatexa <- actionNewAndRegister "UPDATELATEXA" "Update LaTeX" (Just "Just a Stub") Nothing (justMenu MenuUpdateLaTeX)   
 
 
-  -- page menu 
+  ---------------
+  -- page menu --
+  ---------------
+
   newpgba <- actionNewAndRegister "NEWPGBA" "New Page Before" (Just "Just a Stub") Nothing (justMenu MenuNewPageBefore)
   newpgaa <- actionNewAndRegister "NEWPGAA" "New Page After"  (Just "Just a Stub") Nothing (justMenu MenuNewPageAfter)
   newpgea <- actionNewAndRegister "NEWPGEA" "New Page At End" (Just "Just a Stub") Nothing (justMenu MenuNewPageAtEnd)
@@ -278,26 +305,17 @@
   ppstya <- actionNewAndRegister "PPSTYA"   "Paper Style" Nothing Nothing Nothing
   apallpga<- actionNewAndRegister "APALLPGA" "Apply To All Pages" (Just "Just a Stub") Nothing (justMenu MenuApplyToAllPages)
   embedbkgpdfa <- actionNewAndRegister "EMBEDBKGPDFA" "Embed All PDF backgroound" (Just "Just a Stub") Nothing (justMenu MenuEmbedAllPDFBkg)
-  -- ldbkga  <- actionNewAndRegister "LDBKGA"  "Load Background" (Just "Just a Stub") Nothing (justMenu MenuLoadBackground)
-  -- bkgscrshta <- actionNewAndRegister "BKGSCRSHTA" "Background Screenshot" (Just "Just a Stub") Nothing (justMenu MenuBackgroundScreenshot)
   defppa  <- actionNewAndRegister "DEFPPA"  "Default Paper" (Just "Just a Stub") Nothing (justMenu MenuDefaultPaper)
   setdefppa <- actionNewAndRegister "SETDEFPPA" "Set As Default" (Just "Just a Stub") Nothing (justMenu MenuSetAsDefaultPaper)
   
   -- tools menu
-  linka <- actionNewAndRegister "LINKA" "Add Link" (Just "Add Link") (Just stockIndex) (justMenu MenuAddLink)
+  linka <- actionNewAndRegister "LINKA" "Add Link" (Just "Add Link") (Just Gtk.stockIndex) (justMenu MenuAddLink)
   anchora <- actionNewAndRegister "ANCHORA" "Add Anchor" (Just "Add Anchor") Nothing (justMenu MenuAddAnchor)
   listanchora <- actionNewAndRegister "LISTANCHORA" "List Anchors" (Just "List Anchors") Nothing (justMenu MenuListAnchors)
-
-  -- shpreca   <- actionNewAndRegister "SHPRECA" "Shape Recognizer" (Just "Just a Stub") (Just "myshapes") (justMenu MenuShapeRecognizer)
-  -- rulera    <- actionNewAndRegister "RULERA" "Ruler" (Just "Just a Stub") (Just "myruler") (justMenu MenuRuler)
   handreca <- actionNewAndRegister "HANDRECA" "Hoodlet load via Handwriting Recognition" (Just "Just a Stub") (Just "myshapes") (justMenu MenuHandwritingRecognitionDialog)
   
-  
-  -- selregna  <- actionNewAndRegister "SELREGNA" "Select Region" (Just "Just a Stub") (Just "mylasso") (justMenu MenuSelectRegion)
-  -- selrecta  <- actionNewAndRegister "SELRECTA" "Select Rectangle" (Just "Just a Stub") (Just "myrectselect") (justMenu MenuSelectRectangle)
-  -- vertspa   <- actionNewAndRegister "VERTSPA" "Vertical Space" (Just "Just a Stub") (Just "mystretch") (justMenu MenuVerticalSpace)
   clra      <- actionNewAndRegister "CLRA" "Color" (Just "Just a Stub") Nothing Nothing
-  clrpcka   <- actionNewAndRegister "CLRPCKA" "Color Picker.." (Just "Just a Stub") (Just stockSelectColor) (justMenu MenuColorPicker ) 
+  clrpcka   <- actionNewAndRegister "CLRPCKA" "Color Picker.." (Just "Just a Stub") (Just Gtk.stockSelectColor) (justMenu MenuColorPicker ) 
   penopta   <- actionNewAndRegister "PENOPTA" "Pen Options" (Just "Just a Stub") Nothing (justMenu MenuPenOptions)
   erasropta <- actionNewAndRegister "ERASROPTA" "Eraser Options" (Just "Just a Stub") Nothing (justMenu MenuEraserOptions)
   hiltropta <- actionNewAndRegister "HILTROPTA" "Highlighter Options" (Just "Just a Stub") Nothing (justMenu MenuHighlighterOptions)
@@ -307,9 +325,9 @@
   defhiltra <- actionNewAndRegister "DEFHILTRA" "Default Highlighter" (Just "Just a Stub") Nothing (justMenu MenuDefaultHighlighter)
   deftxta   <- actionNewAndRegister "DEFTXTA" "Default Text" (Just "Just a Stub") Nothing (justMenu MenuDefaultText)
   setdefopta <- actionNewAndRegister "SETDEFOPTA" "Set As Default" (Just "Just a Stub") Nothing (justMenu MenuSetAsDefaultOption)
-  relauncha <- actionNewAndRegister "RELAUNCHA" "Relaunch Application" (Just "Just a Stub") Nothing (justMenu MenuRelaunch)
 
 
+
   ------------------
   -- version menu --
   ------------------
@@ -323,227 +341,242 @@
   -----------------  
   -- option menu --
   -----------------
-  uxinputa <- toggleActionNew "UXINPUTA" "Use XInput" (Just "Just a Stub") Nothing 
-  uxinputa `on` actionToggled $ do 
+  uxinputa <- Gtk.toggleActionNew ("UXINPUTA" :: String) "Use XInput" (Just "Just a Stub") Nothing 
+  uxinputa `Gtk.on` Gtk.actionToggled $ do 
     eventHandler evar (UsrEv (Menu MenuUseXInput))
   -- handa <- actionNewAndRegister "HANDA" "Use Touch" (Just "Use touch") (Just "myhand") (justMenu MenuUseTouch)    
-  handa     <- toggleActionNew "HANDA" "Use Touch" (Just "Toggle touch") (Just "myhand") 
-  handa `on` actionToggled $ do 
+  handa     <- Gtk.toggleActionNew ("HANDA" :: String) "Use Touch" (Just "Toggle touch") (Just "myhand") 
+  handa `Gtk.on` Gtk.actionToggled $ do 
     eventHandler evar (UsrEv (Menu MenuUseTouch))
-  smthscra <- toggleActionNew "SMTHSCRA" "Smooth Scrolling" (Just "Just a stub") Nothing
-  smthscra `on` actionToggled $ do 
-    eventHandler evar (UsrEv (Menu MenuSmoothScroll))
-  popmenua <- toggleActionNew "POPMENUA" "Use Popup Menu" (Just "Just a stub") Nothing
-  popmenua `on` actionToggled $ do 
+  -- smthscra <- Gtk.toggleActionNew ("SMTHSCRA" :: String) "Smooth Scrolling" (Just "Just a stub") Nothing
+  -- smthscra `Gtk.on` Gtk.actionToggled $ do 
+  --   eventHandler evar (UsrEv (Menu MenuSmoothScroll))
+  popmenua <- Gtk.toggleActionNew ("POPMENUA" :: String) "Use Popup Menu" (Just "Just a stub") Nothing
+  popmenua `Gtk.on` Gtk.actionToggled $ do 
     eventHandler evar (UsrEv (Menu MenuUsePopUpMenu))
-  ebdimga <- toggleActionNew "EBDIMGA" "Embed PNG/JPG Image" (Just "Just a stub") Nothing
-  ebdimga `on` actionToggled $ do 
+  ebdimga <- Gtk.toggleActionNew ("EBDIMGA" :: String) "Embed PNG/JPG Image" (Just "Just a stub") Nothing
+  ebdimga `Gtk.on` Gtk.actionToggled $ do 
     eventHandler evar (UsrEv (Menu MenuEmbedImage))
-  ebdpdfa <- toggleActionNew "EBDPDFA" "Embed PDF" (Just "Just a stub") Nothing
-  ebdpdfa `on` actionToggled $ do 
+  ebdpdfa <- Gtk.toggleActionNew ("EBDPDFA" :: String) "Embed PDF" (Just "Just a stub") Nothing
+  ebdpdfa `Gtk.on` Gtk.actionToggled $ do 
     eventHandler evar (UsrEv (Menu MenuEmbedPDF))
-  flwlnka <- toggleActionNew "FLWLNKA" "Follow Links" (Just "Just a stub") Nothing
-  flwlnka `on` actionToggled $ do 
+  flwlnka <- Gtk.toggleActionNew ("FLWLNKA" :: String) "Follow Links" (Just "Just a stub") Nothing
+  flwlnka `Gtk.on` Gtk.actionToggled $ do 
     eventHandler evar (UsrEv (Menu MenuFollowLinks))    
-  keepratioa <- toggleActionNew "KEEPRATIOA" "Keep Aspect Ratio" (Just "Just a stub") Nothing
-  keepratioa `on` actionToggled $ do 
+  keepratioa <- Gtk.toggleActionNew ("KEEPRATIOA" :: String) "Keep Aspect Ratio" (Just "Just a stub") Nothing
+  keepratioa `Gtk.on` Gtk.actionToggled $ do 
     eventHandler evar (UsrEv (Menu MenuKeepAspectRatio))
-  vcursora <- toggleActionNew "VCURSORA" "Use Variable Cursor" (Just "Just a stub") Nothing
-  vcursora `on` actionToggled $ do 
+  vcursora <- Gtk.toggleActionNew ("VCURSORA" :: String) "Use Variable Cursor" (Just "Just a stub") Nothing
+  vcursora `Gtk.on` Gtk.actionToggled $ do 
     eventHandler evar (UsrEv (Menu MenuUseVariableCursor))
   -- temporary implementation (later will be as submenus with toggle action. appropriate reflection)
   togclocka <- actionNewAndRegister "TOGCLOCKA" "Toggle Clock Widget"  (Just "Just a stub") Nothing (justMenu MenuToggleClockWidget)
     
-  dcrdcorea <- actionNewAndRegister "DCRDCOREA" "Discard Core Events" (Just "Just a Stub") Nothing (justMenu MenuDiscardCoreEvents)
-  ersrtipa <- actionNewAndRegister "ERSRTIPA" "Eraser Tip" (Just "Just a Stub") Nothing (justMenu MenuEraserTip)
-  pressrsensa <- toggleActionNew "PRESSRSENSA" "Pressure Sensitivity" (Just "Just a Stub") Nothing 
-  pressrsensa `on` actionToggled $ do 
+  pressrsensa <- Gtk.toggleActionNew ("PRESSRSENSA" :: String) "Pressure Sensitivity" (Just "Just a Stub") Nothing 
+  pressrsensa `Gtk.on` Gtk.actionToggled $ do 
     eventHandler evar (UsrEv (Menu MenuPressureSensitivity))
 
+  newpagemoda <- actionNewAndRegister "NEWPAGEMODEA" "New page mode" Nothing Nothing Nothing
+#ifdef DYRE
+  relauncha <- actionNewAndRegister "RELAUNCHA" "Relaunch Application" (Just "Just a Stub") Nothing (justMenu MenuRelaunch)
+#else
+  relauncha <- actionNewAndRegister "RELAUNCHA" "Relaunch Application" (Just "Just a Stub") Nothing (justMenu MenuDefault)
+#endif
 
-  
-  
-  
-  pghilta <- actionNewAndRegister "PGHILTA" "Page Highlight" (Just "Just a Stub") Nothing (justMenu MenuPageHighlight)
-  mltpgvwa <- actionNewAndRegister "MLTPGVWA" "Multiple Page View" (Just "Just a Stub") Nothing (justMenu MenuMultiplePageView) 
-  mltpga <- actionNewAndRegister "MLTPGA" "Multiple Pages" (Just "Just a Stub") Nothing (justMenu MenuMultiplePages)
-  btn2mapa <- actionNewAndRegister "BTN2MAPA" "Button 2 Mapping" (Just "Just a Stub") Nothing (justMenu MenuButton2Mapping)
-  btn3mapa <- actionNewAndRegister "BTN3MAPA" "Button 3 Mapping" (Just "Just a Stub") Nothing (justMenu MenuButton3Mapping)
-  antialiasbmpa <- actionNewAndRegister "ANTIALIASBMPA" "Antialiased Bitmaps" (Just "Just a Stub") Nothing (justMenu MenuAntialiasedBitmaps)
-  prgrsbkga <- actionNewAndRegister "PRGRSBKGA" "Progressive Backgrounds" (Just "Just a Stub") Nothing (justMenu MenuProgressiveBackgrounds)
-  prntpprulea <- actionNewAndRegister "PRNTPPRULEA" "Print Paper Ruling" (Just "Just a Stub") Nothing (justMenu MenuPrintPaperRuling)
-  lfthndscrbra <- actionNewAndRegister "LFTHNDSCRBRA" "Left-Handed Scrollbar" (Just "Just a Stub") Nothing (justMenu MenuLeftHandedScrollbar)
-  shrtnmenua <- actionNewAndRegister "SHRTNMENUA" "Shorten Menus" (Just "Just a Stub") Nothing (justMenu MenuShortenMenus)
-  autosaveprefa <- actionNewAndRegister "AUTOSAVEPREFA" "Auto-Save Preferences" (Just "Just a Stub") Nothing (justMenu MenuAutoSavePreferences)
-  saveprefa <- actionNewAndRegister "SAVEPREFA" "Save Preferences" (Just "Just a Stub") Nothing (justMenu MenuSavePreferences)
-  
+#ifdef HUB
+  huba <- actionNewAndRegister "HUBA" "Hub" (Just "Just a Stub") Nothing (justMenu MenuHub)
+  -- hubsocketa <- actionNewAndRegister "HUBSOCKETA" "Hub Socket" (Just "Just a Stub") Nothing (justMenu MenuHubSocket)
+#else
+  huba <- actionNewAndRegister "HUBA" "Hub" (Just "Just a Stub") Nothing (justMenu MenuDefault)
+  -- hubsocketa <- actionNewAndRegister "HUBSOCKETA" "Hub Socket" (Just "Just a Stub") Nothing (justMenu MenuDefault)
+#endif
+
+
+  -- window menu
+  addtaba <- actionNewAndRegister "ADDTABA" "Add new tab" (Just "Just a Stub") Nothing (justMenu MenuAddTab)
+  -- nexttaba <- actionNewAndRegister "NEXTTABA" "Go to next tab" (Just "Just a Stub") Nothing (justMenu MenuNextTab)
+  closetaba <- actionNewAndRegister "CLOSETABA" "Close current tab" (Just "Just a Stub") Nothing (justMenu MenuCloseTab)
+
+
+
   -- help menu 
   abouta <- actionNewAndRegister "ABOUTA" "About" (Just "Just a Stub") Nothing (justMenu MenuAbout)
 
   -- others
   defaulta <- actionNewAndRegister "DEFAULTA" "Default" (Just "Default") (Just "mydefault") (justMenu MenuDefault)
   
-  agr <- actionGroupNew "AGR"
-  mapM_ (actionGroupAddAction agr) 
-        [fma,ema,vma,lma,ima,pma,tma,verma,oma,hma]
-  mapM_ (actionGroupAddAction agr)   
+  agr <- Gtk.actionGroupNew ("AGR" :: String)
+  mapM_ (Gtk.actionGroupAddAction agr) 
+        [fma,ema,vma,lma,ima,pma,tma,verma,oma,wma,hma]
+  mapM_ (Gtk.actionGroupAddAction agr)   
         [ undoa, redoa, cuta, copya, pastea, deletea ] 
-  mapM_ (\act -> actionGroupAddActionWithAccel agr act Nothing)   
+  mapM_ (\act -> Gtk.actionGroupAddActionWithAccel agr act (Nothing :: Maybe String))   
         [ newa, annpdfa, opena, savea, saveasa
         , reloada, recenta, printa, exporta, synca, versiona, showreva, showida, quita
         , fscra, zooma, zmina, zmouta, nrmsizea, pgwdtha, pgheighta, setzma
-        , fstpagea, prvpagea, nxtpagea, lstpagea {- , shwlayera, hidlayera -}
+        , fstpagea, prvpagea, nxtpagea, lstpagea 
         , hsplita, vsplita, delcvsa
         , newpgba, newpgaa, newpgea, delpga, expsvga, newlyra, nextlayera, prevlayera, gotolayera, dellyra, ppsizea, ppclra
         , ppstya 
         , apallpga, embedbkgpdfa, defppa, setdefppa
-        , ldpnga, ldsvga, texta, textsrca, editsrca, editnetsrca, textfromsrca
-        , latexa, latexneta, combinelatexa, latexfromsrca
+        , ldpnga, ldsvga, ldimgbkga, texta, textsrca, editsrca, editnetsrca, textfromsrca
+        , latexa, latexneta, combinelatexa, latexfromsrca, updatelatexa
         , ldpreimga, ldpreimg2a, ldpreimg3a
-        , linka, anchora, listanchora, {- shpreca, rulera, -} handreca, clra, clrpcka, penopta 
+        , linka, anchora, listanchora, handreca, clra, clrpcka, penopta 
         , erasropta, hiltropta, txtfnta, defpena, defersra, defhiltra, deftxta
-        , setdefopta, relauncha
-        , togpanzooma, toglayera, togclocka
-        , dcrdcorea, ersrtipa, pghilta, mltpgvwa
-        , mltpga, btn2mapa, btn3mapa, antialiasbmpa, prgrsbkga, prntpprulea 
-        , lfthndscrbra, shrtnmenua, autosaveprefa, saveprefa 
+        , setdefopta
+        , togpanzooma, togscra, toglayera, togclocka, newpagemoda, relauncha
+        , huba -- , hubsocketa
+        , addtaba, {- nexttaba, -} closetaba
         , abouta 
         , defaulta         
         ] 
     
-  mapM_ (actionGroupAddAction agr) 
-    [ uxinputa, handa, smthscra, popmenua, ebdimga, ebdpdfa, flwlnka, keepratioa, pressrsensa
-    , vcursora ]
-  -- actionGroupAddRadioActions agr viewmods 0 (assignViewMode evar)
+  mapM_ (Gtk.actionGroupAddAction agr) 
+    [ togglenetsrca, uxinputa, handa, popmenua, ebdimga, ebdpdfa, flwlnka
+    , keepratioa, pressrsensa, vcursora ]
+
   mpgmodconnid <- 
-    actionGroupAddRadioActionsAndGetConnID agr viewmods 0 (assignViewMode evar) -- const (return ()))
+    actionGroupAddRadioActionsAndGetConnID agr viewmods 0 (assignViewMode evar)
   _mpointconnid <- 
     actionGroupAddRadioActionsAndGetConnID agr pointmods 0 (assignPoint evar)
   mpenmodconnid <- 
     actionGroupAddRadioActionsAndGetConnID agr penmods   0 (assignPenMode evar)
-  _mcolorconnid <-  
+  mcolorconnid <-  
     actionGroupAddRadioActionsAndGetConnID agr colormods 0 (assignColor evar) 
-  actionGroupAddRadioActions agr bkgstyles 2 (assignBkgStyle evar)
-  
+  _mbkgstyconnid <-
+    actionGroupAddRadioActionsAndGetConnID agr bkgstyles 2 (assignBkgStyle evar)
+  mnpgmodconnid <- 
+    actionGroupAddRadioActionsAndGetConnID agr newpagemods 0 (assignNewPageMode evar)
+
   
   let disabledActions = 
         [ recenta, printa
         , cuta, copya, deletea
         ,  setzma
-        {- , shwlayera, hidlayera -}
         , newpgea, ppsizea, ppclra
         , defppa, setdefppa
-        -- , shpreca, rulera 
         , erasropta, hiltropta, txtfnta, defpena, defersra, defhiltra, deftxta
         , setdefopta
-        , dcrdcorea, ersrtipa, pghilta, mltpgvwa
-        , mltpga, btn2mapa, btn3mapa, antialiasbmpa, prgrsbkga, prntpprulea 
-        , lfthndscrbra, shrtnmenua, autosaveprefa, saveprefa 
-        , abouta 
+        , abouta
         , defaulta         
+#ifndef DYRE
+        , relauncha
+#endif
+#ifndef HUB
+        , editnetsrca
+        , huba
+#endif
         ] 
       enabledActions = 
         [ opena, savea, saveasa, reloada, versiona, showreva, showida, quita
         , pastea, fstpagea, prvpagea, nxtpagea, lstpagea
         , clra, penopta, zooma, nrmsizea, pgwdtha, texta  
+        , newpagemoda
         ]
   --
-  mapM_ (\x->actionSetSensitive x True) enabledActions  
-  mapM_ (\x->actionSetSensitive x False) disabledActions
+  mapM_ (\x->Gtk.actionSetSensitive x True) enabledActions  
+  mapM_ (\x->Gtk.actionSetSensitive x False) disabledActions
   --
   -- 
   -- radio actions
   --
-  ui <- uiManagerNew
+  ui <- Gtk.uiManagerNew
   
   uiDecl <- readFile (resDir </> "menu.xml")   
-  uiManagerAddUiFromString ui uiDecl
-  uiManagerInsertActionGroup ui agr 0 
-  Just ra2 <- actionGroupGetAction agr "PENFINEA"
-  Gtk.set (castToRadioAction ra2) [radioActionCurrentValue := 2]
-  Just ra3 <- actionGroupGetAction agr "SELREGNA"
-  actionSetSensitive ra3 True 
-  Just ra4 <- actionGroupGetAction agr "VERTSPA"
-  actionSetSensitive ra4 True
-  -- Just ra5 <- actionGroupGetAction agr "HANDA"
-  -- actionSetSensitive ra5 False
-  Just ra6 <- actionGroupGetAction agr "CONTA"
-  actionSetSensitive ra6 True
-  Just _ra7 <- actionGroupGetAction agr "PENA"
-  actionSetSensitive ra6 True  
-  Just toolbar1 <- uiManagerGetWidget ui "/ui/toolbar1"
-  toolbarSetStyle (castToToolbar toolbar1) ToolbarIcons 
-  toolbarSetIconSize (castToToolbar toolbar1) IconSizeSmallToolbar
-  Just toolbar2 <- uiManagerGetWidget ui "/ui/toolbar2"
-  toolbarSetStyle (castToToolbar toolbar2) ToolbarIcons 
-  toolbarSetIconSize (castToToolbar toolbar2) IconSizeSmallToolbar  
-  
-  -- Just pendropdown <- uiManagerGetWidget ui "/ui/toolbar2/PENDROPDOWN"
-  
-  
+  Gtk.uiManagerAddUiFromString ui uiDecl
+  Gtk.uiManagerInsertActionGroup ui agr 0 
+  Just ra2 <- Gtk.actionGroupGetAction agr ("PENFINEA" :: String)
+  Gtk.set (Gtk.castToRadioAction ra2) [Gtk.radioActionCurrentValue Gtk.:= 2]
+  Just ra3 <- Gtk.actionGroupGetAction agr ("SELREGNA" :: String)
+  Gtk.actionSetSensitive ra3 True 
+  Just ra4 <- Gtk.actionGroupGetAction agr ("VERTSPA" :: String)
+  Gtk.actionSetSensitive ra4 True
+  Just ra6 <- Gtk.actionGroupGetAction agr ("CONTA" :: String)
+  Gtk.actionSetSensitive ra6 True
+  Just _ra7 <- Gtk.actionGroupGetAction agr ("PENA" :: String)
+  Gtk.actionSetSensitive ra6 True  
+  Just toolbar1 <- Gtk.uiManagerGetWidget ui ("/ui/toolbar1" :: String)
+  Gtk.toolbarSetStyle (Gtk.castToToolbar toolbar1) Gtk.ToolbarIcons 
+#ifndef GTK3
+  Gtk.toolbarSetIconSize (Gtk.castToToolbar toolbar1) Gtk.IconSizeSmallToolbar
+#endif 
+  Just toolbar2 <- Gtk.uiManagerGetWidget ui ("/ui/toolbar2" :: String)
+  Gtk.toolbarSetStyle (Gtk.castToToolbar toolbar2) Gtk.ToolbarIcons 
+#ifndef GTK3
+  Gtk.toolbarSetIconSize (Gtk.castToToolbar toolbar2) Gtk.IconSizeSmallToolbar  
+#endif 
+    
   let uicomponentsignalhandler = set penModeSignal mpenmodconnid 
                                  . set pageModeSignal mpgmodconnid 
+                                 . set penColorSignal mcolorconnid
+                                 . set newPageModeSignal mnpgmodconnid
                                  $ defaultUIComponentSignalHandler 
   return (ui,uicomponentsignalhandler)   
 
 
 -- |
-actionGroupAddRadioActionsAndGetConnID :: ActionGroup 
-                                       -> [RadioActionEntry]
+actionGroupAddRadioActionsAndGetConnID :: Gtk.ActionGroup 
+                                       -> [Gtk.RadioActionEntry]
                                        -> Int  
-                                       -> (RadioAction -> IO ()) 
-                                       -> IO (Maybe (ConnectId RadioAction))
+                                       -> (Gtk.RadioAction -> IO ()) 
+                                       -> IO (Maybe (Gtk.ConnectId Gtk.RadioAction))
 actionGroupAddRadioActionsAndGetConnID self entries _value onChange = do 
   mgroup <- foldM 
-    (\mgroup (n,RadioActionEntry name label stockId accelerator tooltip value) -> do
-     action <- radioActionNew name label tooltip stockId value
-     case mgroup of 
-       Nothing -> return () 
-       Just gr -> radioActionSetGroup action gr
-     when (n==value) (toggleActionSetActive action True)
-     actionGroupAddActionWithAccel self action accelerator
+    (\mgroup (n,Gtk.RadioActionEntry name label stockId accelerator tooltip value) -> do
+     action <- Gtk.radioActionNew name label tooltip stockId value
+     F.forM_ mgroup $ \gr -> Gtk.radioActionSetGroup action gr
+     when (n==value) (Gtk.toggleActionSetActive action True)
+     Gtk.actionGroupAddActionWithAccel self action accelerator
      return (Just action))
     Nothing (zip [0..] entries)
   case mgroup of 
     Nothing -> return Nothing 
     Just gr -> do 
-      connid <- (gr `on` radioActionChanged) onChange
+      connid <- (gr `Gtk.on` Gtk.radioActionChanged) onChange
       return (Just connid)
 
 
 -- | 
-assignViewMode :: EventVar -> RadioAction -> IO ()
+assignViewMode :: EventVar -> Gtk.RadioAction -> IO ()
 assignViewMode evar a = viewModeToUserEvent a >>= eventHandler evar . UsrEv
     
 -- | 
-assignPenMode :: EventVar -> RadioAction -> IO ()
+assignPenMode :: EventVar -> Gtk.RadioAction -> IO ()
 assignPenMode evar a = do 
-    v <- radioActionGetCurrentValue a
+    v <- Gtk.radioActionGetCurrentValue a
     eventHandler evar (UsrEv (AssignPenMode (int2PenType v)))
 
       
 -- | 
-assignColor :: EventVar -> RadioAction -> IO () 
+assignColor :: EventVar -> Gtk.RadioAction -> IO () 
 assignColor evar a = do 
-    v <- radioActionGetCurrentValue a
+    v <- Gtk.radioActionGetCurrentValue a
     let c = int2Color v
     eventHandler evar (UsrEv (PenColorChanged c))
 
 -- | 
-assignPoint :: EventVar -> RadioAction -> IO ()  
+assignPoint :: EventVar -> Gtk.RadioAction -> IO ()  
 assignPoint evar a = do 
-    v <- radioActionGetCurrentValue a
+    v <- Gtk.radioActionGetCurrentValue a
     eventHandler evar (UsrEv (PenWidthChanged v))
 
 
 -- | 
-assignBkgStyle :: EventVar -> RadioAction -> IO ()
+assignBkgStyle :: EventVar -> Gtk.RadioAction -> IO ()
 assignBkgStyle evar a = do 
-    v <- radioActionGetCurrentValue a 
+    v <- Gtk.radioActionGetCurrentValue a 
     let sty = int2BkgStyle v 
     eventHandler evar (UsrEv (BackgroundStyleChanged sty))
 
 -- | 
+assignNewPageMode :: EventVar -> Gtk.RadioAction -> IO ()
+assignNewPageMode evar a = do 
+    v <- Gtk.radioActionGetCurrentValue a
+    eventHandler evar (UsrEv (AssignNewPageMode (int2NewPageMode v)))
+
+
+-- | 
 int2PenType :: Int -> Either PenType SelectType 
 int2PenType 0 = Left PenWork
 int2PenType 1 = Left EraserWork
@@ -656,3 +689,17 @@
 int2BkgStyle 2 = BkgStyleRuled
 int2BkgStyle 3 = BkgStyleGraph
 int2BkgStyle _ = BkgStyleRuled 
+
+
+-- | 
+int2NewPageMode :: Int -> NewPageModeType
+int2NewPageMode 0 = NPPlain
+int2NewPageMode 1 = NPLast
+int2NewPageMode 2 = NPCycle
+int2NewPageMode _ = error "No such new page mode"
+
+-- |
+newPageMode2Int :: NewPageModeType -> Int
+newPageMode2Int NPPlain = 0
+newPageMode2Int NPLast  = 1
+newPageMode2Int NPCycle = 2
diff --git a/src/Hoodle/GUI/Reflect.hs b/src/Hoodle/GUI/Reflect.hs
--- a/src/Hoodle/GUI/Reflect.hs
+++ b/src/Hoodle/GUI/Reflect.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE RankNTypes #-}
 {-# LANGUAGE ScopedTypeVariables #-}
@@ -7,7 +8,7 @@
 -- Module      : Hoodle.GUI.Reflect
 -- Copyright   : (c) 2013, 2014 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -16,85 +17,85 @@
 
 module Hoodle.GUI.Reflect where
 
-import           Control.Lens (view,Simple,Lens)
-import           Control.Monad (liftM, when)
-import qualified Control.Monad.State as St
-import           Control.Monad.Trans 
+import           Control.Lens (view, Simple,Lens, (^.), (.~), _1,_2,_3)
+import           Control.Monad.State as St
 import           Data.Array.MArray
-import           Data.Foldable (forM_)
+import qualified Data.Foldable as F (forM_,mapM_) 
 import qualified Data.Map as M (lookup)
 import           Data.Word
-import           Graphics.UI.Gtk hiding (get,set)
-import qualified Graphics.UI.Gtk as Gtk (set)
+import qualified Graphics.UI.Gtk as Gtk
 --
-import Hoodle.GUI.Menu 
-import Hoodle.Coroutine.Draw
-import Hoodle.Type.Canvas
-import Hoodle.Type.Coroutine
-import Hoodle.Type.Enum 
-import Hoodle.Type.Event
-import Hoodle.Type.HoodleState
-import Hoodle.Type.PageArrangement
-import Hoodle.Type.Predefined 
-import Hoodle.Util 
-import Hoodle.View.Coordinate
+import           Hoodle.Accessor
+import           Hoodle.Coroutine.Draw
+import           Hoodle.GUI.Menu 
+import           Hoodle.Type.Canvas
+import           Hoodle.Type.Coroutine
+import           Hoodle.Type.Enum 
+import           Hoodle.Type.Event
+import           Hoodle.Type.HoodleState
+import           Hoodle.Type.PageArrangement
+import           Hoodle.Type.Predefined 
+import           Hoodle.Util 
+import           Hoodle.View.Coordinate
 -- 
-import Debug.Trace
+-- import Debug.Trace
 
 -- | 
-changeCurrentCanvasId :: CanvasId -> MainCoroutine HoodleState 
+changeCurrentCanvasId :: CanvasId -> MainCoroutine UnitHoodle
 changeCurrentCanvasId cid = do 
-    xstate1 <- St.get
-    maybe (return xstate1) 
-          (\xst -> do St.put xst 
-                      return xst)
-          (setCurrentCanvasId cid xstate1)
-    reflectViewModeUI
-    St.get     
+    xst <- St.get
+    let uhdl = view (unitHoodles.currentUnit) xst
+    case setCurrentCanvasId cid uhdl of
+      Nothing -> return uhdl
+      Just uhdl' -> do 
+        pureUpdateUhdl (const uhdl')
+        reflectViewModeUI
+        return uhdl'
 
+
 -- | check current canvas id and new active canvas id and invalidate if it's 
 --   changed. 
 chkCvsIdNInvalidate :: CanvasId -> MainCoroutine () 
 chkCvsIdNInvalidate cid = do 
-  currcid <- liftM (getCurrentCanvasId) St.get 
+  currcid <- liftM (getCurrentCanvasId . view (unitHoodles.currentUnit) ) St.get 
   when (currcid /= cid) (changeCurrentCanvasId cid >> invalidateAll)
 
+-- | block signal for act
+blockWhile :: (Gtk.GObjectClass w) => Maybe (Gtk.ConnectId w) -> IO () -> IO ()
+blockWhile msig act = do
+    F.mapM_ (\_ -> print "signal will be blocked") msig
+    F.mapM_ Gtk.signalBlock msig >> act >> F.mapM_ Gtk.signalUnblock msig
 
-blockWhile :: (GObjectClass w) => Maybe (ConnectId w) -> IO () -> IO ()
-blockWhile msig act = 
-  maybe (return ()) signalBlock msig
-  >> act 
-  >> maybe (return ()) signalUnblock msig
-  
 
 -- | reflect view mode UI for current canvas info 
 reflectViewModeUI :: MainCoroutine ()
 reflectViewModeUI = do 
     xstate <- St.get
-    let cinfobox = view currentCanvasInfo xstate 
-        ui = view gtkUIManager xstate       
+    let uhdl = view (unitHoodles.currentUnit) xstate
+        cinfobox = view currentCanvasInfo uhdl
+        ui = view gtkUIManager xstate
     let mconnid = view (uiComponentSignalHandler.pageModeSignal) xstate
-    agr <- liftIO $ uiManagerGetActionGroups ui
+    agr <- liftIO $ Gtk.uiManagerGetActionGroups ui
     ra1 <- maybe (error "reflectUI") return =<< 
-             liftIO (actionGroupGetAction (head agr) "ONEPAGEA")
-    let wra1 = castToRadioAction ra1 
+             liftIO (Gtk.actionGroupGetAction (head agr) "ONEPAGEA")
+    let wra1 = Gtk.castToRadioAction ra1 
     unboxBiAct (pgmodupdate_s mconnid wra1) (pgmodupdate_c mconnid wra1) cinfobox 
     return ()
   where pgmodupdate_s mconnid wra1 _cinfo = do
           liftIO $ blockWhile mconnid $
-                     Gtk.set wra1 [radioActionCurrentValue := 1 ] 
+                     Gtk.set wra1 [Gtk.radioActionCurrentValue Gtk.:= 1 ] 
         pgmodupdate_c mconnid wra1 _cinfo = do
           liftIO $ blockWhile mconnid $ 
-                     Gtk.set wra1 [radioActionCurrentValue := 0 ] 
+                     Gtk.set wra1 [Gtk.radioActionCurrentValue Gtk.:= 0 ] 
 
 -- | 
 reflectPenModeUI :: MainCoroutine ()
 reflectPenModeUI = do 
-    reflectUIComponent penModeSignal "PENA" f
-    reflectCursor
+    reflectUIRadio penModeSignal "PENA" f
+    reflectCursor False
   where 
     f xst = Just $
-      hoodleModeStateEither (view hoodleModeState xst) #  
+      hoodleModeStateEither ((view hoodleModeState . view (unitHoodles.currentUnit)) xst) #  
         either (\_ -> (penType2Int. Left .view (penInfo.penType)) xst)
                (\_ -> (penType2Int. Right .view (selectInfo.selectType)) xst)
 
@@ -102,8 +103,8 @@
 -- | 
 reflectPenColorUI :: MainCoroutine () 
 reflectPenColorUI = do 
-    reflectUIComponent penColorSignal "BLUEA" f
-    reflectCursor
+    reflectUIRadio penColorSignal "BLUEA" f
+    reflectCursor False
   where 
     f xst = 
       let mcolor = 
@@ -117,8 +118,8 @@
 -- | 
 reflectPenWidthUI :: MainCoroutine () 
 reflectPenWidthUI = do 
-    reflectUIComponent penPointSignal "PENVERYFINEA" f
-    reflectCursor
+    reflectUIRadio penPointSignal "PENVERYFINEA" f
+    reflectCursor False
   where 
     f xst = 
       case view (penInfo.penType) xst of 
@@ -127,103 +128,125 @@
         HighlighterWork -> 
           let x = (Just . point2Int HighlighterWork 
                             . view (penInfo.penSet.currHighlighter.penWidth)) xst
-              y = view (penInfo.penSet.currHighlighter.penWidth) xst
-          in trace (" x= " ++ show x ++ " y = " ++ show y ) x 
+              -- y = view (penInfo.penSet.currHighlighter.penWidth) xst
+          in x 
         EraserWork -> (Just . point2Int EraserWork 
                        . view (penInfo.penSet.currEraser.penWidth)) xst
         _ -> Nothing 
 
+-- |
+reflectNewPageModeUI :: MainCoroutine ()
+reflectNewPageModeUI = 
+    reflectUIRadio newPageModeSignal "NEWPAGEPLAINA" (Just . newPageMode2Int . (^. settings.newPageMode))
+
 -- | 
-reflectUIComponent :: Simple Lens UIComponentSignalHandler (Maybe (ConnectId RadioAction))
-                   -> String 
-                   -> (HoodleState -> Maybe Int)   
-                   -> MainCoroutine ()
-reflectUIComponent lnz name f = do 
+reflectUIRadio :: Simple Lens UIComponentSignalHandler (Maybe (Gtk.ConnectId Gtk.RadioAction))
+               -> String 
+               -> (HoodleState -> Maybe Int)   
+               -> MainCoroutine ()
+reflectUIRadio lnz name f = do 
     xst <- St.get 
     let ui = view gtkUIManager xst 
         mconnid = view (uiComponentSignalHandler.lnz) xst 
-    agr <- liftIO $ uiManagerGetActionGroups ui 
-    Just pma <- liftIO $ actionGroupGetAction (head agr) name 
-    let wpma = castToRadioAction pma 
+    agr <- liftIO $ Gtk.uiManagerGetActionGroups ui 
+    Just pma <- liftIO $ Gtk.actionGroupGetAction (head agr) name 
+    let wpma = Gtk.castToRadioAction pma 
     update xst wpma mconnid   
   where update xst wpma mconnid  = do 
           (f xst) # 
-            (maybe (return ()) $ \v -> do
-              doIOaction $ \_evhandler -> do 
-                    blockWhile mconnid 
-                      (Gtk.set wpma [radioActionCurrentValue := v ] )
-                    return (UsrEv ActionOrdered)
-              go)
-         where go = do r <- nextevent
-                       case r of
-                         ActionOrdered -> return ()
-                         _ -> go 
+            (maybe (return ()) $ \v ->
+              doIOaction_ $ blockWhile mconnid (Gtk.set wpma [Gtk.radioActionCurrentValue Gtk.:= v ] )
+            )
 
+
+-- | this function must be moved to GUI.Reflect
+reflectUIToggle :: Gtk.UIManager -> String -> Bool -> IO ()
+reflectUIToggle ui str b = do 
+    agr <- Gtk.uiManagerGetActionGroups ui >>= \x -> 
+      case x of
+        [] -> error "No action group?"
+        y:_ -> return y
+    Just savea <- Gtk.actionGroupGetAction agr str -- ("SAVEA" :: String)
+    Gtk.actionSetSensitive savea b
+
 -- | 
-reflectCursor :: MainCoroutine () 
-reflectCursor = do 
+reflectCursor :: Bool -> MainCoroutine () 
+reflectCursor isforced = do 
     xst <- St.get 
-    let useVCursor = view (settings.doesUseVariableCursor) xst 
-    let go = do r <- nextevent 
-                case r of
-                  ActionOrdered -> return ()
-                  _ -> go 
-    if useVCursor 
-      then 
-        act xst >> go 
-      else do 
-        doIOaction $ \_ -> do
-          let cinfobox   = view currentCanvasInfo xst           
-              canvas     = forBoth' unboxBiAct (view drawArea) cinfobox           
-          win <- widgetGetDrawWindow canvas
-          postGUIAsync (drawWindowSetCursor win Nothing) 
-          return (UsrEv ActionOrdered)
-        go 
- where act xst = doIOaction $ \_ -> do 
-         let -- mcur       = view cursorInfo xst 
-             cinfobox   = view currentCanvasInfo xst 
-             canvas     = forBoth' unboxBiAct (view drawArea) cinfobox 
-             cpn        = PageNum $ 
-                            forBoth' unboxBiAct (view currentPageNum) cinfobox
-             pinfo = view penInfo xst 
-             pcolor = view (penSet . currPen . penColor) pinfo
-             pwidth = view (penSet . currPen . penWidth) pinfo 
-         win <- widgetGetDrawWindow canvas
-         dpy <- widgetGetDisplay canvas  
-         
-         geometry <- 
-           forBoth' unboxBiAct (\c -> let arr = view (viewInfo.pageArrangement) c
-                                      in makeCanvasGeometry cpn arr canvas
-                               ) cinfobox
-         let p2c = desktop2Canvas geometry . page2Desktop geometry
-             CvsCoord (x0,_y0) = p2c (cpn, PageCoord (0,0))  
-             CvsCoord (x1,_y1) = p2c (cpn, PageCoord (pwidth,pwidth))
-             cursize = (x1-x0) 
-             (r,g,b,a) = case pcolor of  
-                           ColorRGBA r' g' b' a' -> (r',g',b',a')
-                           _ -> maybe (0,0,0,1) id (M.lookup pcolor penColorRGBAmap)
-         pb <- pixbufNew ColorspaceRgb True 8 maxCursorWidth maxCursorHeight 
-         let numPixels = maxCursorWidth*maxCursorHeight
-         pbData <- (pixbufGetPixels pb :: IO (PixbufData Int Word8))
-         forM_ [0..numPixels-1] $ \i -> do 
-           let cvt :: Double -> Word8
-               cvt x | x < 0.0039 = 0
-                     | x > 0.996  = 255
-                     | otherwise  = fromIntegral (floor (x*256-1) `mod` 256 :: Int)
-           if (fromIntegral (i `mod` maxCursorWidth)) < cursize 
-              && (fromIntegral (i `div` maxCursorWidth)) < cursize 
-             then do 
-               writeArray pbData (4*i)   (cvt r)
-               writeArray pbData (4*i+1) (cvt g)                  
-               writeArray pbData (4*i+2) (cvt b)
-               writeArray pbData (4*i+3) (cvt a)
-             else do
-               writeArray pbData (4*i)   0
-               writeArray pbData (4*i+1) 0
-               writeArray pbData (4*i+2) 0
-               writeArray pbData (4*i+3) 0
-            
-         postGUIAsync . drawWindowSetCursor win . Just =<< 
-           cursorNewFromPixbuf dpy pb 
-             (floor cursize `div` 2) (floor cursize `div` 2)
-         return (UsrEv ActionOrdered)
+    let b = view (settings.doesUseVariableCursor) xst
+        pinfo = view penInfo xst 
+        pcolor = view (penSet . currPen . penColor) pinfo
+        pwidth = view (penSet . currPen . penWidth) pinfo 
+        cinfo = view cursorInfo xst
+        (ccolor,cwidth,cvar) = cinfo
+    when (pcolor /= ccolor || pwidth /= cwidth || b /= cvar || isforced) $ do
+      msgShout "reflectCursor: change cursor"
+      put . (cursorInfo._1 .~ pcolor) . (cursorInfo._2 .~ pwidth) . (cursorInfo._3 .~ b) $ xst 
+      doIOaction_ $ if b  
+                      then varyCursor xst 
+                      else do let uhdl       = view (unitHoodles.currentUnit) xst
+                                  cinfobox   = view currentCanvasInfo uhdl           
+                                  canvas     = forBoth' unboxBiAct (view drawArea) cinfobox
+#ifdef GTK3
+                              Just win <- Gtk.widgetGetWindow canvas
+#else
+                              win <- Gtk.widgetGetDrawWindow canvas
+#endif
+                              Gtk.postGUIAsync (Gtk.drawWindowSetCursor win Nothing) 
+                              return (UsrEv ActionOrdered)
+ where 
+   varyCursor xst = do 
+     putStrLn "reflectCursor : inside act"
+
+     -- Gtk.postGUIAsync $ do 
+     let uhdl = view (unitHoodles.currentUnit) xst
+         -- mcur       = view cursorInfo xst 
+         cinfobox   = view currentCanvasInfo uhdl
+         canvas     = forBoth' unboxBiAct (view drawArea) cinfobox 
+         cpn        = PageNum $ 
+                        forBoth' unboxBiAct (view currentPageNum) cinfobox
+         pinfo = view penInfo xst 
+         pcolor = view (penSet . currPen . penColor) pinfo
+         pwidth = view (penSet . currPen . penWidth) pinfo 
+#ifdef GTK3
+     Just win <- Gtk.widgetGetWindow canvas
+#else
+     win <- Gtk.widgetGetDrawWindow canvas
+#endif
+     dpy <- Gtk.widgetGetDisplay canvas  
+
+     geometry <- 
+       forBoth' unboxBiAct (\c -> let arr = view (viewInfo.pageArrangement) c
+                                  in makeCanvasGeometry cpn arr canvas
+                           ) cinfobox
+     let p2c = desktop2Canvas geometry . page2Desktop geometry
+         CvsCoord (x0,_y0) = p2c (cpn, PageCoord (0,0))  
+         CvsCoord (x1,_y1) = p2c (cpn, PageCoord (pwidth,pwidth))
+         cursize = (x1-x0) 
+         (r,g,b,a) = case pcolor of  
+                       ColorRGBA r' g' b' a' -> (r',g',b',a')
+                       _ -> maybe (0,0,0,1) id (M.lookup pcolor penColorRGBAmap)
+     pb <- Gtk.pixbufNew Gtk.ColorspaceRgb True 8 maxCursorWidth maxCursorHeight 
+     let numPixels = maxCursorWidth*maxCursorHeight
+     pbData <- (Gtk.pixbufGetPixels pb :: IO (Gtk.PixbufData Int Word8))
+     F.forM_ [0..numPixels-1] $ \i -> do 
+       let cvt :: Double -> Word8
+           cvt x | x < 0.0039 = 0
+                 | x > 0.996  = 255
+                 | otherwise  = fromIntegral (floor (x*256-1) `mod` 256 :: Int)
+       if (fromIntegral (i `mod` maxCursorWidth)) < cursize 
+          && (fromIntegral (i `div` maxCursorWidth)) < cursize 
+         then do 
+           writeArray pbData (4*i)   (cvt r)
+           writeArray pbData (4*i+1) (cvt g)                  
+           writeArray pbData (4*i+2) (cvt b)
+           writeArray pbData (4*i+3) (cvt a)
+         else do
+           writeArray pbData (4*i)   0
+           writeArray pbData (4*i+1) 0
+           writeArray pbData (4*i+2) 0
+           writeArray pbData (4*i+3) 0
+
+     Gtk.drawWindowSetCursor win . Just =<< 
+       Gtk.cursorNewFromPixbuf dpy pb (floor cursize `div` 2) (floor cursize `div` 2)
+     return (UsrEv ActionOrdered)
diff --git a/src/Hoodle/ModelAction/Adjustment.hs b/src/Hoodle/ModelAction/Adjustment.hs
--- a/src/Hoodle/ModelAction/Adjustment.hs
+++ b/src/Hoodle/ModelAction/Adjustment.hs
@@ -1,7 +1,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.ModelAction.Adjustment 
--- Copyright   : (c) 2011, 2012 Ian-Woo Kim
+-- Copyright   : (c) 2011,2012,2014 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
@@ -13,7 +13,8 @@
 module Hoodle.ModelAction.Adjustment where
 
 -- from other package
-import Graphics.UI.Gtk 
+import qualified Data.Foldable as F (mapM_)
+import qualified Graphics.UI.Gtk as Gtk
 -- from hoodle-platform 
 import Data.Hoodle.BBox (BBox(..))
 import Data.Hoodle.Simple (Dimension(..))
@@ -24,31 +25,30 @@
 -- | adjust values, upper limit and page size according to canvas geometry 
 
 adjustScrollbarWithGeometry :: CanvasGeometry 
-                               -> ((Adjustment,Maybe (ConnectId Adjustment))
-                                  ,(Adjustment,Maybe (ConnectId Adjustment))) 
+                               -> ((Gtk.Adjustment,Maybe (Gtk.ConnectId Gtk.Adjustment))
+                                  ,(Gtk.Adjustment,Maybe (Gtk.ConnectId Gtk.Adjustment))) 
                                -> IO ()
 adjustScrollbarWithGeometry geometry ((hadj,mconnidh),(vadj,mconnidv)) = do 
   let DesktopDimension (Dim w h) = desktopDim geometry 
       ViewPortBBox (BBox (x0,y0) (x1,y1)) = canvasViewPort geometry 
       xsize = x1-x0
       ysize = y1-y0 
-  maybe (return ()) signalBlock mconnidh
-  maybe (return ()) signalBlock mconnidv
-  adjustmentSetUpper hadj w 
-  adjustmentSetUpper vadj h 
-  adjustmentSetValue hadj x0 
-  adjustmentSetValue vadj y0
-  adjustmentSetPageSize hadj xsize -- (min xsize w)
-  adjustmentSetPageSize vadj ysize --  (min ysize h)
-  adjustmentSetPageIncrement hadj (xsize*0.9)
-  adjustmentSetPageIncrement vadj (ysize*0.9)
-  maybe (return ()) signalUnblock mconnidh
-  maybe (return ()) signalUnblock mconnidv
+  F.mapM_ Gtk.signalBlock mconnidh
+  F.mapM_ Gtk.signalBlock mconnidv
+  Gtk.adjustmentSetUpper hadj w 
+  Gtk.adjustmentSetUpper vadj h 
+  Gtk.adjustmentSetValue hadj x0 
+  Gtk.adjustmentSetValue vadj y0
+  Gtk.adjustmentSetPageSize hadj xsize -- (min xsize w)
+  Gtk.adjustmentSetPageSize vadj ysize --  (min ysize h)
+  Gtk.adjustmentSetPageIncrement hadj (xsize*0.9)
+  Gtk.adjustmentSetPageIncrement vadj (ysize*0.9)
+  F.mapM_ Gtk.signalUnblock mconnidh
+  F.mapM_ Gtk.signalUnblock mconnidv
 
 -- | 
-
-setAdjustments :: ((Adjustment,Maybe (ConnectId Adjustment))
-                  ,(Adjustment,Maybe (ConnectId Adjustment))) 
+setAdjustments :: ((Gtk.Adjustment,Maybe (Gtk.ConnectId Gtk.Adjustment))
+                  ,(Gtk.Adjustment,Maybe (Gtk.ConnectId Gtk.Adjustment))) 
                   -> (Double,Double) 
                   -> (Double,Double)
                   -> (Double,Double) 
@@ -57,18 +57,18 @@
 setAdjustments ((hadj,mconnidh),(vadj,mconnidv)) 
                (upperx,uppery) (lowerx,lowery) 
                (valuex,valuey) (pagex,pagey) = do 
-    maybe (return ()) signalBlock mconnidh
-    maybe (return ()) signalBlock mconnidv
-    adjustmentSetUpper hadj upperx 
-    adjustmentSetUpper vadj uppery 
-    adjustmentSetLower hadj lowerx
-    adjustmentSetLower vadj lowery
-    adjustmentSetValue hadj valuex
-    adjustmentSetValue vadj valuey 
-    adjustmentSetPageSize hadj pagex
-    adjustmentSetPageSize vadj pagey
-    maybe (return ()) signalUnblock mconnidh
-    maybe (return ()) signalUnblock mconnidv
+    F.mapM_ Gtk.signalBlock mconnidh
+    F.mapM_ Gtk.signalBlock mconnidv
+    Gtk.adjustmentSetUpper hadj upperx 
+    Gtk.adjustmentSetUpper vadj uppery 
+    Gtk.adjustmentSetLower hadj lowerx
+    Gtk.adjustmentSetLower vadj lowery
+    Gtk.adjustmentSetValue hadj valuex
+    Gtk.adjustmentSetValue vadj valuey 
+    Gtk.adjustmentSetPageSize hadj pagex
+    Gtk.adjustmentSetPageSize vadj pagey
+    F.mapM_ Gtk.signalUnblock mconnidh
+    F.mapM_ Gtk.signalUnblock mconnidv
     
 
      
diff --git a/src/Hoodle/ModelAction/Clipboard.hs b/src/Hoodle/ModelAction/Clipboard.hs
--- a/src/Hoodle/ModelAction/Clipboard.hs
+++ b/src/Hoodle/ModelAction/Clipboard.hs
@@ -20,7 +20,7 @@
 import qualified Data.ByteString.Base64 as B64 
 import qualified Data.ByteString.Char8 as C8
 import qualified Data.Serialize as Se 
-import           Graphics.UI.Gtk hiding (get,set)
+import qualified Graphics.UI.Gtk as Gtk
 -- from hoodle-platform 
 import           Data.Hoodle.Simple
 -- import           Graphics.Hoodle.Render.Type
@@ -37,12 +37,10 @@
   | null itms = return xstate
   | otherwise = do 
     let ui = view gtkUIManager xstate
-    hdltag <- atomNew "hoodle"
-    -- tgttag <- atomNew "Stroke"
-    -- seltag <- atomNew "Stroke"
-    clipbd <- clipboardGet hdltag
+    hdltag <- Gtk.atomNew "hoodle"
+    clipbd <- Gtk.clipboardGet hdltag
     let bstr = C8.unpack . B64.encode . Se.encode $ itms 
-    clipboardSetText clipbd bstr
+    Gtk.clipboardSetText clipbd bstr
     togglePaste ui True 
     case (view hookSet xstate) of 
       Nothing -> return () 
diff --git a/src/Hoodle/ModelAction/ContextMenu.hs b/src/Hoodle/ModelAction/ContextMenu.hs
--- a/src/Hoodle/ModelAction/ContextMenu.hs
+++ b/src/Hoodle/ModelAction/ContextMenu.hs
@@ -1,11 +1,13 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.ModelAction.ContextMenu
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -14,17 +16,20 @@
 
 module Hoodle.ModelAction.ContextMenu where
 
-import           Control.Concurrent (forkIO, threadDelay)
 import qualified Data.ByteString.Char8 as B
-import           Data.Foldable (forM_)
 import           Data.UUID.V4
-import           DBus 
-import           DBus.Client 
 import qualified Graphics.Rendering.Cairo as Cairo
-import           Graphics.UI.Gtk
+import qualified Graphics.UI.Gtk as Gtk
 import           System.Directory 
 import           System.FilePath 
+#ifdef HUB
+import           Control.Concurrent (forkIO, threadDelay)
+import           Control.Exception
+import           Data.Foldable (forM_)
+import           DBus 
+import           DBus.Client 
 import           System.Process
+#endif
 -- 
 import           Data.Hoodle.BBox
 import           Data.Hoodle.Simple
@@ -35,56 +40,58 @@
 import Hoodle.Util
 
 -- |
-menuOpenALink :: UrlPath -> IO MenuItem
-menuOpenALink urlpath = do 
+menuOpenALink :: (AllEvent -> IO ()) -> UrlPath -> IO Gtk.MenuItem
+menuOpenALink evhandler urlpath = do 
     let urlname = case urlpath of 
                     FileUrl fp -> fp 
                     HttpUrl url -> url 
-    menuitemlnk <- menuItemNewWithLabel ("Open "++urlname) 
-    menuitemlnk `on` menuItemActivate $ openLinkAction urlpath Nothing
+    menuitemlnk <- Gtk.menuItemNewWithLabel ("Open "++urlname :: String) 
+    menuitemlnk `Gtk.on` Gtk.menuItemActivate $ evhandler (UsrEv (OpenLink urlpath Nothing)) 
     return menuitemlnk
 
-
 -- | 
-openLinkAction :: UrlPath 
+#ifdef HUB
+openLinkActionDBus :: UrlPath 
                -> Maybe (B.ByteString,B.ByteString) -- ^ (docid,anchorid)
                -> IO () 
-openLinkAction urlpath mid = do
-    cli <- connectSession
-    case urlpath of 
-      FileUrl fp -> do 
-        putStrLn "test dbus"
-        emit cli (signal "/" "org.ianwookim.hoodle" "findWindow") 
-                   { signalBody = [ toVariant fp] }         
-        return () 
-      HttpUrl url -> do 
-        let cmdargs = [url]
-        createProcess (proc "xdg-open" cmdargs)  
-        return () 
-    forkIO $ do 
-      threadDelay 2000000
-      forM_ mid $ \(docid,anchorid) -> do
-                  print (docid,anchorid)
-                  emit cli (signal "/" "org.ianwookim.hoodle" "callLink")
-                             { signalBody = 
-                                 [ toVariant (B.unpack docid 
-                                              ++ "," 
-                                              ++ B.unpack anchorid) ] }
-    return ()
+openLinkActionDBus urlpath mid = do
+    flip catch (\(ex :: SomeException) -> print ex ) $ do
+      cli <- connectSession
+      case urlpath of 
+        FileUrl fp -> do 
+          emit cli (signal "/" "org.ianwookim.hoodle" "findWindow") { signalBody = [ toVariant fp] }         
+          return () 
+        HttpUrl url -> do 
+          let cmdargs = [url]
+          createProcess (proc "xdg-open" cmdargs)  
+          return () 
+      forkIO $ do 
+        threadDelay 2000000
+        forM_ mid $ \(docid,anchorid) -> do
+                    print (docid,anchorid)
+                    emit cli (signal "/" "org.ianwookim.hoodle" "callLink")
+                               { signalBody = 
+                                   [ toVariant (B.unpack docid 
+                                                ++ "," 
+                                                ++ B.unpack anchorid) ] }
+      return ()
+#endif
+
+
 -- | 
-menuCreateALink :: (AllEvent -> IO ()) -> [RItem] -> IO (Maybe MenuItem)
+menuCreateALink :: (AllEvent -> IO ()) -> [RItem] -> IO (Maybe Gtk.MenuItem)
 menuCreateALink evhandler sitems = 
   if (length . filter isLinkInRItem) sitems > 0
   then return Nothing 
-  else do mi <- menuItemNewWithLabel "Create a link to..." 
-          mi `on` menuItemActivate $ 
+  else do mi <- Gtk.menuItemNewWithLabel ("Create a link to..." :: String)
+          mi `Gtk.on` Gtk.menuItemActivate $ 
             evhandler (UsrEv (GotContextMenuSignal CMenuCreateALink))
           return (Just mi)
          
 
 -- |
-makeSVGFromSelection :: RenderCache -> [RItem] -> BBox -> IO SVG 
-makeSVGFromSelection cache hititms (BBox (ulx,uly) (lrx,lry)) = do 
+makeSVGFromSelection :: RenderCache -> CanvasId -> [RItem] -> BBox -> IO SVG 
+makeSVGFromSelection cache cid hititms (BBox (ulx,uly) (lrx,lry)) = do 
   uuid <- nextRandom
   tdir <- getTemporaryDirectory
   let filename = tdir </> show uuid <.> "svg"
@@ -92,7 +99,7 @@
       (w,h) = (lrx-ulx,lry-uly)
   Cairo.withSVGSurface filename w h $ \s -> Cairo.renderWith s $ do 
     Cairo.translate (-ulx) (-uly) 
-    mapM_ (renderRItem cache) hititms 
+    mapM_ (renderRItem cache cid) hititms 
   bstr <- B.readFile filename
   let svg = SVG Nothing Nothing bstr (x,y) (Dim w h)
   svg `seq` removeFile filename 
diff --git a/src/Hoodle/ModelAction/File.hs b/src/Hoodle/ModelAction/File.hs
--- a/src/Hoodle/ModelAction/File.hs
+++ b/src/Hoodle/ModelAction/File.hs
@@ -5,9 +5,9 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.ModelAction.File 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -19,16 +19,15 @@
 -- from other package
 import           Control.Applicative
 import           Control.Lens (view,set)
-import           Data.Attoparsec 
+import           Data.Attoparsec.ByteString.Char8
 import           Data.ByteString.Base64 
 import qualified Data.ByteString.Char8 as C
 import qualified Data.ByteString.Lazy.Char8 as L
-import qualified Data.IntMap as IM
 import           Data.Maybe 
 import           Data.Monoid ((<>))
 import           Data.Time.Clock
+import qualified Data.Traversable as T
 import           Graphics.GD.ByteString 
-import           Graphics.UI.Gtk hiding (get,set)
 import qualified Graphics.UI.Gtk.Poppler.Document as Poppler
 import qualified Graphics.UI.Gtk.Poppler.Page as PopplerPage
 import           System.Directory (canonicalizePath)
@@ -36,14 +35,14 @@
 import           System.IO (hClose, hFileSize, openFile, IOMode(..)) 
 import           System.Process
 -- from hoodle-platform 
-import           Data.Hoodle.Generic
 import           Data.Hoodle.Simple
 import           Graphics.Hoodle.Render.Background
-import           Graphics.Hoodle.Render.Type.Background 
 import           Graphics.Hoodle.Render.Type.Hoodle
 import           Text.Hoodle.Builder (builder)
 import qualified Text.Hoodle.Parse.Attoparsec as PA
-import qualified Text.Hoodle.Migrate.V0_1_1_to_V0_2 as MV
+import qualified Text.Hoodle.Migrate.V0_2_2_to_V0_3 as MV
+-- import qualified Data.Hoodle.Simple.V0_3 as V0_3
+import qualified Text.Hoodle.Migrate.V0_3_to_HEAD as MVHEAD
 -- from this package
 import           Hoodle.Type.HoodleState
 import           Hoodle.Util
@@ -54,33 +53,56 @@
   case parseOnly PA.checkHoodleVersion bstr of 
     Left str -> error str 
     Right v -> do 
-      if ( v <= "0.1.1" ) 
-        then MV.migrate bstr
+      if ( v <= "0.2.2" ) 
+        then T.traverse MVHEAD.hoodle2Hoodle =<< (MV.migrate bstr)
         else return (parseOnly PA.hoodle bstr)
 
 -- | this is very temporary, need to be changed.     
-findFirstPDFFile :: [(Int,RPage)] -> Maybe C.ByteString
-findFirstPDFFile xs = let ys = (filter isJust . map f) xs 
-                      in if null ys then Nothing else head ys 
-  where f (_,p) = case view gbackground p of 
-                    RBkgPDF _ fi _ _ _ -> Just fi
-                    _ -> Nothing 
+findFirstPDFFile :: [Page] -> Maybe C.ByteString
+findFirstPDFFile xs = let ys = mapMaybe f xs 
+                      in listToMaybe ys
+  where f :: Page -> Maybe C.ByteString
+        f p = case page_bkg p of
+                BackgroundPdf _ _ fi _ -> fi
+                _ -> Nothing
+
       
-findAllPDFPages :: [(Int,RPage)] -> [Int]
+findAllPDFPages :: [Page] -> [Int]
 findAllPDFPages = catMaybes . map f
-  where f (n,p) = case view gbackground p of 
-                    RBkgPDF _ _ _ _ _ -> Just n
-                    _ -> Nothing 
+  where f p = case page_bkg p of 
+                     BackgroundPdf _ _ _ n -> Just n
+                     _ -> Nothing
 
-replacePDFPages :: [(Int,RPage)] -> [(Int,RPage)] 
+replacePDFPages :: [Page] -> [Page] 
 replacePDFPages xs = map f xs 
-  where f (n,p) = case view gbackground p of 
-          RBkgPDF _ _ pdfn mpdf msfc -> (n, set gbackground (RBkgEmbedPDF pdfn mpdf msfc) p)
-          _ -> (n,p) 
+  where f p = let bkg = page_bkg p
+              in case bkg of    
+                   BackgroundPdf typ _ _ pdfn -> p { page_bkg = BackgroundEmbedPdf typ pdfn }
+                   _ -> p
         
 -- | 
-embedPDFInHoodle :: RHoodle -> IO RHoodle
-embedPDFInHoodle hdl = do 
+embedPDFInHoodle :: Hoodle -> IO Hoodle -- RHoodle -> IO RHoodle
+embedPDFInHoodle hdl = putStrLn "embedPDFInHoodle is now bugful. I do not do anything here " >> return hdl
+{-    let pgsWnum = zip [0..] (hoodle_pages hdl)
+        mfn = findFirstPDFFile (hoodle_pages hdl)
+        allpdfpg = findAllPDFPages pgs 
+    case mfn of 
+      Nothing -> return hdl 
+      Just fn -> do 
+        let fnstr = C.unpack fn 
+            pglst = map show allpdfpg 
+            cmdargs =  [fnstr, "cat"] ++ pglst ++ ["output", "-"]
+        -- print cmdargs 
+        (_,Just hout,_,_) <- createProcess (proc "pdftk" cmdargs) { std_out = CreatePipe } 
+        bstr <- C.hGetContents hout
+        let ebdsrc = makeEmbeddedPdfSrcString bstr 
+            npgs = (IM.fromAscList . replacePDFPages pgs 
+    
+            nhdl0 = rHoodle2Hoodle . (gpages .~ npgs) $ hdl
+            nhdl1 = nhdl0 { hoodle_embeddedpdf = Just ebdsrc }
+        cnstrctRHoodle nhdl1
+-}
+{-
     let pgs = (IM.toAscList . view gpages) hdl  
         mfn = findFirstPDFFile pgs
         allpdfpg = findAllPDFPages pgs 
@@ -97,7 +119,7 @@
         let ebdsrc = makeEmbeddedPdfSrcString bstr 
             npgs = (IM.fromAscList . replacePDFPages) pgs 
         (return . set gembeddedpdf (Just ebdsrc) . set gpages npgs) hdl
-
+-}
 
 
 makeEmbeddedPdfSrcString :: C.ByteString -> C.ByteString 
@@ -172,27 +194,18 @@
                    
 
 -- | 
-saveHoodle :: HoodleState -> IO HoodleState 
-saveHoodle xstate = do 
-    let hdl = (rHoodle2Hoodle . getHoodle) xstate 
-    case view (hoodleFileControl.hoodleFileName) xstate of 
-      Nothing -> return xstate 
-      Just filename -> do 
-        L.writeFile filename . builder $ hdl
-        ctime <- getCurrentTime 
-        let ui = view gtkUIManager xstate
-        toggleSave ui False
-        return (set isSaved True . set (hoodleFileControl.lastSavedTime) (Just ctime) $ xstate )
-             
--- | this function must be moved to GUI.Reflect
-toggleSave :: UIManager -> Bool -> IO ()
-toggleSave ui b = do 
-    agr <- uiManagerGetActionGroups ui >>= \x -> 
-      case x of
-        [] -> error "No action group?"
-        y:_ -> return y
-    Just savea <- actionGroupGetAction agr "SAVEA"
-    actionSetSensitive savea b
+saveHoodle :: UnitHoodle -> IO UnitHoodle
+saveHoodle uhdl = do 
+    let hdl = (rHoodle2Hoodle . getHoodle) uhdl 
+    case view (hoodleFileControl.hoodleFileName) uhdl of 
+      LocalDir Nothing -> return uhdl 
+      LocalDir (Just filename) -> action hdl filename 
+      TempDir filename -> action hdl filename 
+  where 
+    action hdl filename = do 
+      L.writeFile filename . builder $ hdl
+      ctime <- getCurrentTime 
+      return (set isSaved True . set (hoodleFileControl.lastSavedTime) (Just ctime) $ uhdl)
 
 -- | 
 makeNewItemImage :: Bool  -- ^ isEmbedded?
@@ -216,7 +229,6 @@
                                              (fromIntegral h * 72 / 90) 
                   | w >= h = Dim 300 (fromIntegral h*300/fromIntegral w)
                   | otherwise = Dim (fromIntegral w*300/fromIntegral h) 300 
-          -- bstr <- savePngByteString img 
           bstr <- C.readFile filename 
           let b64str = encode bstr 
               ebdsrc = "data:image/png;base64," <> b64str
diff --git a/src/Hoodle/ModelAction/Layer.hs b/src/Hoodle/ModelAction/Layer.hs
--- a/src/Hoodle/ModelAction/Layer.hs
+++ b/src/Hoodle/ModelAction/Layer.hs
@@ -1,7 +1,9 @@
+{-# LANGUAGE CPP #-}
+
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.ModelAction.Layer 
--- Copyright   : (c) 2011-2013 Ian-Woo Kim
+-- Copyright   : (c) 2011-2014 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
@@ -16,8 +18,7 @@
 import           Control.Category
 import           Control.Lens (view,over)
 import           Data.IORef
-import           Graphics.UI.Gtk hiding (get,set)
-import qualified Graphics.UI.Gtk as Gtk (get)
+import qualified Graphics.UI.Gtk as Gtk
 -- from hoodle-platform 
 import           Data.Hoodle.Generic
 import           Data.Hoodle.Zipper
@@ -41,23 +42,28 @@
 
 
 -- | 
-layerChooseDialog :: IORef Int -> Int -> Int -> IO Dialog
+layerChooseDialog :: IORef Int -> Int -> Int -> IO Gtk.Dialog
 layerChooseDialog layernumref cidx len = do 
-    dialog <- dialogNew 
-    layerentry <- entryNew
-    entrySetText layerentry (show (succ cidx))
-    label <- labelNew (Just (" / " ++ show len))
-    hbox <- hBoxNew False 0 
-    upper <- dialogGetUpper dialog
-    boxPackStart upper hbox PackNatural 0 
-    boxPackStart hbox layerentry PackNatural 0 
-    boxPackStart hbox label PackGrow 0 
-    widgetShowAll upper
-    buttonOk <- dialogAddButton dialog stockOk ResponseOk
-    _buttonCancel <- dialogAddButton dialog stockCancel ResponseCancel
+    dialog <- Gtk.dialogNew 
+    layerentry <- Gtk.entryNew
+    Gtk.entrySetText layerentry (show (succ cidx))
+    label <- Gtk.labelNew (Just (" / " ++ show len))
+    hbox <- Gtk.hBoxNew False 0 
+#ifdef GTK3    
+    upper <- fmap Gtk.castToContainer (Gtk.dialogGetContentArea dialog)
+    Gtk.containerAdd upper hbox
+#else
+    upper <- Gtk.dialogGetUpper dialog
+    Gtk.boxPackStart upper hbox Gtk.PackNatural 0 
+#endif
+    Gtk.boxPackStart hbox layerentry Gtk.PackNatural 0 
+    Gtk.boxPackStart hbox label Gtk.PackGrow 0 
+    Gtk.widgetShowAll upper
+    buttonOk <- Gtk.dialogAddButton dialog Gtk.stockOk Gtk.ResponseOk
+    _buttonCancel <- Gtk.dialogAddButton dialog Gtk.stockCancel Gtk.ResponseCancel
 
-    buttonOk `on` buttonActivated $ do 
-      txt <- Gtk.get layerentry entryText
+    buttonOk `Gtk.on` Gtk.buttonActivated $ do 
+      txt <- Gtk.get layerentry Gtk.entryText
       maybe (return ()) (modifyIORef layernumref . const . pred) . maybeRead $ txt
     return dialog
 
diff --git a/src/Hoodle/ModelAction/Page.hs b/src/Hoodle/ModelAction/Page.hs
--- a/src/Hoodle/ModelAction/Page.hs
+++ b/src/Hoodle/ModelAction/Page.hs
@@ -4,9 +4,9 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.ModelAction.Page 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -21,12 +21,10 @@
 import           Data.Functor.Identity (Identity(..))
 import qualified Data.IntMap as M
 import           Data.Traversable (mapM)
-import           Graphics.UI.Gtk (adjustmentGetValue)
+import qualified Graphics.UI.Gtk as Gtk (adjustmentGetValue)
 -- from hoodle-platform
 import           Data.Hoodle.Generic
 import           Data.Hoodle.Select
--- import           Data.Hoodle.Zipper 
--- import           Graphics.Hoodle.Render.Type
 -- from this package
 import           Hoodle.Util
 import           Hoodle.Type.Alias
@@ -52,13 +50,13 @@
   . hoodleModeStateEither
   
 -- |
-updatePageAll :: HoodleModeState -> HoodleState -> IO HoodleState
-updatePageAll hdlmodst xstate = do 
-  let cmap = getCanvasInfoMap xstate
+updatePageAll :: HoodleModeState -> UnitHoodle -> IO UnitHoodle
+updatePageAll hdlmodst uhdl = do 
+  let cmap = view cvsInfoMap uhdl
   cmap' <- mapM (updatePage hdlmodst . adjustPage hdlmodst) cmap
-  return $ maybe xstate id 
+  return $ maybe uhdl id 
            . setCanvasInfoMap cmap' 
-           . set hoodleModeState hdlmodst $ xstate
+           . set hoodleModeState hdlmodst $ uhdl
 
 -- | 
 adjustPage :: HoodleModeState -> CanvasInfoBox -> CanvasInfoBox  
@@ -94,7 +92,7 @@
         pg = getPageFromGHoodleMap pagenum hdl 
         pdim = PageDimension $ view gdimension pg
         (hadj,vadj) = view adjustments cinfo
-    (xpos,ypos) <- (,) <$> adjustmentGetValue hadj <*> adjustmentGetValue vadj 
+    (xpos,ypos) <- (,) <$> Gtk.adjustmentGetValue hadj <*> Gtk.adjustmentGetValue vadj 
     let arr = makeSingleArrangement zmode pdim cdim (xpos,ypos)
         vinfo = view viewInfo cinfo 
         nvinfo = xfrmViewInfo (const arr) vinfo
@@ -108,8 +106,8 @@
         canvas = view drawArea cinfo 
         zmode = view (viewInfo.zoomMode) cinfo
         (hadj,vadj) = view adjustments cinfo
-    (xdesk,ydesk) <- (,) <$> adjustmentGetValue hadj 
-                         <*> adjustmentGetValue vadj 
+    (xdesk,ydesk) <- (,) <$> Gtk.adjustmentGetValue hadj 
+                         <*> Gtk.adjustmentGetValue vadj 
     geometry <- makeCanvasGeometry (PageNum pagenum) oarr canvas 
     case desktop2Page geometry (DeskCoord (xdesk,ydesk)) of
       Nothing -> return (CanvasContPage cinfo)
@@ -131,19 +129,19 @@
     updateCvsInfoFrmHoodle hdl c
 
 -- | 
-setPage :: HoodleState -> PageNum -> CanvasId -> IO CanvasInfoBox
-setPage xstate pnum cid = do  
-  let cinfobox =  getCanvasInfo cid xstate
-  unboxBiAct (liftM CanvasSinglePage . setPageSingle xstate pnum) 
-             (liftM CanvasContPage . setPageCont xstate pnum)
+setPage :: UnitHoodle -> PageNum -> CanvasId -> IO CanvasInfoBox
+setPage uhdl pnum cid = do  
+  let cinfobox =  getCanvasInfo cid uhdl
+  unboxBiAct (liftM CanvasSinglePage . setPageSingle uhdl pnum) 
+             (liftM CanvasContPage . setPageCont uhdl pnum)
              cinfobox
 
 -- | setPageSingle : in Single Page mode   
-setPageSingle :: HoodleState -> PageNum  
+setPageSingle :: UnitHoodle -> PageNum  
               -> CanvasInfo SinglePage
               -> IO (CanvasInfo SinglePage)
-setPageSingle xstate pnum cinfo = do 
-  let hdl = getHoodle xstate
+setPageSingle uhdl pnum cinfo = do 
+  let hdl = getHoodle uhdl
   geometry <- getCvsGeomFrmCvsInfo cinfo
   let cdim = canvasDim geometry 
   let pg = getPageFromGHoodleMap (unPageNum pnum) hdl
@@ -154,20 +152,17 @@
            . set (viewInfo.pageArrangement) arr $ cinfo 
 
 -- | setPageCont : in Continuous Page mode   
-setPageCont :: HoodleState -> PageNum  
+setPageCont :: UnitHoodle -> PageNum  
             -> CanvasInfo ContinuousPage
             -> IO (CanvasInfo ContinuousPage)
-setPageCont xstate pnum cinfo = do 
-  let hdl = getHoodle xstate
+setPageCont uhdl pnum cinfo = do 
+  let hdl = getHoodle uhdl
   geometry <- getCvsGeomFrmCvsInfo cinfo
   let cdim = canvasDim geometry 
       zmode = view (viewInfo.zoomMode) cinfo
       arr = makeContinuousArrangement zmode cdim hdl (pnum,PageCoord (0,0))  
   return $ set currentPageNum (unPageNum pnum)
            . set (viewInfo.pageArrangement) arr $ cinfo 
-
-  
-
 
 -- | need to be refactored into zoomRatioFrmRelToCurr (rename zoomRatioRelPredefined)
 relZoomRatio :: CanvasGeometry -> ZoomModeRel -> Double
diff --git a/src/Hoodle/ModelAction/Pen.hs b/src/Hoodle/ModelAction/Pen.hs
--- a/src/Hoodle/ModelAction/Pen.hs
+++ b/src/Hoodle/ModelAction/Pen.hs
@@ -3,7 +3,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.ModelAction.Pen 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
@@ -14,26 +14,17 @@
 
 module Hoodle.ModelAction.Pen where
 
-import           Control.Lens (view,set,over)
+import           Control.Lens (view)
 import           Control.Monad (when)
-import           Control.Monad.Identity (runIdentity)
 import           Data.Foldable
-import qualified Data.IntMap as IM
 import           Data.Sequence hiding (take, drop)
 import           Data.Strict.Tuple hiding (uncurry)
 import qualified Graphics.Rendering.Cairo as Cairo
 -- from hoodle-platform 
-import           Data.Hoodle.BBox
-import           Data.Hoodle.Generic
 import           Data.Hoodle.Simple
-import           Graphics.Hoodle.Render
-import           Graphics.Hoodle.Render.Type
 -- from this package 
-import           Hoodle.ModelAction.Layer
-import           Hoodle.ModelAction.Page
 import           Hoodle.Type.Canvas
 import           Hoodle.Type.Enum
-import           Hoodle.Type.PageArrangement
 --
 
 data TempRender a = TempRender { tempSurfaceSrc :: Cairo.Surface  
@@ -65,7 +56,7 @@
       ptool = case ptype of 
                   PenWork -> "pen" 
                   HighlighterWork -> "highlighter"
-                  _ -> error "error in addPDraw"
+                  _ -> error "error in createNewStroke"
       
       newstroke = 
         case pvwpen of 
@@ -78,25 +69,4 @@
                            , stroke_vwdata = map (\(x,y,z)->(x,y,pwidth*z)) . toList $ pdraw }
   in newstroke 
 
-
--- | 
-addPDraw :: RenderCache
-         -> PenInfo 
-         -> RHoodle
-         -> PageNum 
-         -> Seq (Double,Double,Double) 
-         -> IO (RHoodle,BBox) -- ^ new hoodle and bbox in page coordinate
-addPDraw cache pinfo hdl (PageNum pgnum) pdraw = do 
-    let currpage = getPageFromGHoodleMap pgnum hdl
-        currlayer = getCurrentLayer currpage
-        dim = view gdimension currpage
-        newstroke = createNewStroke pinfo pdraw         
-        newstrokebbox = runIdentity (makeBBoxed newstroke)
-        bbox = getBBox newstrokebbox
-    newlayerbbox <- updateLayerBuf cache dim (Just bbox)
-                    . over gitems (++[RItemStroke newstrokebbox]) 
-                    $ currlayer
-    let newpagebbox = adjustCurrentLayer newlayerbbox currpage 
-        newhdlbbox = set gpages (IM.adjust (const newpagebbox) pgnum (view gpages hdl) ) hdl 
-    return (newhdlbbox,bbox)
 
diff --git a/src/Hoodle/ModelAction/Select.hs b/src/Hoodle/ModelAction/Select.hs
--- a/src/Hoodle/ModelAction/Select.hs
+++ b/src/Hoodle/ModelAction/Select.hs
@@ -27,7 +27,7 @@
 import           Data.Time.Clock
 import qualified Graphics.Rendering.Cairo as Cairo
 import           Graphics.Rendering.Cairo.Matrix ( invert, transformPoint )
-import           Graphics.UI.Gtk hiding (get,set)
+import qualified Graphics.UI.Gtk as Gtk
 -- from hoodle-platform
 import           Data.Hoodle.Generic
 import           Data.Hoodle.BBox
@@ -65,10 +65,10 @@
 -- |                     
 scaleFromToBBox :: BBox -> BBox -> (Double,Double) -> (Double,Double)
 scaleFromToBBox (BBox (ox1,oy1) (ox2,oy2)) (BBox (nx1,ny1) (nx2,ny2)) (x,y) = 
-  let scalex = (nx2-nx1) / (ox2-ox1)
-      scaley = (ny2-ny1) / (oy2-oy1) 
-      nx = (x-ox1)*scalex+nx1
-      ny = (y-oy1)*scaley+ny1
+  let sx = (nx2-nx1) / (ox2-ox1)
+      sy = (ny2-ny1) / (oy2-oy1) 
+      nx = (x-ox1)*sx+nx1
+      ny = (y-oy1)*sy+ny1
   in (nx,ny)
 
 -- |
@@ -86,17 +86,13 @@
   where coordtrans (x,y) = unCvsCoord . desktop2Canvas geometry . page2Desktop geometry 
                            $ (pnum,PageCoord (x,y))
 
---       nbbox = bboxFromImage nimg
---  in ImageBBox nimg nbbox
-
-
 -- |
 getSelectedItms :: Page SelectMode -> [RItem]
 getSelectedItms = either (const []) (concatMap unHitted . getB) . rItmsInActiveLyr   
 -- |
-getSelectedItmsFromHoodleState :: HoodleState -> Maybe [RItem] 
-getSelectedItmsFromHoodleState xstate = 
-  case view hoodleModeState xstate of 
+getSelectedItmsFromUnitHoodle :: UnitHoodle -> Maybe [RItem] 
+getSelectedItmsFromUnitHoodle uhdl = 
+  case view hoodleModeState uhdl of 
     ViewAppendState _ -> Nothing 
     SelectState thdl -> fmap (getSelectedItms.Prelude.snd) (view gselSelected thdl)
   
@@ -124,30 +120,17 @@
 
 
 
+
 -- |
 updateTempHoodleSelect :: Hoodle SelectMode -> Page SelectMode -> Int 
                            -> Hoodle SelectMode 
 updateTempHoodleSelect thdl tpage pagenum =                
   let pgs = view gselAll thdl 
       pgs' = M.adjust (const (hPage2RPage tpage)) pagenum pgs
-  in set gselAll pgs' 
-     . set gselSelected (Just (pagenum,tpage))
-     $ thdl 
-     
--- |
-updateTempHoodleSelectIO :: RenderCache 
-                         -> Hoodle SelectMode 
-                         -> Page SelectMode 
-                         -> Int
-                         -> IO (Hoodle SelectMode)
-updateTempHoodleSelectIO cache thdl tpage pagenum = do   
-  let pgs = view gselAll thdl 
-  newpage <- (updatePageBuf cache . hPage2RPage) tpage
-  let pgs' = M.adjust (const newpage) pagenum pgs
-  return $  set gselAll pgs' 
-            . set gselSelected (Just (pagenum,tpage))
-            $ thdl 
+  in set gselAll pgs' . set gselSelected (Just (pagenum,tpage)) $ thdl 
+
   
+  
 -- |   
 calculateWholeBBox :: [BBoxed Stroke] -> Maybe BBox  
 calculateWholeBBox = toMaybe . mconcat . map ( Union . Middle. getBBox ) 
@@ -181,27 +164,27 @@
     
 
 -- |
-toggleCutCopyDelete :: UIManager -> Bool -> IO ()
+toggleCutCopyDelete :: Gtk.UIManager -> Bool -> IO ()
 toggleCutCopyDelete ui b = do 
-    agr <- uiManagerGetActionGroups ui >>= \x -> 
+    agr <- Gtk.uiManagerGetActionGroups ui >>= \x -> 
       case x of
         [] -> error "No action group?"
         y:_ -> return y
-    Just deletea <- actionGroupGetAction agr "DELETEA"
-    Just copya <- actionGroupGetAction agr "COPYA"
-    Just cuta <- actionGroupGetAction agr "CUTA"
+    Just deletea <- Gtk.actionGroupGetAction agr "DELETEA"
+    Just copya <- Gtk.actionGroupGetAction agr "COPYA"
+    Just cuta <- Gtk.actionGroupGetAction agr "CUTA"
     let copycutdeletea = [copya,cuta,deletea] 
-    mapM_ (flip actionSetSensitive b) copycutdeletea
+    mapM_ (flip Gtk.actionSetSensitive b) copycutdeletea
 
 -- |
-togglePaste :: UIManager -> Bool -> IO ()
+togglePaste :: Gtk.UIManager -> Bool -> IO ()
 togglePaste ui b = do 
-    agr <- uiManagerGetActionGroups ui >>= \x -> 
+    agr <- Gtk.uiManagerGetActionGroups ui >>= \x -> 
       case x of
         [] -> error "No action group?"
         y:_ -> return y
-    Just pastea <- actionGroupGetAction agr "PASTEA"
-    actionSetSensitive pastea b
+    Just pastea <- Gtk.actionGroupGetAction agr "PASTEA"
+    Gtk.actionSetSensitive pastea b
 
 -- |
 changeStrokeColor :: PenColor -> BBoxed Stroke -> BBoxed Stroke
@@ -349,10 +332,10 @@
 
 
 -- | 
-mkItmsNImg :: RenderCache -> Page SelectMode -> IO ItmsNImg
-mkItmsNImg cache tpage = do 
+mkItmsNImg :: RenderCache -> CanvasId -> Page SelectMode -> IO ItmsNImg
+mkItmsNImg cache cid tpage = do 
     let itms = getSelectedItms tpage
-        drawselection = mapM_ (renderRItem cache) itms 
+        drawselection = mapM_ (renderRItem cache cid) itms 
         Dim cw ch = view gdimension tpage 
         mbbox = case getULBBoxFromSelected tpage of 
                   Middle bbox -> Just bbox 
diff --git a/src/Hoodle/ModelAction/Text.hs b/src/Hoodle/ModelAction/Text.hs
--- a/src/Hoodle/ModelAction/Text.hs
+++ b/src/Hoodle/ModelAction/Text.hs
@@ -5,7 +5,7 @@
 -- Module      : Hoodle.ModelAction.File 
 -- Copyright   : (c) 2011-2014 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -17,10 +17,8 @@
 import           Control.Applicative
 import           Data.Attoparsec.Text as A
 import           Data.Char (isAlphaNum)
-import qualified Data.Map as M
+import qualified Data.HashMap.Strict as M
 import qualified Data.Text as T
-import qualified Data.Text.Encoding as TE
-import qualified Data.Text.IO as TIO
 --
 import Debug.Trace
 
@@ -38,7 +36,7 @@
 -}
 
 -- | 
-getKeywordMap :: T.Text -> M.Map T.Text T.Text
+getKeywordMap :: T.Text -> M.HashMap T.Text T.Text
 getKeywordMap txt = case parseOnly (many keywordContents) txt of 
                       Left err -> trace (show err) $ M.empty
                       Right lst -> M.fromList lst
@@ -69,6 +67,11 @@
     txt <- T.unlines <$> manyTill oneline keywordEnd
     return (k,txt)
 
-
+-- |
+extractKeyword :: T.Text -> Maybe T.Text
+extractKeyword txt = 
+    case T.unpack txt of
+      'e':'m':'b':'e':'d':'l':'a':'t':'e':'x':':':'k':'e':'y':'w':'o':'r':'d':':':xs -> Just (T.pack xs)
+      _ -> Nothing
 
 
diff --git a/src/Hoodle/ModelAction/Window.hs b/src/Hoodle/ModelAction/Window.hs
--- a/src/Hoodle/ModelAction/Window.hs
+++ b/src/Hoodle/ModelAction/Window.hs
@@ -1,12 +1,13 @@
-{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.ModelAction.Window 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -16,28 +17,35 @@
 module Hoodle.ModelAction.Window where
 
 -- from other packages
-import           Control.Concurrent
-import           Control.Concurrent.STM
 import           Control.Lens (view)
-import           Control.Monad
-import           Control.Monad.Trans 
+import           Control.Monad hiding (forM_)
+import           Control.Monad.Trans
+import           Data.Foldable (forM_)
 import qualified Data.IntMap as M
+import           Data.IORef (newIORef, readIORef)
+import           Data.Traversable (traverse)
+import           Data.UUID (UUID)
+import           Data.UUID.V4
+#ifdef HUB
+import           Control.Concurrent
+import           Control.Concurrent.STM
 import           Data.Maybe (mapMaybe)
 import qualified Data.Text as T
-import           DBus
+import           DBus hiding (UUID)
 import           DBus.Client
-import           Graphics.UI.Gtk hiding (get,set)
-import qualified Graphics.UI.Gtk as Gtk (set)
+#endif
+import qualified Graphics.UI.Gtk as Gtk
 import           System.FilePath
 -- from this package
 import           Hoodle.Device
 import           Hoodle.Type.Canvas
 import           Hoodle.Type.Event
-import           Hoodle.Type.Window
 import           Hoodle.Type.HoodleState
+import           Hoodle.Type.Window
 import           Hoodle.Util
 -- 
 
+#ifdef HUB
 getDBUSEvent :: (AllEvent -> IO ()) -> TVar Bool -> IO ()
 getDBUSEvent callback tvar = do
     client <- connectSession
@@ -56,243 +64,280 @@
           let fps = mapMaybe fromVariant (signalBody sig) :: [T.Text]
           b <- atomically (readTVar tvar)  
           when ((not.null) fps && b) $ do  
-            (postGUISync . callback . UsrEv . DBusEv . ImageFileDropped . T.unpack . head) 
+            (Gtk.postGUISync . callback . UsrEv . DBusEv . ImageFileDropped . T.unpack . head) 
               fps
             return ()
         getLaTeX sig = do 
           let latex = mapMaybe fromVariant (signalBody sig) :: [T.Text]
           b <- atomically (readTVar tvar)  
           when ((not.null) latex && b) $ do  
-            (postGUISync . callback . UsrEv . DBusEv . DBusNetworkInput . head) 
+            (Gtk.postGUISync . callback . UsrEv . DBusEv . DBusNetworkInput . head) 
               latex
             return ()
+#endif
 
 -- | set frame title according to file name
 setTitleFromFileName :: HoodleState -> IO () 
 setTitleFromFileName xstate = do 
-  case view (hoodleFileControl.hoodleFileName) xstate of
-    Nothing -> Gtk.set (view rootOfRootWindow xstate) 
-                       [ windowTitle := "untitled" ]
-    Just filename -> Gtk.set (view rootOfRootWindow xstate) 
-                             [ windowTitle := takeFileName filename] 
+  case view (unitHoodles.currentUnit.hoodleFileControl.hoodleFileName) xstate of
+    LocalDir Nothing         -> Gtk.set (view rootOfRootWindow xstate) 
+                                  [ Gtk.windowTitle Gtk.:= ("untitled" :: String) ]
+    LocalDir (Just filename) -> Gtk.set (view rootOfRootWindow xstate) 
+                                  [ Gtk.windowTitle Gtk.:= takeFileName filename] 
+    TempDir  _filename       -> Gtk.set (view rootOfRootWindow xstate) 
+                                  [ Gtk.windowTitle Gtk.:= ("shared document" :: String)]
 
 -- | 
 newCanvasId :: CanvasInfoMap -> CanvasId 
-newCanvasId cmap = 
-  let cids = M.keys cmap 
-  in  (maximum cids) + 1  
+newCanvasId cmap = let cids = M.keys cmap in (maximum cids) + 1  
 
 -- | initialize CanvasInfo with creating windows and connect events
-initCanvasInfo :: HoodleState -> CanvasId -> IO (CanvasInfo a)
-initCanvasInfo xstate cid = 
-  minimalCanvasInfo xstate cid >>= connectDefaultEventCanvasInfo xstate
+initCanvasInfo :: HoodleState -> UnitHoodle -> CanvasId -> IO (CanvasInfo a)
+initCanvasInfo xstate uhdl cid = 
+  minimalCanvasInfo cid >>= connectDefaultEventCanvasInfo xstate uhdl
   
 
 -- | only creating windows 
-minimalCanvasInfo :: HoodleState -> CanvasId -> IO (CanvasInfo a)
-minimalCanvasInfo _xstate cid = do 
-    canvas <- drawingAreaNew
-    scrwin <- scrolledWindowNew Nothing Nothing 
-    containerAdd scrwin canvas
-    hadj <- adjustmentNew 0 0 500 100 200 200 
-    vadj <- adjustmentNew 0 0 500 100 200 200 
-    scrolledWindowSetHAdjustment scrwin hadj 
-    scrolledWindowSetVAdjustment scrwin vadj 
+minimalCanvasInfo :: CanvasId -> IO (CanvasInfo a)
+minimalCanvasInfo cid = do
+    canvas <- Gtk.drawingAreaNew
+    scrwin <- Gtk.scrolledWindowNew Nothing Nothing 
+    Gtk.containerAdd scrwin canvas
+    hadj <- Gtk.adjustmentNew 0 0 500 100 200 200 
+    vadj <- Gtk.adjustmentNew 0 0 500 100 200 200 
+    Gtk.scrolledWindowSetHAdjustment scrwin hadj 
+    Gtk.scrolledWindowSetVAdjustment scrwin vadj 
     return $ CanvasInfo cid canvas Nothing scrwin (error "no viewInfo" :: ViewInfo a) 0 hadj vadj Nothing Nothing defaultCanvasWidgets Nothing 
 
 
 -- | only connect events 
-
 connectDefaultEventCanvasInfo 
-  :: HoodleState -> CanvasInfo a -> IO (CanvasInfo a )
-connectDefaultEventCanvasInfo xstate cinfo = do 
+  :: HoodleState -> UnitHoodle -> CanvasInfo a -> IO (CanvasInfo a )
+connectDefaultEventCanvasInfo xstate _uhdl cinfo = do 
     let callback = view callBack xstate
+        ui = view gtkUIManager xstate 
         dev = view deviceList xstate 
         canvas = _drawArea cinfo 
         cid = _canvasId cinfo 
         scrwin = _scrolledWindow cinfo
         hadj = _horizAdjustment cinfo 
-        vadj = _vertAdjustment cinfo 
-
-    widgetSetCanFocus canvas True 
-    widgetGrabFocus canvas     
-    
-    _sizereq <- canvas `on` sizeRequest $ return (Requisition 800 400)    
-    
-    _keyevent <- canvas `on` keyPressEvent $ tryEvent $ do 
-      m <- eventModifier
-      n <- eventKeyName 
+        vadj = _vertAdjustment cinfo
+    Gtk.widgetSetCanFocus canvas True 
+    Gtk.widgetGrabFocus canvas     
+#ifdef GTK3
+    {- 
+#endif
+    _sizereq <- canvas `Gtk.on` Gtk.sizeRequest $ return (Gtk.Requisition 800 400)
+    _keyevent <- canvas `Gtk.on` Gtk.keyPressEvent $ Gtk.tryEvent $ do 
+      m <- Gtk.eventModifier
+      n <- Gtk.eventKeyName 
       let keystr = show m ++ ":" ++ show n
       liftIO $ (callback (UsrEv (CustomKeyEvent keystr)))
-    _bpevent <- canvas `on` buttonPressEvent $ tryEvent $ do 
-                 liftIO $ widgetGrabFocus canvas 
-                 (mbtn,mp) <- getPointer dev
-                 case mp of 
-                   Nothing -> return ()
-                   Just p -> do 
-                     let pbtn = maybe PenButton1 id mbtn
-                     case pbtn of 
-                       TouchButton -> liftIO (callback (UsrEv (TouchDown cid p)))
-                       _ -> liftIO (callback (UsrEv (PenDown cid pbtn p)))
-    _confevent <- canvas `on` configureEvent $ tryEvent $ do 
-                   (w,h) <- eventSize 
-                   liftIO $ callback (UsrEv (CanvasConfigure cid (fromIntegral w) (fromIntegral h)))
-    _brevent <- canvas `on` buttonReleaseEvent $ tryEvent $ do 
+    _bpevent <- canvas `Gtk.on` Gtk.buttonPressEvent $ Gtk.tryEvent $ do 
+                 liftIO $ Gtk.widgetGrabFocus canvas 
                  (mbtn,mp) <- getPointer dev
-                 case mp of 
-                   Nothing -> return () 
-                   Just p -> do
-                     let pbtn = maybe PenButton1 id mbtn
-                     case pbtn of 
-                       TouchButton -> (liftIO . callback . UsrEv) (TouchUp cid p)
-                       _ -> (liftIO . callback . UsrEv) (PenUp cid p)
-                       
+                 forM_ mp $ \p -> do 
+                   let pbtn = maybe PenButton1 id mbtn
+                   case pbtn of 
+                     TouchButton -> liftIO (callback (UsrEv (TouchDown cid p)))
+                     _ -> liftIO (callback (UsrEv (PenDown cid pbtn p)))
+    _confevent <- canvas `Gtk.on` Gtk.configureEvent $ Gtk.tryEvent $ do 
+                    (w,h) <- Gtk.eventSize 
+                    liftIO $ callback (UsrEv (CanvasConfigure cid (fromIntegral w) (fromIntegral h)))
+    _brevent <- canvas `Gtk.on` Gtk.buttonReleaseEvent $ Gtk.tryEvent $ do 
+                  (mbtn,mp) <- getPointer dev
+                  forM_ mp $ \p -> do 
+                    let pbtn = maybe PenButton1 id mbtn
+                    case pbtn of 
+                      TouchButton -> (liftIO . callback . UsrEv) (TouchUp cid p)
+                      _ -> (liftIO . callback . UsrEv) (PenUp cid p)
+#ifdef HUB
     tvar <- newTVarIO False 
     forkIO $ getDBUSEvent callback tvar
-    _focus <- canvas `on` focusInEvent $ tryEvent $ liftIO $ do
+    _focus <- canvas `Gtk.on` Gtk.focusInEvent $ Gtk.tryEvent $ liftIO $ do
                 atomically (writeTVar tvar True)
-                widgetGrabFocus canvas 
-    _focusout <- canvas `on` focusOutEvent $ tryEvent $ liftIO $ atomically (writeTVar tvar False)
-    _exposeev <- canvas `on` exposeEvent $ tryEvent $ do 
-      liftIO $ widgetGrabFocus canvas       
+                Gtk.widgetGrabFocus canvas 
+    _focusout <- canvas `Gtk.on` Gtk.focusOutEvent $ Gtk.tryEvent $ liftIO $ atomically (writeTVar tvar False)
+#endif
+
+
+#ifdef GTK3
+    _exposeev <- canvas `Gtk.on` Gtk.draw $ do 
+#else
+    _exposeev <- canvas `Gtk.on` Gtk.exposeEvent $ Gtk.tryEvent $ do 
+#endif
+      liftIO $ Gtk.widgetGrabFocus canvas       
       (liftIO . callback . UsrEv) (UpdateCanvas cid) 
-    canvas `on` motionNotifyEvent $ tryEvent $ do 
+    canvas `Gtk.on` Gtk.motionNotifyEvent $ Gtk.tryEvent $ do 
       (mbtn,mp) <- getPointer dev
-      case mp of 
-        Nothing -> return ()
-        Just p -> do 
-          let pbtn = maybe PenButton1 id mbtn      
-          case pbtn of 
-            TouchButton -> (liftIO . callback . UsrEv) (TouchMove cid p) 
-            _ -> (liftIO . callback . UsrEv) (PenMove cid p)
-
+      forM_ mp $ \p -> do
+        let pbtn = maybe PenButton1 id mbtn      
+        case pbtn of 
+          TouchButton -> (liftIO . callback . UsrEv) (TouchMove cid p) 
+          _ -> (liftIO . callback . UsrEv) (PenMove cid p)
     -- drag and drop setting
-    dragDestSet canvas [DestDefaultMotion, DestDefaultDrop] [ActionCopy]
-    dragDestAddTextTargets canvas
-    canvas `on` dragDataReceived $ \_dc pos _i _ts -> do 
-      s <- selectionDataGetText 
+    Gtk.dragDestSet canvas [Gtk.DestDefaultMotion, Gtk.DestDefaultDrop] [Gtk.ActionCopy]
+    Gtk.dragDestAddTextTargets canvas
+    canvas `Gtk.on` Gtk.dragDataReceived $ \_dc pos _i _ts -> do 
+      s <- Gtk.selectionDataGetText 
       (liftIO . callback . UsrEv) (GotLink s pos)
       
-    widgetAddEvents canvas [PointerMotionMask,Button1MotionMask,KeyPressMask]      
-    let ui = view gtkUIManager xstate 
-    agr <- liftIO ( uiManagerGetActionGroups ui >>= \x ->
+    Gtk.widgetAddEvents canvas [Gtk.PointerMotionMask,Gtk.Button1MotionMask,Gtk.KeyPressMask]
+    agr <- liftIO ( Gtk.uiManagerGetActionGroups ui >>= \x ->
                       case x of 
                         [] -> error "No action group? "
                         y:_ -> return y )
-    uxinputa <- liftIO (actionGroupGetAction agr "UXINPUTA" >>= \(Just x) -> 
-                          return (castToToggleAction x) )
-    b <- liftIO $ toggleActionGetActive uxinputa
-    if b then widgetSetExtensionEvents canvas [ExtensionEventsAll]
-         else widgetSetExtensionEvents canvas [ExtensionEventsNone]
-    hadjconnid <- afterValueChanged hadj $ do 
-                    v <- adjustmentGetValue hadj 
+    uxinputa <- liftIO (Gtk.actionGroupGetAction agr ("UXINPUTA" :: String) >>= \(Just x) -> 
+                          return (Gtk.castToToggleAction x) )
+    b <- liftIO $ Gtk.toggleActionGetActive uxinputa
+#ifdef GTK3    
+#else
+    if b then Gtk.widgetSetExtensionEvents canvas [Gtk.ExtensionEventsAll]
+         else Gtk.widgetSetExtensionEvents canvas [Gtk.ExtensionEventsNone]
+#endif
+    hadjconnid <- Gtk.afterValueChanged hadj $ do 
+                    v <- Gtk.adjustmentGetValue hadj 
                     (callback . UsrEv) (HScrollBarMoved cid v)
-    vadjconnid <- afterValueChanged vadj $ do 
-                    v <- adjustmentGetValue vadj     
+    vadjconnid <- Gtk.afterValueChanged vadj $ do 
+                    v <- Gtk.adjustmentGetValue vadj     
                     (callback . UsrEv) (VScrollBarMoved cid v)
-    Just vscrbar <- scrolledWindowGetVScrollbar scrwin
-    _bpevtvscrbar <- vscrbar `on` buttonPressEvent $ do 
-                      v <- liftIO $ adjustmentGetValue vadj 
+    Just vscrbar <- Gtk.scrolledWindowGetVScrollbar scrwin
+    _bpevtvscrbar <- vscrbar `Gtk.on` Gtk.buttonPressEvent $ do 
+                      v <- liftIO $ Gtk.adjustmentGetValue vadj 
                       liftIO ((callback . UsrEv) (VScrollBarStart cid v))
                       return False
-    _brevtvscrbar <- vscrbar `on` buttonReleaseEvent $ do 
-                      v <- liftIO $ adjustmentGetValue vadj 
+    _brevtvscrbar <- vscrbar `Gtk.on` Gtk.buttonReleaseEvent $ do 
+                      v <- liftIO $ Gtk.adjustmentGetValue vadj 
                       liftIO ((callback . UsrEv) (VScrollBarEnd cid v))
                       return False
     return $ cinfo { _horizAdjConnId = Just hadjconnid
                    , _vertAdjConnId = Just vadjconnid }
-    
--- | recreate windows from old canvas info but no event connect
+#ifdef GTK3
+    -}
+#endif
+    -- temp
+    return $ cinfo     
 
+-- | recreate windows from old canvas info but no event connect
 reinitCanvasInfoStage1 
-  :: HoodleState -> CanvasInfo a -> IO (CanvasInfo a)
-reinitCanvasInfoStage1 xstate oldcinfo = do 
+  :: UnitHoodle -> CanvasInfo a -> IO (CanvasInfo a)
+reinitCanvasInfoStage1 _uhdl oldcinfo = do 
   let cid = view canvasId oldcinfo 
-  newcinfo <- minimalCanvasInfo xstate cid      
+  newcinfo <- minimalCanvasInfo cid      
   return $ newcinfo { _viewInfo = _viewInfo oldcinfo 
                     , _currentPageNum = _currentPageNum oldcinfo 
                     } 
 
     
 -- | event connect
-
 reinitCanvasInfoStage2 
-  :: HoodleState -> CanvasInfo a -> IO (CanvasInfo a)
-reinitCanvasInfoStage2 = connectDefaultEventCanvasInfo
+  :: HoodleState -> UnitHoodle -> CanvasInfo a -> IO (CanvasInfo a)
+reinitCanvasInfoStage2 = connectDefaultEventCanvasInfo 
     
 -- | event connecting for all windows                          
-                         
-eventConnect :: HoodleState -> WindowConfig 
-                -> IO (HoodleState,WindowConfig)
-eventConnect xstate (Node cid) = do 
-    let cmap = getCanvasInfoMap xstate 
+eventConnect :: HoodleState -> UnitHoodle -> WindowConfig -> IO (UnitHoodle,WindowConfig)
+eventConnect xst uhdl (Node cid) = do 
+    let cmap = view cvsInfoMap uhdl 
         cinfobox = maybeError' "eventConnect" $ M.lookup cid cmap
-    ncinfobox <- forBoth unboxBiXform (reinitCanvasInfoStage2 xstate) cinfobox
-    let xstate' = updateFromCanvasInfoAsCurrentCanvas ncinfobox xstate
-    return (xstate', Node cid)        
-eventConnect xstate (HSplit wconf1 wconf2) = do  
-    (xstate',wconf1') <- eventConnect xstate wconf1 
-    (xstate'',wconf2') <- eventConnect xstate' wconf2 
-    return (xstate'',HSplit wconf1' wconf2')
-eventConnect xstate (VSplit wconf1 wconf2) = do  
-    (xstate',wconf1') <- eventConnect xstate wconf1 
-    (xstate'',wconf2') <- eventConnect xstate' wconf2 
-    return (xstate'',VSplit wconf1' wconf2')
+    ncinfobox <- forBoth unboxBiXform (reinitCanvasInfoStage2 xst uhdl) cinfobox
+    let uhdl' = updateFromCanvasInfoAsCurrentCanvas ncinfobox uhdl
+    return (uhdl', Node cid)        
+eventConnect xst uhdl (HSplit wconf1 wconf2) = do  
+    (uhdl',wconf1') <- eventConnect xst uhdl wconf1 
+    (uhdl'',wconf2') <- eventConnect xst uhdl' wconf2 
+    return (uhdl'',HSplit wconf1' wconf2')
+eventConnect xst uhdl (VSplit wconf1 wconf2) = do  
+    (uhdl',wconf1') <- eventConnect xst uhdl wconf1 
+    (uhdl'',wconf2') <- eventConnect xst uhdl' wconf2 
+    return (uhdl'',VSplit wconf1' wconf2')
     
 -- | default construct frame     
-
-constructFrame :: HoodleState -> WindowConfig 
-                  -> IO (HoodleState,Widget,WindowConfig)
-constructFrame hst wcfg = constructFrame' (CanvasSinglePage defaultCvsInfoSinglePage) hst wcfg 
-
-
+constructFrame :: HoodleState 
+               -> UnitHoodle -> WindowConfig 
+               -> IO (UnitHoodle,Gtk.Widget,WindowConfig)
+constructFrame xst uhdl wcfg = 
+    let callback = view callBack xst
+    in constructFrame' callback (CanvasSinglePage defaultCvsInfoSinglePage) uhdl wcfg 
 
 -- | construct frames with template
-
-constructFrame' :: CanvasInfoBox -> 
-                   HoodleState -> WindowConfig 
-                   -> IO (HoodleState,Widget,WindowConfig)
-constructFrame' template oxstate (Node cid) = do 
-    let ocmap = getCanvasInfoMap oxstate 
-    (cinfobox,_cmap,xstate) <- case M.lookup cid ocmap of 
-      Just cinfobox' -> return (cinfobox',ocmap,oxstate)
+constructFrame' :: (AllEvent -> IO ()) -> CanvasInfoBox -> UnitHoodle -> WindowConfig 
+                -> IO (UnitHoodle,Gtk.Widget,WindowConfig)
+constructFrame' _callback template ouhdl (Node cid) = do 
+    let ocmap = view cvsInfoMap ouhdl
+    (cinfobox,_cmap,uhdl) <- case M.lookup cid ocmap of 
+      Just cinfobox' -> return (cinfobox',ocmap,ouhdl)
       Nothing -> do 
         let cinfobox' = setCanvasId cid template 
             cmap' = M.insert cid cinfobox' ocmap
-            xstate' = maybe oxstate id (setCanvasInfoMap cmap' oxstate)
-        return (cinfobox',cmap',xstate')
-    ncinfobox <- forBoth unboxBiXform (reinitCanvasInfoStage1 xstate) cinfobox
-    let xstate' = updateFromCanvasInfoAsCurrentCanvas ncinfobox xstate
-    let scrwin = forBoth' unboxBiAct (castToWidget.view scrolledWindow) ncinfobox
-    return (xstate', scrwin, Node cid)
-constructFrame' template xstate (HSplit wconf1 wconf2) = do  
-    (xstate',win1,wconf1') <- constructFrame' template xstate wconf1     
-    (xstate'',win2,wconf2') <- constructFrame' template xstate' wconf2 
-    let callback = view callBack xstate'' 
-    hpane' <- hPanedNew
-    hpane' `on` buttonPressEvent $ do 
+            uhdl' = maybe ouhdl id (setCanvasInfoMap cmap' ouhdl)
+        return (cinfobox',cmap',uhdl')
+    ncinfobox <- forBoth unboxBiXform (reinitCanvasInfoStage1 uhdl) cinfobox
+    let uhdl' = updateFromCanvasInfoAsCurrentCanvas ncinfobox uhdl
+    forBoth' unboxBiAct (putStrLn <=< Gtk.widgetGetName . view drawArea) ncinfobox
+    let scrwin = forBoth' unboxBiAct (Gtk.castToWidget.view scrolledWindow) ncinfobox
+    return (uhdl', scrwin, Node cid)
+constructFrame' callback template uhdl (HSplit wconf1 wconf2) = do  
+    (uhdl',win1,wconf1') <- constructFrame' callback template uhdl wconf1
+    (uhdl'',win2,wconf2') <- constructFrame' callback template uhdl' wconf2 
+    hpane' <- Gtk.hPanedNew
+    hpane' `Gtk.on` Gtk.buttonPressEvent $ do 
       liftIO ((callback . UsrEv) PaneMoveStart)
       return False 
-    hpane' `on` buttonReleaseEvent $ do 
+    hpane' `Gtk.on` Gtk.buttonReleaseEvent $ do 
       liftIO ((callback . UsrEv) PaneMoveEnd)
       return False       
-    panedPack1 hpane' win1 True False
-    panedPack2 hpane' win2 True False
-    widgetShowAll hpane' 
-    return (xstate'',castToWidget hpane', HSplit wconf1' wconf2')
-constructFrame' template xstate (VSplit wconf1 wconf2) = do  
-    (xstate',win1,wconf1') <- constructFrame' template xstate wconf1 
-    (xstate'',win2,wconf2') <- constructFrame' template xstate' wconf2 
-    let callback = view callBack xstate''     
-    vpane' <- vPanedNew 
-    vpane' `on` buttonPressEvent $ do 
+    Gtk.panedPack1 hpane' win1 True False
+    Gtk.panedPack2 hpane' win2 True False
+    Gtk.widgetShowAll hpane' 
+    return (uhdl'',Gtk.castToWidget hpane', HSplit wconf1' wconf2')
+constructFrame' callback template uhdl (VSplit wconf1 wconf2) = do  
+    (uhdl',win1,wconf1') <- constructFrame' callback template uhdl wconf1 
+    (uhdl'',win2,wconf2') <- constructFrame' callback template uhdl' wconf2 
+    vpane' <- Gtk.vPanedNew 
+    vpane' `Gtk.on` Gtk.buttonPressEvent $ do 
       liftIO ((callback . UsrEv) PaneMoveStart)
       return False 
-    vpane' `on` buttonReleaseEvent $ do 
+    vpane' `Gtk.on` Gtk.buttonReleaseEvent $ do 
       liftIO ((callback . UsrEv) PaneMoveEnd)
       return False 
-    panedPack1 vpane' win1 True False
-    panedPack2 vpane' win2 True False
-    widgetShowAll vpane' 
-    return (xstate'',castToWidget vpane', VSplit wconf1' wconf2')
+    Gtk.panedPack1 vpane' win1 True False
+    Gtk.panedPack2 vpane' win2 True False
+    Gtk.widgetShowAll vpane' 
+    return (uhdl'',Gtk.castToWidget vpane', VSplit wconf1' wconf2')
   
+registerFrameToContainer :: Gtk.Window -> Gtk.Box -> Gtk.Widget -> IO ()
+registerFrameToContainer rtrwin rtcntr win = do
+    Gtk.boxPackEnd rtcntr win Gtk.PackGrow 0 
+   --  Gtk.widgetShowAll rtcntr  
+    Gtk.widgetShowAll rtrwin
+    Gtk.widgetQueueDraw rtrwin
+
+
+createTab :: (AllEvent -> IO ()) -> Gtk.Notebook -> Gtk.VBox -> IO (Int,UUID,Gtk.Button)
+createTab callback notebook vboxcvs = do
+    hbox <- Gtk.hBoxNew False 0 
+    ebox <- Gtk.eventBoxNew
+    label <- Gtk.labelNew (Just "      " :: Maybe String)
+    Gtk.containerAdd ebox label
+    Gtk.dragSourceSet ebox [Gtk.Button1] [Gtk.ActionCopy]
+    Gtk.dragSourceSetIconStock ebox Gtk.stockIndex
+    Gtk.dragSourceAddTextTargets ebox
+    button <- Gtk.buttonNewWithLabel ("X" :: String)
+    -- Gtk.Gtk.widgetSetSensitive button False
+    Gtk.boxPackStart hbox {- label -} ebox Gtk.PackNatural 0
+    Gtk.boxPackStart hbox button Gtk.PackNatural 0 
+    Gtk.widgetShowAll hbox
+    mlabel <- Gtk.labelNew (Nothing :: Maybe String)
+    n <- Gtk.notebookAppendPageMenu notebook vboxcvs hbox mlabel
+    uuid <- nextRandom
+    button `Gtk.on` Gtk.buttonActivated $ callback (UsrEv (CloseTab uuid))
+
+    -- ebox `Gtk.on` Gtk.dragBegin $ \_dc -> do 
+    --   liftIO $ putStrLn "dragging"
+    ebox `Gtk.on` Gtk.dragDataGet $ \_dc _iid _ts -> do
+      minfo <- liftIO $ do 
+        ref <- newIORef (Nothing :: Maybe String)
+        callback (UsrEv (GetHoodleFileInfoFromTab uuid ref))
+        readIORef ref
+      traverse Gtk.selectionDataSetText minfo >> return ()
+    return (n,uuid,button)
diff --git a/src/Hoodle/Script.hs b/src/Hoodle/Script.hs
--- a/src/Hoodle/Script.hs
+++ b/src/Hoodle/Script.hs
@@ -1,7 +1,9 @@
+{-# LANGUAGE CPP #-}
+
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Script
--- Copyright   : (c) 2012, 2013 Ian-Woo Kim
+-- Copyright   : (c) 2012-2014 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
@@ -13,7 +15,9 @@
 module Hoodle.Script where 
 
 import Hoodle.Script.Hook
+#ifdef DYRE
 import Config.Dyre.Relaunch
+#endif
 
 -- | 
 
@@ -34,10 +38,10 @@
 
 
 -- | 
-
+#ifdef DYRE
 relaunchApplication :: IO ()
 relaunchApplication = do 
   putStrLn "relaunching hoodle!"
   relaunchMaster Nothing 
-  
+#endif
   
diff --git a/src/Hoodle/Script/Coroutine.hs b/src/Hoodle/Script/Coroutine.hs
--- a/src/Hoodle/Script/Coroutine.hs
+++ b/src/Hoodle/Script/Coroutine.hs
@@ -3,7 +3,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Script.Coroutine
--- Copyright   : (c) 2012, 2013 Ian-Woo Kim
+-- Copyright   : (c) 2012-2015 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
@@ -85,3 +85,4 @@
     rfilename <- hoist (H.embedPredefinedImage3Hook hset)
     liftIO rfilename 
   return r   
+
diff --git a/src/Hoodle/Script/Hook.hs b/src/Hoodle/Script/Hook.hs
--- a/src/Hoodle/Script/Hook.hs
+++ b/src/Hoodle/Script/Hook.hs
@@ -1,7 +1,9 @@
+{-# LANGUAGE CPP #-}
+
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Script.Hook
--- Copyright   : (c) 2012, 2013 Ian-Woo Kim
+-- Copyright   : (c) 2012-2015 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
@@ -15,6 +17,9 @@
 import Data.Hoodle.Simple 
 import Graphics.Hoodle.Render.Type.Hoodle
 -- 
+#ifdef HUB
+import Hoodle.Type.Hub
+#endif
 
 -- | 
 data Hook = Hook { saveAsHook :: Maybe (Hoodle -> IO ())
@@ -33,6 +38,10 @@
                  , warningEmbedImageSize :: Maybe Integer
                  , shrinkCmd4EmbedImage :: Maybe (Double -> FilePath -> FilePath -> IO ())  
                  , getIPaddress :: Maybe (IO String)
+#ifdef HUB
+                 , hubInfo :: Maybe HubInfo
+                 , sqliteInfo :: Maybe FilePath
+#endif
                  } 
 
 
@@ -53,4 +62,8 @@
                    , warningEmbedImageSize = Nothing
                    , shrinkCmd4EmbedImage = Nothing
                    , getIPaddress = Nothing
+#ifdef HUB
+                   , hubInfo = Nothing
+                   , sqliteInfo = Nothing
+#endif
                    }
diff --git a/src/Hoodle/Type/Alias.hs b/src/Hoodle/Type/Alias.hs
--- a/src/Hoodle/Type/Alias.hs
+++ b/src/Hoodle/Type/Alias.hs
@@ -3,7 +3,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Type.Alias
--- Copyright   : (c) 2012, 2013 Ian-Woo Kim
+-- Copyright   : (c) 2012-2014 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
diff --git a/src/Hoodle/Type/Canvas.hs b/src/Hoodle/Type/Canvas.hs
--- a/src/Hoodle/Type/Canvas.hs
+++ b/src/Hoodle/Type/Canvas.hs
@@ -75,19 +75,11 @@
 , xfrmCvsInfo
 , xfrmViewInfo
 , getDrawAreaFromBox
--- , unboxGet
--- , unboxSet
 , unboxLens
 , unboxBiAct
 , unboxBiXform
 , forBoth
 , forBoth'
--- , unboxSelect
--- , fmap4CvsInfoBox
--- , insideAction4CvsInfoBox
--- , insideAction4CvsInfoBoxF
--- , boxAction
--- , selectBox
 -- * others
 , updateCanvasDimForSingle
 , updateCanvasDimForContSingle
@@ -98,12 +90,13 @@
 import qualified Data.IntMap as M
 import           Data.Sequence
 import qualified Graphics.Rendering.Cairo as Cairo
-import           Graphics.UI.Gtk hiding (get,set)
+import qualified Graphics.UI.Gtk as Gtk
 -- 
 import           Data.Hoodle.Simple (Dimension(..))
 import           Data.Hoodle.BBox
 import           Data.Hoodle.Predefined 
 import           Graphics.Hoodle.Render.Type.Item
+import           Graphics.Hoodle.Render.Type.Renderer
 --
 import           Hoodle.Type.Enum 
 import           Hoodle.Type.PageArrangement
@@ -112,9 +105,6 @@
 
 
 -- |
-type CanvasId = Int 
-
--- |
 data PenDraw = PenDraw { _points :: Seq (Double,Double) } 
              deriving (Show)
 
@@ -138,9 +128,7 @@
 emptyPenDraw :: PenDraw
 emptyPenDraw = PenDraw empty
 
-
 -- | default view info with single page mode
-
 defaultViewInfoSinglePage :: ViewInfo SinglePage
 defaultViewInfoSinglePage = 
   ViewInfo { _zoomMode = Original 
@@ -157,20 +145,18 @@
 pageArrangement :: Simple Lens (ViewInfo a) (PageArrangement a)
 pageArrangement = lens _pageArrangement (\f a -> f { _pageArrangement = a })
 
-
-
 -- |
 data CanvasInfo (a :: ViewMode) = 
        CanvasInfo { _canvasId :: CanvasId
-                  , _drawArea :: DrawingArea
+                  , _drawArea :: Gtk.DrawingArea
                   , _mDrawSurface :: Maybe Cairo.Surface 
-                  , _scrolledWindow :: ScrolledWindow
+                  , _scrolledWindow :: Gtk.ScrolledWindow
                   , _viewInfo :: ViewInfo a
                   , _currentPageNum :: Int
-                  , _horizAdjustment :: Adjustment
-                  , _vertAdjustment :: Adjustment 
-                  , _horizAdjConnId :: Maybe (ConnectId Adjustment)
-                  , _vertAdjConnId :: Maybe (ConnectId Adjustment)
+                  , _horizAdjustment :: Gtk.Adjustment
+                  , _vertAdjustment :: Gtk.Adjustment 
+                  , _horizAdjConnId :: Maybe (Gtk.ConnectId Gtk.Adjustment)
+                  , _vertAdjConnId :: Maybe (Gtk.ConnectId Gtk.Adjustment)
                   , _canvasWidgets :: CanvasWidgets
                   , _notifiedItem :: Maybe (PageNum,BBox,RItem) 
                   }
@@ -196,8 +182,8 @@
 -- |     
 defaultCvsInfoSinglePage :: CanvasInfo SinglePage
 defaultCvsInfoSinglePage = 
-  CanvasInfo { _canvasId = error "cvsid"
-             , _drawArea = error "DrawingArea"
+  CanvasInfo { _canvasId = error "defaultCvsInfoSinglePage cvsid"
+             , _drawArea = error "defaultCvsInfoSinglePage DrawingArea"
              , _mDrawSurface = Nothing 
              , _scrolledWindow = error "ScrolledWindow"
              , _viewInfo = defaultViewInfoSinglePage
@@ -215,7 +201,7 @@
 canvasId = lens _canvasId (\f a -> f { _canvasId = a })
 
 -- | 
-drawArea :: Simple Lens (CanvasInfo a) DrawingArea
+drawArea :: Simple Lens (CanvasInfo a) Gtk.DrawingArea
 drawArea = lens _drawArea (\f a -> f { _drawArea = a })
 
 -- | 
@@ -224,7 +210,7 @@
 
 
 -- | 
-scrolledWindow :: Simple Lens (CanvasInfo a) ScrolledWindow
+scrolledWindow :: Simple Lens (CanvasInfo a) Gtk.ScrolledWindow
 scrolledWindow = lens _scrolledWindow (\f a -> f { _scrolledWindow = a })
 
 -- |
@@ -236,23 +222,23 @@
 currentPageNum = lens _currentPageNum (\f a -> f { _currentPageNum = a })
 
 -- | 
-horizAdjustment :: Simple Lens (CanvasInfo a) Adjustment 
+horizAdjustment :: Simple Lens (CanvasInfo a) Gtk.Adjustment 
 horizAdjustment = lens _horizAdjustment (\f a -> f { _horizAdjustment = a })
 
 -- | 
-vertAdjustment :: Simple Lens (CanvasInfo a) Adjustment 
+vertAdjustment :: Simple Lens (CanvasInfo a) Gtk.Adjustment 
 vertAdjustment = lens _vertAdjustment (\f a -> f { _vertAdjustment = a })
 
 -- | ConnectId for horizontal scrollbar value change event 
-horizAdjConnId :: Simple Lens (CanvasInfo a) (Maybe (ConnectId Adjustment))
+horizAdjConnId :: Simple Lens (CanvasInfo a) (Maybe (Gtk.ConnectId Gtk.Adjustment))
 horizAdjConnId = lens _horizAdjConnId (\f a -> f { _horizAdjConnId = a })
 
 -- | ConnectId for vertical scrollbar value change event 
-vertAdjConnId :: Simple Lens (CanvasInfo a) (Maybe (ConnectId Adjustment))
+vertAdjConnId :: Simple Lens (CanvasInfo a) (Maybe (Gtk.ConnectId Gtk.Adjustment))
 vertAdjConnId = lens _vertAdjConnId (\f a -> f { _vertAdjConnId = a })
 
 -- | composition lens
-adjustments :: Simple Lens (CanvasInfo a) (Adjustment,Adjustment) 
+adjustments :: Simple Lens (CanvasInfo a) (Gtk.Adjustment,Gtk.Adjustment) 
 adjustments = lens getter setter  
   where getter = (,) <$> view horizAdjustment <*> view vertAdjustment 
         setter f (h,v) = set horizAdjustment h . set vertAdjustment v $ f
@@ -270,25 +256,21 @@
   CanvasSinglePage :: CanvasInfo SinglePage -> CanvasInfoBox  
   CanvasContPage :: CanvasInfo ContinuousPage -> CanvasInfoBox
                    
-
-
-forBoth ::  
-          ((CanvasInfo SinglePage -> f (CanvasInfo SinglePage))
-              -> (CanvasInfo ContinuousPage -> f (CanvasInfo ContinuousPage)) 
-              -> (CanvasInfoBox -> f CanvasInfoBox))   
-          -> (forall a. CanvasInfo a -> f (CanvasInfo a))
-          -> CanvasInfoBox -> f CanvasInfoBox
+forBoth :: ((CanvasInfo SinglePage -> f (CanvasInfo SinglePage))
+             -> (CanvasInfo ContinuousPage -> f (CanvasInfo ContinuousPage)) 
+             -> (CanvasInfoBox -> f CanvasInfoBox))   
+        -> (forall a. CanvasInfo a -> f (CanvasInfo a))
+        -> CanvasInfoBox -> f CanvasInfoBox
 forBoth m f = m f f 
 
 
-forBoth' ::  ((CanvasInfo SinglePage -> r)
+forBoth' :: ((CanvasInfo SinglePage -> r)
               -> (CanvasInfo ContinuousPage -> r) 
               -> (CanvasInfoBox -> r) )
-          -> (forall a. CanvasInfo a -> r)
-          -> CanvasInfoBox -> r
+         -> (forall a. CanvasInfo a -> r)
+         -> CanvasInfoBox -> r
 forBoth' m f = m f f 
 
-
 -- | single page action and continuous page act
 unboxBiXform :: (Functor f) => 
                 (CanvasInfo SinglePage -> f (CanvasInfo SinglePage)) 
@@ -318,7 +300,7 @@
 unboxLens l = lens (unboxGet l) (flip (unboxSet l)) 
 
 -- |
-getDrawAreaFromBox :: CanvasInfoBox -> DrawingArea 
+getDrawAreaFromBox :: CanvasInfoBox -> Gtk.DrawingArea 
 getDrawAreaFromBox = view (unboxLens drawArea)
 
 -- |
@@ -338,7 +320,6 @@
 penColor :: Simple Lens WidthColorStyle PenColor
 penColor = lens _penColor (\f a -> f { _penColor = a } )
 
-
 -- | 
 data PenHighlighterEraserSet = PenHighlighterEraserSet 
                                { _currPen :: WidthColorStyle 
@@ -369,7 +350,6 @@
 currVerticalSpace :: Simple Lens PenHighlighterEraserSet WidthColorStyle
 currVerticalSpace = lens _currVerticalSpace 
                       (\f a -> f { _currVerticalSpace = a } )
-
                      
 -- | 
 data PenInfo = PenInfo { _penType :: PenType
@@ -482,5 +462,7 @@
               Cairo.rectangle 0 0 w' h' 
               Cairo.fill 
             return sfc 
+
+
   return $ (set (viewInfo.pageArrangement) arr'.set mDrawSurface msfc) cinfo
      
diff --git a/src/Hoodle/Type/Coroutine.hs b/src/Hoodle/Type/Coroutine.hs
--- a/src/Hoodle/Type/Coroutine.hs
+++ b/src/Hoodle/Type/Coroutine.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE GADTs #-}
+{-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeSynonymInstances #-}
 {-# LANGUAGE FlexibleInstances #-}
@@ -9,7 +10,7 @@
 -- Module      : Hoodle.Type.Coroutine 
 -- Copyright   : (c) 2011-2014 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -115,7 +116,6 @@
 -- | 
 doIOaction :: ((AllEvent -> IO ()) -> IO AllEvent) -> MainCoroutine ()
 doIOaction action = modify (tempQueue %~ enqueue (mkIOaction action))
-
 
 
 
diff --git a/src/Hoodle/Type/Enum.hs b/src/Hoodle/Type/Enum.hs
--- a/src/Hoodle/Type/Enum.hs
+++ b/src/Hoodle/Type/Enum.hs
@@ -3,7 +3,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Type.Enum 
--- Copyright   : (c) 2011-2013 Ian-Woo Kim
+-- Copyright   : (c) 2011-2014 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
@@ -17,9 +17,10 @@
 import           Control.Lens (Simple,Lens,lens)
 import qualified Data.ByteString.Char8 as B
 import qualified Data.Map as M
-import           Data.Maybe 
 -- 
 import           Data.Hoodle.Predefined
+--
+import           Hoodle.Util
 
 -- | drawing efficiency
 data DrawFlag = Clear | BkgEfficient | Efficient
@@ -81,6 +82,8 @@
 
 data RotateDir = CW | CCW deriving (Show, Ord, Eq)
 
+-- | 
+data NewPageModeType = NPPlain | NPLast | NPCycle deriving (Show, Ord, Eq)
 
 --
 -- lenses
@@ -105,12 +108,12 @@
                              , (ColorWhite, "white") ]
 
 penColorRGBAmap :: M.Map PenColor (Double,Double,Double,Double)
-penColorRGBAmap = M.fromList $ map (\x->(fst x,fromJust (M.lookup (snd x) predefined_pencolor))) 
+penColorRGBAmap = M.fromList $ map (\x->(fst x,fromJustError "penColorRGBAmap" (M.lookup (snd x) predefined_pencolor))) 
                              $ M.toList penColorNameMap 
 
 convertPenColorToRGBA :: PenColor -> (Double,Double,Double,Double)
 convertPenColorToRGBA (ColorRGBA r g b a) = (r,g,b,a)
-convertPenColorToRGBA c = fromJust (M.lookup c penColorRGBAmap)
+convertPenColorToRGBA c = fromJustError "convertPenColorToRGBA" (M.lookup c penColorRGBAmap)
 
 convertRGBAToHex :: (Double,Double,Double,Double) -> B.ByteString 
 convertRGBAToHex = B.pack . rgbaToHEX 
diff --git a/src/Hoodle/Type/Event.hs b/src/Hoodle/Type/Event.hs
--- a/src/Hoodle/Type/Event.hs
+++ b/src/Hoodle/Type/Event.hs
@@ -1,11 +1,12 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleInstances #-}
 
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Type.Event 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -21,10 +22,12 @@
 import           Data.ByteString 
 import           Data.IORef
 import qualified Data.Text as T
-import           Data.Time.Clock
 import           Data.UUID (UUID)
 import qualified Graphics.Rendering.Cairo as Cairo
-import           Graphics.UI.Gtk hiding (Image)
+import qualified Graphics.UI.Gtk as Gtk
+#ifdef HUB
+import           Data.Time.Clock
+#endif
 -- from hoodle-platform
 import           Control.Monad.Trans.Crtn.Event 
 import           Data.Hoodle.BBox
@@ -33,18 +36,24 @@
 -- from this package
 import           Hoodle.Device 
 import           Hoodle.Type.Enum
-import           Hoodle.Type.Canvas
 import           Hoodle.Type.PageArrangement
+import           Hoodle.Util
+#ifdef HUB
+import           Hoodle.Type.Hub
+import           Hoodle.Type.Synchronization
+#endif
 
 -- | 
 data AllEvent = UsrEv UserEvent | SysEv SystemEvent
               deriving Show 
 
 instance Show (Cairo.Surface) where
-  show _ = "surface"
+  show _ = "cairo surface"
 
 -- | 
-data SystemEvent = TestSystemEvent | ClockUpdateEvent | RenderCacheUpdate (UUID, (Double,Cairo.Surface))
+data SystemEvent = TestSystemEvent 
+                 | ClockUpdateEvent 
+                 | RenderCacheUpdate (SurfaceID, (Double,Cairo.Surface))
                  deriving Show 
                           
 -- | 
@@ -62,6 +71,7 @@
                | PenWidthChanged Int 
                | AssignPenMode (Either PenType SelectType) 
                | BackgroundStyleChanged BackgroundStyle 
+               | AssignNewPageMode NewPageModeType
                | HScrollBarMoved Int Double
                | VScrollBarMoved Int Double 
                | VScrollBarStart Int Double
@@ -83,10 +93,13 @@
                | LaTeXInput (Maybe (ByteString,ByteString))
                | TextInput (Maybe String)
                | AddLink (Maybe (String,FilePath))
+               | OpenLink UrlPath (Maybe (T.Text,T.Text))
+               | OpenShared UUID
+               | OpenTemp UUID FilePath
                | EventDisconnected
                | GetHoodleFileInfo (IORef (Maybe String))
+               | GetHoodleFileInfoFromTab UUID (IORef (Maybe String))
                | GotLink (Maybe String) (Int,Int)
-               | Sync UTCTime 
                | FileReloadOrdered
                | CustomKeyEvent String 
                | GotRevision String String
@@ -96,21 +109,37 @@
                | GotRecogResult Bool T.Text
                | MiniBuffer MiniBufferEvent
                | MultiLine MultiLineEvent
-               | NetworkProcess NetworkEvent
-               | DBusEv DBusEvent
                | RenderEv RenderEvent
                | LinePosition (Maybe (Int,Int))
                | Keyword (Maybe T.Text)
+               | SwitchTab Int
+               | CloseTab UUID
+               | UIEv UIEvent 
+#ifdef HUB
+               | DBusEv DBusEvent
+               | NetworkProcess NetworkEvent
+               | DisconnectedHub FilePath (FilePath,Maybe FilePath) HubInfo
+               | SyncInfoUpdated UUID FileSyncStatus
+               | FileSyncFromHub UUID FileSyncStatus
+               | GotSyncEvent Bool UUID FileSyncStatus
+               | Sync UTCTime 
+               | SyncFileFinished FileSyncStatus
+#endif
                deriving Show
                       
 instance Show (IORef a) where                      
   show _ = "IORef"
 
+data UIEvent = UIGetFlag Bool
+             deriving Show
+
+
 data RenderEvent = GotRItem RItem
                  | GotRItems [RItem]
                  | GotRBackground RBackground
                  | GotRHoodle RHoodle
                  | GotNone
+                 | FinishCommand SurfaceID
                  deriving Show
 
 -- | 
@@ -123,15 +152,15 @@
                | MenuRecentDocument
                | MenuLoadPNGorJPG
                | MenuLoadSVG
+               | MenuLoadImageBackground
                | MenuText
                | MenuEmbedTextSource
                | MenuEditEmbedTextSource
-               | MenuEditNetEmbedTextSource
                | MenuTextFromSource
                | MenuLaTeX
-               | MenuLaTeXNetwork
                | MenuCombineLaTeX
-               | MenuLaTeXFromSource 
+               | MenuLaTeXFromSource
+               | MenuUpdateLaTeX
                | MenuEmbedPredefinedImage
                | MenuEmbedPredefinedImage2
                | MenuEmbedPredefinedImage3                 
@@ -185,13 +214,10 @@
                | MenuAddLink
                | MenuAddAnchor
                | MenuListAnchors
-               --  | MenuShapeRecognizer
-               --  | MenuRuler
                | MenuHandwritingRecognitionDialog
                | MenuSelectRegion
                | MenuSelectRectangle
                | MenuVerticalSpace
-               --   | MenuHandTool
                | MenuPenOptions
                | MenuEraserOptions 
                | MenuHighlighterOptions
@@ -202,10 +228,11 @@
                | MenuDefaultHighlighter
                | MenuDefaultText 
                | MenuSetAsDefaultOption
+#ifdef DYRE
                | MenuRelaunch
+#endif
                | MenuUseXInput
                | MenuUseTouch 
-               | MenuSmoothScroll
                | MenuUsePopUpMenu
                | MenuEmbedImage
                | MenuEmbedPDF
@@ -215,23 +242,19 @@
                | MenuTogglePanZoomWidget
                | MenuToggleLayerWidget
                | MenuToggleClockWidget
-               | MenuDiscardCoreEvents 
-               | MenuEraserTip 
+               | MenuToggleScrollWidget
                | MenuPressureSensitivity
-               | MenuPageHighlight
-               | MenuMultiplePageView
-               | MenuMultiplePages
-               | MenuButton2Mapping
-               | MenuButton3Mapping 
-               | MenuAntialiasedBitmaps
-               | MenuProgressiveBackgrounds
-               | MenuPrintPaperRuling 
-               | MenuLeftHandedScrollbar
-               | MenuShortenMenus
-               | MenuAutoSavePreferences
-               | MenuSavePreferences
+               | MenuAddTab
+               | MenuCloseTab
                | MenuAbout
                | MenuDefault
+#ifdef HUB
+               | MenuEditNetEmbedTextSource
+               | MenuToggleNetworkEditSource
+               | MenuLaTeXNetwork
+               | MenuHub
+--                | MenuHubSocket
+#endif
                deriving Show 
 
 -- |
@@ -251,8 +274,10 @@
                       | CMenuMakeLinkToAnchor Anchor
                       | CMenuPangoConvert (Double,Double) T.Text
                       | CMenuLaTeXConvert (Double,Double) T.Text
+#ifdef HUB
                       | CMenuLaTeXConvertNetwork (Double,Double) T.Text
-                      | CMenuLaTeXUpdate (Double,Double) T.Text
+#endif
+                      | CMenuLaTeXUpdate (Double,Double) Dimension T.Text
                       | CMenuCropImage (BBoxed Image)
                       | CMenuRotate    RotateDir (BBoxed Image)
                       | CMenuExport (BBoxed Image)
@@ -263,19 +288,20 @@
 
 
 -- | event for minibuffer operation (currently pen only) 
-data MiniBufferEvent = MiniBufferInitialized DrawWindow
+data MiniBufferEvent = MiniBufferInitialized Gtk.DrawWindow
                      | MiniBufferPenDown PenButton PointerCoord
                      | MiniBufferPenUp PointerCoord
                      | MiniBufferPenMove PointerCoord
                      deriving Show
 
-instance Show DrawWindow where
+instance Show Gtk.DrawWindow where
   show _ = "DrawWindow"
 
 -- | event for multiline text view/buffer
 data MultiLineEvent = MultiLineChanged T.Text
                     deriving Show
 
+#ifdef HUB
 -- | event for network
 data NetworkEvent = NetworkDialog 
                   | NetworkInitialized ThreadId (MVar ())
@@ -283,19 +309,22 @@
                   | NetworkCloseDialog
                   | NetworkClosed
                   deriving Show
+#endif
 
 instance Show (MVar ()) where
   show _ = "MVar"
 
+#ifdef HUB
 data DBusEvent = DBusNetworkInput T.Text
                | ImageFileDropped FilePath
                | GoToLink (T.Text,T.Text)
                deriving Show
+#endif
 
 -- | 
-viewModeToUserEvent :: RadioAction -> IO UserEvent
+viewModeToUserEvent :: Gtk.RadioAction -> IO UserEvent
 viewModeToUserEvent a = do 
-    v <- radioActionGetCurrentValue a
+    v <- Gtk.radioActionGetCurrentValue a
     case v of 
       1 -> return ToSinglePage
       0 -> return ToContSinglePage
diff --git a/src/Hoodle/Type/HoodleState.hs b/src/Hoodle/Type/HoodleState.hs
--- a/src/Hoodle/Type/HoodleState.hs
+++ b/src/Hoodle/Type/HoodleState.hs
@@ -1,12 +1,13 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TypeOperators #-}
 
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Type.HoodleState 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -14,24 +15,33 @@
 -----------------------------------------------------------------------------
 
 module Hoodle.Type.HoodleState 
-( HoodleState(..)
+( HoodleState
 , HoodleModeState(..)
+, UnitHoodle
 , IsOneTimeSelectMode(..)
-, Settings(..)
-, UIComponentSignalHandler(..)
+, Settings
+, UIComponentSignalHandler
+, FileStore(..)
 -- | labels
+, unitKey
+, unitUUID
+, unitButton
 , hoodleModeState
 , hoodleFileControl
 , cvsInfoMap
 , currentCanvas
+, isOneTimeSelectMode
 , frameState
 , rootWindow
+, unitHoodles
+, rootNotebook
 , rootContainer
 , rootOfRootWindow
 , currentPenDraw
 , callBack
 , deviceList
 , penInfo
+, cursorInfo
 , selectInfo
 , gtkUIManager
 , isSaved
@@ -40,41 +50,49 @@
 , isFullScreen 
 , settings
 , uiComponentSignalHandler
-, isOneTimeSelectMode
 , lastTimeCanvasConfigure
 , hookSet 
 , tempLog 
 , tempQueue 
 , statusBar
-, renderCache
+, renderCacheVar
 , pdfRenderQueue
+, genRenderQueue
 , doesNotInvalidate
--- , cursorInfo
+, nextPdfBkgPageNum
 -- 
 , hoodleFileName 
 , lastSavedTime
+, syncMD5History
 --
 , doesUseXInput 
 , doesUseTouch
-, doesSmoothScroll 
 , doesUsePopUpMenu
 , doesEmbedImage
 , doesEmbedPDF
 , doesFollowLinks
 , doesKeepAspectRatio
 , doesUseVariableCursor
+, newPageMode
+, networkEditSourceInfo
+#ifdef HUB
+, sqliteFileName
+#endif
 -- 
 , penModeSignal
 , pageModeSignal
 , penPointSignal
 , penColorSignal
+, newPageModeSignal
+, switchTabSignal
 -- | others 
+, emptyUnitHoodle
 , emptyHoodleState
 , defaultSettings 
 , defaultUIComponentSignalHandler
 , getHoodle
 -- | additional lenses 
-, getCanvasInfoMap 
+--  , getCanvasInfoMap 
 , setCanvasInfoMap 
 , getCurrentCanvasId
 , setCurrentCanvasId
@@ -89,22 +107,22 @@
 , getCurrentPageFromHoodleModeState
 , getCurrentPageDimFromHoodleModeState
 -- | for debug
-, showCanvasInfoMapViewPortBBox
+-- , showCanvasInfoMapViewPortBBox
+-- , getTheUnit
+-- , putTheUnit
+, currentUnit
 ) where
 
-import           Control.Applicative hiding (empty)
 import           Control.Concurrent
 import           Control.Concurrent.STM
-import           Control.Lens (Simple,Lens,view,set,lens)
-import           Control.Monad.State hiding (get,modify)
+import           Control.Lens (Simple,Lens,view,set,lens,(^.))
 import           Data.Functor.Identity (Identity(..))
 import qualified Data.HashMap.Strict as HM
 import qualified Data.IntMap as M
-import           Data.Maybe
 import           Data.Sequence 
+import qualified Data.Text as T
 import           Data.Time.Clock
 import           Data.UUID (UUID)
--- import qualified Graphics.Rendering.Cairo as Cairo
 import qualified Graphics.UI.Gtk as Gtk hiding (Clipboard, get,set)
 -- from hoodle-platform
 import           Control.Monad.Trans.Crtn.Event 
@@ -139,72 +157,115 @@
                          | YesAfterSelect
                          deriving (Show,Eq,Ord)
 
+data UnitHoodle = UnitHoodle { _unitKey :: Int
+                             , _unitUUID :: UUID
+                             , _unitButton :: Gtk.Button
+                             , _hoodleModeState :: HoodleModeState
+                             , _hoodleFileControl :: HoodleFileControl
+                             , _cvsInfoMap :: CanvasInfoMap 
+                             , _currentCanvas :: (CanvasId,CanvasInfoBox)
+                             , _frameState :: WindowConfig 
+                             , _rootWindow :: Gtk.Widget
+                             , _rootContainer :: Gtk.Box
+                             , _isSaved :: Bool 
+                             , _undoTable :: UndoTable HoodleModeState
+                             , _isOneTimeSelectMode :: IsOneTimeSelectMode
+                             }
+
+
 data HoodleState = 
-    HoodleState { _hoodleModeState :: HoodleModeState
-                , _hoodleFileControl :: HoodleFileControl
-                , _cvsInfoMap :: CanvasInfoMap 
-                , _currentCanvas :: (CanvasId,CanvasInfoBox)
-                , _frameState :: WindowConfig 
-                , _rootWindow :: Gtk.Widget
-                , _rootContainer :: Gtk.Box
+    HoodleState { _unitHoodles :: (Int, M.IntMap UnitHoodle)
+                , _rootNotebook :: Gtk.Notebook
                 , _rootOfRootWindow :: Gtk.Window
                 , _currentPenDraw :: PenDraw
                 , _callBack ::  AllEvent -> IO ()
                 , _deviceList :: DeviceList
                 , _penInfo :: PenInfo
+                , _cursorInfo :: (PenColor,Double,Bool) -- ^ (pen color, pen width, use variable cursor)
                 , _selectInfo :: SelectInfo 
                 , _gtkUIManager :: Gtk.UIManager 
-                , _isSaved :: Bool 
-                , _undoTable :: UndoTable HoodleModeState
-                , _backgroundStyle :: BackgroundStyle 
                 , _isFullScreen :: Bool 
                 , _settings :: Settings 
+                , _backgroundStyle :: BackgroundStyle 
                 , _uiComponentSignalHandler :: UIComponentSignalHandler 
-                , _isOneTimeSelectMode :: IsOneTimeSelectMode
                 , _lastTimeCanvasConfigure :: Maybe UTCTime 
                 , _hookSet :: Maybe Hook
                 , _tempQueue :: Queue (Either (ActionOrder AllEvent) AllEvent)
                 , _tempLog :: String -> String 
                 , _statusBar :: Maybe Gtk.Statusbar
-                , _renderCache :: RenderCache
-                , _pdfRenderQueue :: TVar (Seq (UUID,PDFCommand))
+                , _renderCacheVar :: TVar RenderCache
+                , _pdfRenderQueue :: PDFCommandQueue
+                , _genRenderQueue :: GenCommandQueue
                 , _doesNotInvalidate :: Bool
-                -- , _cursorInfo :: Maybe Cursor
+                , _nextPdfBkgPageNum :: Maybe Int
                 } 
 
 
--- | lens for hoodleModeState
-hoodleModeState :: Simple Lens HoodleState HoodleModeState
-hoodleModeState = lens _hoodleModeState (\f a -> f { _hoodleModeState = a } )
+-- | current unit
+currentUnit :: Simple Lens (Int,M.IntMap UnitHoodle) UnitHoodle
+currentUnit = lens (\(k,m) -> fromJustError "currentUnit" (M.lookup k m)) (\(_,m) a -> (_unitKey a,M.insert (_unitKey a) a m))
 
+-- | lens for unitKey
+unitKey :: Simple Lens UnitHoodle Int
+unitKey = lens _unitKey (\f a -> f { _unitKey = a })
 
+-- | lens for unitKey
+unitUUID :: Simple Lens UnitHoodle UUID
+unitUUID = lens _unitUUID (\f a -> f { _unitUUID = a })
 
--- | 
-hoodleFileControl :: Simple Lens HoodleState HoodleFileControl
-hoodleFileControl = lens _hoodleFileControl (\f a -> f { _hoodleFileControl = a })
+-- | lens for unitKey
+unitButton :: Simple Lens UnitHoodle Gtk.Button
+unitButton = lens _unitButton (\f a -> f { _unitButton = a })
 
 
+-- | lens for hoodleModeState
+hoodleModeState :: Simple Lens UnitHoodle HoodleModeState
+hoodleModeState = lens _hoodleModeState (\f a -> f { _hoodleModeState = a } )
 
+-- | 
+hoodleFileControl :: Simple Lens UnitHoodle HoodleFileControl
+hoodleFileControl = lens _hoodleFileControl (\f a -> f { _hoodleFileControl = a })
+
 -- | lens for cvsInfoMap
-cvsInfoMap :: Simple Lens HoodleState CanvasInfoMap
+cvsInfoMap :: Simple Lens UnitHoodle CanvasInfoMap
 cvsInfoMap = lens _cvsInfoMap (\f a -> f { _cvsInfoMap = a } )
 
 -- | lens for currentCanvas
-currentCanvas :: Simple Lens HoodleState (CanvasId,CanvasInfoBox)
+currentCanvas :: Simple Lens UnitHoodle (CanvasId,CanvasInfoBox)
 currentCanvas = lens _currentCanvas (\f a -> f { _currentCanvas = a } )
 
 -- | lens for frameState
-frameState :: Simple Lens HoodleState WindowConfig
+frameState :: Simple Lens UnitHoodle WindowConfig
 frameState = lens _frameState (\f a -> f { _frameState = a } )
 
 -- | lens for rootWindow
-rootWindow :: Simple Lens HoodleState Gtk.Widget
+rootWindow :: Simple Lens UnitHoodle Gtk.Widget
 rootWindow = lens _rootWindow (\f a -> f { _rootWindow = a } )
 
 -- | lens for rootContainer
-rootContainer :: Simple Lens HoodleState Gtk.Box
+rootContainer :: Simple Lens UnitHoodle Gtk.Box
 rootContainer = lens _rootContainer (\f a -> f { _rootContainer = a } )
 
+-- | lens for isSaved
+isSaved :: Simple Lens UnitHoodle Bool
+isSaved = lens _isSaved (\f a -> f { _isSaved = a } )
+
+-- | lens for undoTable
+undoTable :: Simple Lens UnitHoodle (UndoTable HoodleModeState)
+undoTable = lens _undoTable (\f a -> f { _undoTable = a } )
+
+-- | lens for isOneTimeSelectMode
+isOneTimeSelectMode :: Simple Lens UnitHoodle IsOneTimeSelectMode
+isOneTimeSelectMode = lens _isOneTimeSelectMode (\f a -> f { _isOneTimeSelectMode = a } )
+
+-- | lens for unitHoodles 
+unitHoodles :: Simple Lens HoodleState (Int,M.IntMap UnitHoodle)
+unitHoodles = lens _unitHoodles (\f a -> f { _unitHoodles = a } )
+
+-- | lens for rootWindow
+rootNotebook :: Simple Lens HoodleState Gtk.Notebook
+rootNotebook = lens _rootNotebook (\f a -> f { _rootNotebook = a } )
+
 -- | lens for rootOfRootWindow
 rootOfRootWindow :: Simple Lens HoodleState Gtk.Window
 rootOfRootWindow = lens _rootOfRootWindow (\f a -> f { _rootOfRootWindow = a } )
@@ -225,6 +286,11 @@
 penInfo :: Simple Lens HoodleState PenInfo
 penInfo = lens _penInfo (\f a -> f { _penInfo = a } )
 
+-- | lens for cursorInfo
+cursorInfo :: Simple Lens HoodleState (PenColor,Double,Bool)
+cursorInfo = lens _cursorInfo (\f a -> f { _cursorInfo = a } )
+
+
 -- | lens for selectInfo
 selectInfo :: Simple Lens HoodleState SelectInfo
 selectInfo = lens _selectInfo (\f a -> f { _selectInfo = a } )
@@ -233,14 +299,6 @@
 gtkUIManager :: Simple Lens HoodleState Gtk.UIManager
 gtkUIManager = lens _gtkUIManager (\f a -> f { _gtkUIManager = a } )
 
--- | lens for isSaved
-isSaved :: Simple Lens HoodleState Bool
-isSaved = lens _isSaved (\f a -> f { _isSaved = a } )
-
--- | lens for undoTable
-undoTable :: Simple Lens HoodleState (UndoTable HoodleModeState)
-undoTable = lens _undoTable (\f a -> f { _undoTable = a } )
-
 -- | background style = plain, lined, ruled, graph
 backgroundStyle :: Simple Lens HoodleState BackgroundStyle
 backgroundStyle = lens _backgroundStyle (\f a -> f { _backgroundStyle = a } )
@@ -257,12 +315,7 @@
 uiComponentSignalHandler :: Simple Lens HoodleState UIComponentSignalHandler
 uiComponentSignalHandler = lens _uiComponentSignalHandler (\f a -> f { _uiComponentSignalHandler = a })
 
--- | lens for isOneTimeSelectMode
-isOneTimeSelectMode :: Simple Lens HoodleState IsOneTimeSelectMode
-isOneTimeSelectMode = lens _isOneTimeSelectMode (\f a -> f { _isOneTimeSelectMode = a } )
 
-
-
 -- | lens for lastTimeCanvasConfigure
 lastTimeCanvasConfigure :: Simple Lens HoodleState (Maybe UTCTime)
 lastTimeCanvasConfigure = lens _lastTimeCanvasConfigure (\f a -> f { _lastTimeCanvasConfigure = a } )
@@ -284,34 +337,46 @@
 statusBar = lens _statusBar (\f a -> f { _statusBar = a })
 
 -- | 
-renderCache :: Simple Lens HoodleState RenderCache
-renderCache = lens _renderCache (\f a -> f { _renderCache = a })
+renderCacheVar :: Simple Lens HoodleState (TVar RenderCache)
+renderCacheVar = lens _renderCacheVar (\f a -> f { _renderCacheVar = a })
 
 -- | 
-pdfRenderQueue :: Simple Lens HoodleState (TVar (Seq (UUID, PDFCommand)))
+pdfRenderQueue :: Simple Lens HoodleState PDFCommandQueue
 pdfRenderQueue = lens _pdfRenderQueue (\f a -> f { _pdfRenderQueue = a })
 
+-- | 
+genRenderQueue :: Simple Lens HoodleState GenCommandQueue
+genRenderQueue = lens _genRenderQueue (\f a -> f { _genRenderQueue = a })
 
+
 -- | 
 doesNotInvalidate :: Simple Lens HoodleState Bool
 doesNotInvalidate = lens _doesNotInvalidate (\f a -> f { _doesNotInvalidate = a })
 
+-- | 
+nextPdfBkgPageNum :: Simple Lens HoodleState (Maybe Int)
+nextPdfBkgPageNum = lens _nextPdfBkgPageNum (\f a -> f { _nextPdfBkgPageNum = a })
 
 
+
 {-
 -- | 
 cursorInfo :: Simple Lens HoodleState (Maybe Cursor)
 cursorInfo = lens _cursorInfo (\f a -> f { _cursorInfo = a })
 -}
 
+data FileStore = LocalDir (Maybe FilePath)
+               | TempDir FilePath
+
 -- | 
 data HoodleFileControl = 
-  HoodleFileControl { _hoodleFileName :: Maybe FilePath 
+  HoodleFileControl { _hoodleFileName :: FileStore -- Maybe FilePath 
                     , _lastSavedTime  :: Maybe UTCTime 
+                    , _syncMD5History :: [T.Text]
                     } 
 
 -- | lens for currFileName
-hoodleFileName :: Simple Lens HoodleFileControl (Maybe FilePath)
+hoodleFileName :: Simple Lens HoodleFileControl FileStore -- (Maybe FilePath)
 hoodleFileName = lens _hoodleFileName (\f a -> f { _hoodleFileName = a } )
 
 -- | lens for last saved time
@@ -319,13 +384,20 @@
 lastSavedTime = lens _lastSavedTime (\f a -> f { _lastSavedTime = a } )
 
 
+-- | lens for last saved time
+syncMD5History :: Simple Lens HoodleFileControl [T.Text] 
+syncMD5History = lens _syncMD5History (\f a -> f { _syncMD5History = a } )
 
+
+
 -- | 
 data UIComponentSignalHandler = UIComponentSignalHandler
        { _penModeSignal :: Maybe (Gtk.ConnectId Gtk.RadioAction)
        , _pageModeSignal :: Maybe (Gtk.ConnectId Gtk.RadioAction)
        , _penPointSignal :: Maybe (Gtk.ConnectId Gtk.RadioAction)
        , _penColorSignal :: Maybe (Gtk.ConnectId Gtk.RadioAction)
+       , _newPageModeSignal :: Maybe (Gtk.ConnectId Gtk.RadioAction)
+       , _switchTabSignal :: Maybe (Gtk.ConnectId Gtk.Notebook)
        } 
 
 -- | lens for penModeSignal
@@ -344,18 +416,30 @@
 penColorSignal :: Simple Lens UIComponentSignalHandler (Maybe (Gtk.ConnectId Gtk.RadioAction))
 penColorSignal = lens _penColorSignal (\f a -> f { _penColorSignal = a } )
 
+-- | lens for newPageModeSignal
+newPageModeSignal :: Simple Lens UIComponentSignalHandler (Maybe (Gtk.ConnectId Gtk.RadioAction))
+newPageModeSignal = lens _newPageModeSignal (\f a -> f { _newPageModeSignal = a } )
 
+-- | lens for switchTabSignal
+switchTabSignal :: Simple Lens UIComponentSignalHandler (Maybe (Gtk.ConnectId Gtk.Notebook))
+switchTabSignal = lens _switchTabSignal (\f a -> f { _switchTabSignal = a } )
+
+
 -- | A set of Hoodle settings 
 data Settings = 
   Settings { _doesUseXInput :: Bool 
            , _doesUseTouch :: Bool 
-           , _doesSmoothScroll :: Bool 
            , _doesUsePopUpMenu :: Bool 
            , _doesEmbedImage :: Bool 
            , _doesEmbedPDF :: Bool 
            , _doesFollowLinks :: Bool 
            , _doesKeepAspectRatio :: Bool
            , _doesUseVariableCursor :: Bool 
+           , _newPageMode :: NewPageModeType
+           , _networkEditSourceInfo :: Maybe ThreadId
+#ifdef HUB
+           , _sqliteFileName :: Maybe FilePath
+#endif
            } 
   
 
@@ -367,10 +451,6 @@
 doesUseTouch :: Simple Lens Settings Bool
 doesUseTouch = lens _doesUseTouch (\f a -> f { _doesUseTouch = a } )
 
--- | flag for smooth scrolling 
-doesSmoothScroll :: Simple Lens Settings Bool
-doesSmoothScroll = lens _doesSmoothScroll (\f a -> f { _doesSmoothScroll = a } )
-
 -- | flag for using popup menu
 doesUsePopUpMenu :: Simple Lens Settings Bool
 doesUsePopUpMenu = lens _doesUsePopUpMenu (\f a -> f { _doesUsePopUpMenu = a } )
@@ -395,54 +475,83 @@
 doesUseVariableCursor :: Simple Lens Settings Bool
 doesUseVariableCursor = lens _doesUseVariableCursor (\f a -> f {_doesUseVariableCursor=a})
 
+-- | new page mode: plain | last | cycle
+newPageMode :: Simple Lens Settings NewPageModeType
+newPageMode = lens _newPageMode (\f a -> f {_newPageMode=a})
+
+-- | network edit source mode
+networkEditSourceInfo :: Simple Lens Settings (Maybe ThreadId)
+networkEditSourceInfo = lens _networkEditSourceInfo (\f a -> f {_networkEditSourceInfo=a})
+
+#ifdef HUB
+-- | sqlite file
+sqliteFileName :: Simple Lens Settings (Maybe FilePath)
+sqliteFileName = lens _sqliteFileName (\f a -> f {_sqliteFileName=a})
+#endif
+
+-- |
+emptyUnitHoodle :: IO UnitHoodle
+emptyUnitHoodle = do
+  hdl <- emptyGHoodle
+  return $ 
+    UnitHoodle { _unitKey = 0
+               , _unitUUID = error "unitUUID"
+               , _unitButton = error "unitButton"
+               , _hoodleModeState = ViewAppendState hdl 
+               , _hoodleFileControl = emptyHoodleFileControl 
+               , _cvsInfoMap = error "emptyHoodleState.cvsInfoMap"
+               , _currentCanvas = error "emtpyHoodleState.currentCanvas"
+               , _frameState = error "emptyHoodleState.frameState" 
+               , _rootWindow = error "emtpyHoodleState.rootWindow"
+               , _rootContainer = error "emptyHoodleState.rootContainer"
+               , _isSaved = False 
+               , _undoTable = emptyUndo 1 
+               , _isOneTimeSelectMode = NoOneTimeSelectMode
+               }
+
 -- | default hoodle state 
 emptyHoodleState :: IO HoodleState 
 emptyHoodleState = do
-  hdl <- emptyGHoodle
-  tvar <- atomically $ newTVar empty 
+  unit <- emptyUnitHoodle
+  tvarpdf <- atomically $ newTVar empty 
+  tvargen <- atomically $ newTVar empty 
+  tvarcache <- atomically $ newTVar HM.empty
   return $
-    HoodleState  
-    { _hoodleModeState = ViewAppendState hdl 
-    , _hoodleFileControl = emptyHoodleFileControl 
-    -- , _currFileName = Nothing 
-    , _cvsInfoMap = error "emptyHoodleState.cvsInfoMap"
-    , _currentCanvas = error "emtpyHoodleState.currentCanvas"
-    , _frameState = error "emptyHoodleState.frameState" 
-    , _rootWindow = error "emtpyHoodleState.rootWindow"
-    , _rootContainer = error "emptyHoodleState.rootContainer"
-    , _rootOfRootWindow = error "emptyHoodleState.rootOfRootWindow"
-    , _currentPenDraw = emptyPenDraw 
-    -- , _clipboard = emptyClipboard
-    , _callBack = error "emtpyHoodleState.callBack"
-    , _deviceList = error "emtpyHoodleState.deviceList"
-    , _penInfo = defaultPenInfo 
-    , _selectInfo = SelectInfo SelectLassoWork 
-    , _gtkUIManager = error "emptyHoodleState.gtkUIManager"
-    , _isSaved = False 
-    , _undoTable = emptyUndo 1 
-    -- , _isEventBlocked = False 
-    , _backgroundStyle = BkgStyleLined
-    , _isFullScreen = False
-    , _settings = defaultSettings
-    , _uiComponentSignalHandler = defaultUIComponentSignalHandler 
-    , _isOneTimeSelectMode = NoOneTimeSelectMode
-    -- , _pageModeSignal = Nothing
-    -- , _penModeSignal = Nothing                        
-    , _lastTimeCanvasConfigure = Nothing                      
-    , _hookSet = Nothing
-    , _tempQueue = emptyQueue
-    , _tempLog = id 
-    , _statusBar = Nothing 
-    , _renderCache = HM.empty
-    , _pdfRenderQueue = tvar
-    , _doesNotInvalidate = False
-    -- , _cursorInfo = Nothing
-    }
+    HoodleState { _unitHoodles = (0, M.singleton 0 unit)
+                , _rootNotebook = error "emtpyHoodleState.rootNotebook"
+                , _rootOfRootWindow = error "emptyHoodleState.rootOfRootWindow"
+                , _currentPenDraw = emptyPenDraw 
+                , _callBack = error "emtpyHoodleState.callBack"
+                , _deviceList = error "emtpyHoodleState.deviceList"
+                , _penInfo = defaultPenInfo 
+                , _cursorInfo = (defaultPenInfo ^. penSet.currPen.penColor, defaultPenInfo ^. penSet.currPen.penWidth, False)
+                , _selectInfo = SelectInfo SelectLassoWork 
+                , _gtkUIManager = error "emptyHoodleState.gtkUIManager"
+                -- , _isEventBlocked = False 
+                , _backgroundStyle = BkgStyleLined
+                , _isFullScreen = False
+                , _settings = defaultSettings
+                , _uiComponentSignalHandler = defaultUIComponentSignalHandler 
+                -- , _pageModeSignal = Nothing
+                -- , _penModeSignal = Nothing                        
+                , _lastTimeCanvasConfigure = Nothing                      
+                , _hookSet = Nothing
+                , _tempQueue = emptyQueue
+                , _tempLog = id 
+                , _statusBar = Nothing 
+                , _renderCacheVar = tvarcache -- HM.empty
+                , _pdfRenderQueue = tvarpdf
+                , _genRenderQueue = tvargen
+                , _doesNotInvalidate = False
+                , _nextPdfBkgPageNum = Nothing
+                -- , _cursorInfo = Nothing
+                }
 
 emptyHoodleFileControl :: HoodleFileControl 
 emptyHoodleFileControl = 
-  HoodleFileControl { _hoodleFileName = Nothing 
+  HoodleFileControl { _hoodleFileName = LocalDir Nothing 
                     , _lastSavedTime = Nothing 
+                    , _syncMD5History = []
                     } 
 
 
@@ -451,7 +560,9 @@
   UIComponentSignalHandler{ _penModeSignal = Nothing 
                           , _pageModeSignal = Nothing 
                           , _penPointSignal = Nothing 
-                          , _penColorSignal = Nothing 
+                          , _penColorSignal = Nothing
+                          , _newPageModeSignal = Nothing
+                          , _switchTabSignal = Nothing
                           } 
 
 
@@ -461,51 +572,48 @@
   Settings 
   { _doesUseXInput = False
   , _doesUseTouch = True
-  , _doesSmoothScroll = False
   , _doesUsePopUpMenu = True 
   , _doesEmbedImage = True 
   , _doesEmbedPDF = True 
   , _doesFollowLinks = True
   , _doesKeepAspectRatio = False
   , _doesUseVariableCursor = False
+  , _newPageMode = NPPlain
+  , _networkEditSourceInfo = Nothing
+#ifdef HUB
+  , _sqliteFileName = Nothing
+#endif 
   } 
   
 
 -- | 
-getHoodle :: HoodleState -> Hoodle EditMode 
+getHoodle :: UnitHoodle -> Hoodle EditMode 
 getHoodle = either id gSelect2GHoodle . hoodleModeStateEither . view hoodleModeState 
 
 -- | 
-getCurrentCanvasId :: HoodleState -> CanvasId
+getCurrentCanvasId :: UnitHoodle -> CanvasId
 getCurrentCanvasId = fst . _currentCanvas 
   
 -- | 
-
-setCurrentCanvasId :: CanvasId -> HoodleState -> Maybe HoodleState
+setCurrentCanvasId :: CanvasId -> UnitHoodle -> Maybe UnitHoodle
 setCurrentCanvasId a f = do 
     cinfobox <- M.lookup a (_cvsInfoMap f)
     return (f { _currentCanvas = (a,cinfobox) })
-     
--- | 
-    
-getCanvasInfoMap :: HoodleState -> CanvasInfoMap 
-getCanvasInfoMap = _cvsInfoMap 
 
 -- | 
-
-setCanvasInfoMap :: CanvasInfoMap -> HoodleState -> Maybe HoodleState 
-setCanvasInfoMap cmap xstate 
+setCanvasInfoMap :: CanvasInfoMap -> UnitHoodle -> Maybe UnitHoodle
+setCanvasInfoMap cmap uhdl
   | M.null cmap = Nothing
   | otherwise = 
-      let (cid,_) = _currentCanvas xstate
+      let (cid,_) = _currentCanvas uhdl
           (cidmax,cinfomax) = M.findMax cmap
           mcinfobox = M.lookup cid cmap 
-      in Just . maybe (xstate {_currentCanvas=(cidmax,cinfomax), _cvsInfoMap = cmap}) 
-                       (\cinfobox -> xstate {_currentCanvas = (cid,cinfobox)
-                                            ,_cvsInfoMap = cmap }) 
+      in Just . maybe (uhdl {_currentCanvas=(cidmax,cinfomax), _cvsInfoMap = cmap}) 
+                       (\cinfobox -> uhdl { _currentCanvas = (cid,cinfobox)
+                                          , _cvsInfoMap = cmap }) 
                 $ mcinfobox
 
-currentCanvasInfo :: Simple Lens HoodleState CanvasInfoBox
+currentCanvasInfo :: Simple Lens UnitHoodle CanvasInfoBox
 currentCanvasInfo = lens getter setter 
   where 
     getter = snd . _currentCanvas 
@@ -515,48 +623,47 @@
       in f { _currentCanvas = (cid,a), _cvsInfoMap = cmap' }
 
 -- | 
-resetHoodleModeStateBuffers :: RenderCache -> HoodleModeState -> IO HoodleModeState 
-resetHoodleModeStateBuffers cache hdlmodestate1 = 
+resetHoodleModeStateBuffers :: CanvasId -> HoodleModeState -> Renderer ()
+resetHoodleModeStateBuffers cid hdlmodestate1 = 
   case hdlmodestate1 of 
-    ViewAppendState hdl -> liftIO . liftM ViewAppendState . updateHoodleBuf cache $ hdl
-    _ -> return hdlmodestate1
+    ViewAppendState hdl -> updateHoodleBuf cid hdl
+    _ -> return ()
 
 -- |
-getCanvasInfo :: CanvasId -> HoodleState -> CanvasInfoBox 
-getCanvasInfo cid xstate = 
-  let cinfoMap = getCanvasInfoMap xstate
+getCanvasInfo :: CanvasId -> UnitHoodle -> CanvasInfoBox 
+getCanvasInfo cid uhdl = 
+  let cinfoMap = view cvsInfoMap uhdl
       maybeCvs = M.lookup cid cinfoMap
   in maybeError' ("no canvas with id = " ++ show cid) maybeCvs
 
 -- | 
-setCanvasInfo :: (CanvasId,CanvasInfoBox) -> HoodleState -> HoodleState 
-setCanvasInfo (cid,cinfobox) xstate = 
-  let cmap = getCanvasInfoMap xstate
+setCanvasInfo :: (CanvasId,CanvasInfoBox) -> UnitHoodle -> UnitHoodle
+setCanvasInfo (cid,cinfobox) uhdl = 
+  let cmap = view cvsInfoMap uhdl
       cmap' = M.insert cid cinfobox cmap 
-  in maybe xstate id $ setCanvasInfoMap cmap' xstate
-
-
+  in maybe uhdl id $ setCanvasInfoMap cmap' uhdl
 
 -- | change current canvas. this is the master function  
-updateFromCanvasInfoAsCurrentCanvas :: CanvasInfoBox -> HoodleState -> HoodleState
-updateFromCanvasInfoAsCurrentCanvas cinfobox xstate = 
+updateFromCanvasInfoAsCurrentCanvas :: CanvasInfoBox -> UnitHoodle-> UnitHoodle
+updateFromCanvasInfoAsCurrentCanvas cinfobox uhdl = 
   let cid = view (unboxLens canvasId) cinfobox 
-      cmap = getCanvasInfoMap xstate
+      cmap = view cvsInfoMap uhdl
       cmap' = M.insert cid cinfobox cmap 
-  in xstate { _currentCanvas = (cid,cinfobox)
-            , _cvsInfoMap = cmap' }
+  in uhdl { _currentCanvas = (cid,cinfobox)
+          , _cvsInfoMap = cmap' }
 
 -- | 
 setCanvasId :: CanvasId -> CanvasInfoBox -> CanvasInfoBox 
 setCanvasId cid = runIdentity . forBoth unboxBiXform (return . set canvasId cid)   
 
 -- | 
-modifyCanvasInfo :: CanvasId -> (CanvasInfoBox -> CanvasInfoBox) -> HoodleState
-                    -> HoodleState
-modifyCanvasInfo cid f xstate =  
-    maybe xstate id . flip setCanvasInfoMap xstate 
-                    . M.adjust f cid . getCanvasInfoMap 
-    $ xstate 
+modifyCanvasInfo :: CanvasId -> (CanvasInfoBox -> CanvasInfoBox) 
+                 -> UnitHoodle
+                 -> UnitHoodle
+modifyCanvasInfo cid f uhdl =  
+    maybe uhdl id . flip setCanvasInfoMap uhdl
+                  . M.adjust f cid . view cvsInfoMap 
+    $ uhdl
 
 -- | 
 hoodleModeStateEither :: HoodleModeState -> Either (Hoodle EditMode) (Hoodle SelectMode) 
@@ -584,11 +691,6 @@
 getPageMapFromHoodleModeState = either (view gpages) (view gselAll) . hoodleModeStateEither 
   
       
--- | 
-showCanvasInfoMapViewPortBBox :: HoodleState -> IO ()
-showCanvasInfoMapViewPortBBox xstate = do 
-  let cmap = getCanvasInfoMap xstate
-  print . map (view (unboxLens (viewInfo.pageArrangement.viewPortBBox))) . M.elems $ cmap 
 
 
 
diff --git a/src/Hoodle/Type/Hub.hs b/src/Hoodle/Type/Hub.hs
new file mode 100644
--- /dev/null
+++ b/src/Hoodle/Type/Hub.hs
@@ -0,0 +1,28 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Hoodle.Type.Hub
+-- Copyright   : (c) 2014 Ian-Woo Kim
+--
+-- License     : BSD3
+-- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
+-- Stability   : experimental
+-- Portability : GHC
+--
+-----------------------------------------------------------------------------
+
+module Hoodle.Type.Hub where
+
+import Data.Text (Text)
+--
+
+
+data HubInfo = HubInfo { googleClientId :: Text
+                       , googleClientSecret :: Text
+                       , googleAuthURL :: String
+                       , hubURL :: String
+                       , hubFileRoot :: FilePath
+                       , hubSocketURL :: String
+                       , hubSocketPort :: Int
+                       , hubSocketPath :: String
+                       } 
+             deriving (Show,Eq,Ord)
diff --git a/src/Hoodle/Type/PageArrangement.hs b/src/Hoodle/Type/PageArrangement.hs
--- a/src/Hoodle/Type/PageArrangement.hs
+++ b/src/Hoodle/Type/PageArrangement.hs
@@ -9,7 +9,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Type.PageArrangement
--- Copyright   : (c) 2012, 2013 Ian-Woo Kim
+-- Copyright   : (c) 2012-2014 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
diff --git a/src/Hoodle/Type/Synchronization.hs b/src/Hoodle/Type/Synchronization.hs
new file mode 100644
--- /dev/null
+++ b/src/Hoodle/Type/Synchronization.hs
@@ -0,0 +1,105 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TemplateHaskell #-}
+{-# LANGUAGE TypeFamilies #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Hoodle.Type.Synchronization
+-- Copyright   : (c) 2014, 2015 Ian-Woo Kim
+--
+-- License     : BSD3
+-- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
+-- Stability   : experimental
+-- Portability : GHC
+--
+-----------------------------------------------------------------------------
+
+module Hoodle.Type.Synchronization where
+
+import           Control.Applicative
+import           Data.Aeson as AE
+import           Data.Data
+import qualified Data.HashMap.Strict as H
+import           Data.Text
+import           Data.Time.Clock (UTCTime)
+import           Database.Persist.TH
+
+share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
+FileSyncStatus
+    uuid    Text
+    md5     Text
+    time    UTCTime
+    UniqueFileSyncStatusUUID uuid
+    deriving Typeable
+    deriving Show
+    deriving Eq
+|]
+
+
+instance ToJSON FileSyncStatus where
+  toJSON FileSyncStatus {..} = object [ "uuid" .= toJSON fileSyncStatusUuid 
+                                      , "md5"  .= toJSON fileSyncStatusMd5
+                                      , "time" .= toJSON fileSyncStatusTime 
+                                      ]
+instance FromJSON FileSyncStatus where
+  parseJSON (Object v) = 
+    let r = do
+          String uuid   <- H.lookup "uuid" v
+          String md5txt <- H.lookup "md5" v
+          eutime <- fromJSON <$> H.lookup "time" v
+          utime <- case eutime of
+                     Error _ -> Nothing
+                     Success a -> a
+          return (FileSyncStatus uuid md5txt utime)
+    in maybe (fail "error in parsing FileSyncStatus") return r
+  parseJSON _ = fail "error in parsing FileSyncStatus" 
+
+
+data FileContent = FileContent { file_uuid :: Text
+                               , file_path :: Maybe Text
+                               , file_content :: Text 
+                               , file_rsync :: Maybe FileRsync
+                               , client_uuid :: Text
+                               }
+                 deriving Show
+
+instance ToJSON FileContent where
+  toJSON FileContent {..} = object [ "uuid"    .= toJSON file_uuid
+                                   , "path"    .= toJSON file_path
+                                   , "content" .= toJSON file_content 
+                                   , "rsync"   .= toJSON file_rsync
+                                   , "client"  .= toJSON client_uuid
+                                   ]
+
+instance FromJSON FileContent where
+  parseJSON (Object v) = 
+    FileContent <$> v .: "uuid" 
+                <*> v .: "path" 
+                <*> v .: "content" 
+                <*> v .: "rsync" 
+                <*> v .: "client"
+  parseJSON _ = fail "error in parsing FileContent"
+
+data FileRsync = FileRsync { frsync_uuid :: Text 
+                           , frsync_sig :: Text
+                           }
+               deriving Show
+
+instance ToJSON FileRsync where
+  toJSON FileRsync {..} = object [ "uuid" .= toJSON frsync_uuid
+                                 , "signature" .= toJSON frsync_sig ]
+
+instance FromJSON FileRsync where
+  parseJSON (Object v) = 
+    let r = do 
+          String uuid <- H.lookup "uuid" v
+          String sig <- H.lookup "signature" v
+          return (FileRsync uuid sig)
+    in maybe (fail "error in parsing FileRsync") return r
+  parseJSON _ = fail "error in parsing FileRsync"
diff --git a/src/Hoodle/Type/Widget.hs b/src/Hoodle/Type/Widget.hs
--- a/src/Hoodle/Type/Widget.hs
+++ b/src/Hoodle/Type/Widget.hs
@@ -20,6 +20,7 @@
 , WidgetConfig
 , LayerWidgetConfig 
 , ClockWidgetConfig
+, ScrollWidgetConfig
 -- * lenses 
 , panZoomWidgetPosition
 , panZoomWidgetTouchIsZoom
@@ -30,13 +31,15 @@
 , clockWidgetConfig
 , clockWidgetPosition
 , clockWidgetTime
+, scrollWidgetConfig
 , widgetConfig 
 , doesUsePanZoomWidget
 , doesUseLayerWidget
 , doesUseClockWidget
+, doesUseScrollWidget
 -- * defaults 
 , defaultCanvasWidgets
-, defaultLWConfig 
+, defaultLWConfig
 , defaultWidgetConfig
 -- * utility
 , allWidgets
@@ -48,12 +51,12 @@
 
 
 -- | 
-data WidgetItem = PanZoomWidget | LayerWidget | ClockWidget 
+data WidgetItem = PanZoomWidget | LayerWidget | ClockWidget | ScrollWidget
                 deriving (Show,Eq,Ord)
 
 -- | 
 allWidgets :: [WidgetItem] 
-allWidgets = [PanZoomWidget, LayerWidget, ClockWidget] 
+allWidgets = [PanZoomWidget, LayerWidget, ClockWidget, ScrollWidget] 
 
 
 -- | 
@@ -87,19 +90,24 @@
                                    , _clockWidgetTime :: (Int,Int,Int)
                                    }
      
-                         
+-- | lens for position of clock widget                         
 clockWidgetPosition :: Simple Lens ClockWidgetConfig CanvasCoordinate
 clockWidgetPosition = lens _clockWidgetPosition (\f a -> f { _clockWidgetPosition = a } )
 
+-- | lens for time for clock widget
 clockWidgetTime :: Simple Lens ClockWidgetConfig (Int,Int,Int)
 clockWidgetTime = lens _clockWidgetTime (\f a -> f { _clockWidgetTime = a })
 
+-- |
+data ScrollWidgetConfig = ScrWConfig
 
+
 -- | 
 data CanvasWidgets = 
   CanvasWidgets { _panZoomWidgetConfig :: PanZoomWidgetConfig
                 , _layerWidgetConfig :: LayerWidgetConfig 
-                , _clockWidgetConfig :: ClockWidgetConfig 
+                , _clockWidgetConfig :: ClockWidgetConfig
+                , _scrollWidgetConfig :: ScrollWidgetConfig 
                 , _widgetConfig :: WidgetConfig 
                 }   
 
@@ -115,7 +123,11 @@
 clockWidgetConfig :: Simple Lens CanvasWidgets ClockWidgetConfig 
 clockWidgetConfig = lens _clockWidgetConfig (\f a -> f { _clockWidgetConfig = a })
 
+-- | 
+scrollWidgetConfig :: Simple Lens CanvasWidgets ScrollWidgetConfig
+scrollWidgetConfig = lens _scrollWidgetConfig (\f a -> f { _scrollWidgetConfig = a })
 
+
 -- | default hoodle widgets
 defaultCanvasWidgets :: CanvasWidgets
 defaultCanvasWidgets = 
@@ -123,6 +135,7 @@
   { _panZoomWidgetConfig = defaultPZWConfig 
   , _layerWidgetConfig = defaultLWConfig 
   , _clockWidgetConfig = defaultClkConfig
+  , _scrollWidgetConfig = defaultScrWConfig
   , _widgetConfig = defaultWidgetConfig 
   }   
 
@@ -147,9 +160,15 @@
             }
 
 
+-- | 
+defaultScrWConfig :: ScrollWidgetConfig 
+defaultScrWConfig = ScrWConfig
+
+
 data WidgetConfig = WidgetConfig { _doesUsePanZoomWidget :: Bool 
                                  , _doesUseLayerWidget :: Bool 
-                                 , _doesUseClockWidget :: Bool 
+                                 , _doesUseClockWidget :: Bool
+                                 , _doesUseScrollWidget :: Bool
                                  } 
 
 -- | flag for pan zoom widget 
@@ -164,12 +183,17 @@
 doesUseClockWidget :: Simple Lens WidgetConfig Bool 
 doesUseClockWidget = lens _doesUseClockWidget (\f a -> f {_doesUseClockWidget = a}) 
 
+-- | flag for scroll widget
+doesUseScrollWidget :: Simple Lens WidgetConfig Bool
+doesUseScrollWidget = lens _doesUseScrollWidget (\f a -> f {_doesUseScrollWidget = a})
 
+
 -- | default widget configuration 
 defaultWidgetConfig :: WidgetConfig 
 defaultWidgetConfig = WidgetConfig { _doesUsePanZoomWidget = False
                                    , _doesUseLayerWidget = False
                                    , _doesUseClockWidget = False
+                                   , _doesUseScrollWidget = False
                                    } 
 
 
diff --git a/src/Hoodle/Util.hs b/src/Hoodle/Util.hs
--- a/src/Hoodle/Util.hs
+++ b/src/Hoodle/Util.hs
@@ -3,7 +3,7 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Util 
--- Copyright   : (c) 2013 Ian-Woo Kim
+-- Copyright   : (c) 2013, 2014 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
@@ -15,7 +15,9 @@
 module Hoodle.Util where
 
 import Control.Applicative 
-import Data.Attoparsec.Char8 
+import Control.Monad.IO.Class
+import Control.Monad.Trans.Maybe
+import Data.Attoparsec.ByteString.Char8
 import qualified Data.ByteString.Char8 as B
 import Data.Maybe
 import Data.Time.Clock 
@@ -36,16 +38,30 @@
 (#) = flip ($)
 infixr 0 #
 
+-- safehead :: [a] -> Maybe a
+-- safehead [] = Nothing
+-- safehead (a:_) = a
+
 maybeFlip :: Maybe a -> b -> (a->b) -> b  
 maybeFlip m n j = maybe n j m   
 
-uncurry4 :: (a->b->c->d->e)->(a,b,c,d)->e 
-uncurry4 f (x,y,z,w) = f x y z w 
-
 maybeRead :: Read a => String -> Maybe a 
 maybeRead = fmap fst . listToMaybe . reads 
 
+runMaybeT_ :: (Monad m) => MaybeT m a -> m ()
+runMaybeT_ m = runMaybeT m >> return () 
 
+fromJustError :: String -> Maybe a -> a
+fromJustError _   (Just x) = x
+fromJustError err Nothing = error err
+
+either_ :: (Monad m) => (b -> m ()) -> Either a b -> m ()
+either_ = either (const (return ()))
+
+
+uncurry4 :: (a->b->c->d->e)->(a,b,c,d)->e 
+uncurry4 f (x,y,z,w) = f x y z w 
+
 getLargestWidth :: Hoodle -> Double 
 getLargestWidth hdl = 
   let ws = map (dim_width . page_dim) (hoodle_pages hdl)  
@@ -76,11 +92,15 @@
   hPutStrLn outh str
   hClose outh 
 
+
+-- | for debugging
+msgShout :: (MonadIO m) => String -> m ()
+msgShout = liftIO . putStrLn
+
+
 -- | 
 maybeError' :: String -> Maybe a -> a
 maybeError' str = maybe (error str) id
-
-
 
 data UrlPath = FileUrl FilePath | HttpUrl String 
              deriving (Show,Eq)
diff --git a/src/Hoodle/View/Coordinate.hs b/src/Hoodle/View/Coordinate.hs
--- a/src/Hoodle/View/Coordinate.hs
+++ b/src/Hoodle/View/Coordinate.hs
@@ -1,10 +1,11 @@
+{-# LANGUAGE CPP #-}
 {-# LANGUAGE GADTs #-} 
 {-# LANGUAGE TupleSections #-}
 
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.View.Coordinate
--- Copyright   : (c) 2012, 2013 Ian-Woo Kim
+-- Copyright   : (c) 2012-2014 Ian-Woo Kim
 --
 -- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
@@ -22,7 +23,7 @@
 import qualified Data.IntMap as M
 import           Data.Maybe
 import           Data.Monoid
-import           Graphics.UI.Gtk hiding (get,set)
+import qualified Graphics.UI.Gtk as Gtk
 -- from hoodle-platform
 import Data.Hoodle.Simple (Dimension(..))
 import Data.Hoodle.Generic
@@ -50,18 +51,23 @@
   , page2Desktop :: (PageNum,PageCoordinate) -> DesktopCoordinate
   } 
 
+
 -- | make a canvas geometry data structure from current status 
 makeCanvasGeometry :: PageNum 
                       -> PageArrangement vm 
-                      -> DrawingArea 
+                      -> Gtk.DrawingArea 
                       -> IO CanvasGeometry 
 makeCanvasGeometry cpn arr canvas = do 
-  win <- widgetGetDrawWindow canvas
+#ifdef GTK3  
+  Just win <- Gtk.widgetGetWindow canvas
+#else
+  win <- Gtk.widgetGetDrawWindow canvas
+#endif
   let cdim@(CanvasDimension (Dim w' h')) = view canvasDimension arr
-  screen <- widgetGetScreen canvas
-  (ws,hs) <- (,) <$> (fromIntegral <$> screenGetWidth screen)
-                 <*> (fromIntegral <$> screenGetHeight screen)
-  (x0,y0) <- return . ((,) <$> fromIntegral.fst <*> fromIntegral.snd ) =<< drawWindowGetOrigin win
+  screen <- Gtk.widgetGetScreen canvas
+  (ws,hs) <- (,) <$> (fromIntegral <$> Gtk.screenGetWidth screen)
+                 <*> (fromIntegral <$> Gtk.screenGetHeight screen)
+  (x0,y0) <- return . ((,) <$> fromIntegral.fst <*> fromIntegral.snd ) =<< Gtk.drawWindowGetOrigin win
   let corig = CanvasOrigin (x0,y0)
       (deskdim, cvsvbbox, p2d, d2p) = 
         case arr of  
diff --git a/src/Hoodle/View/Draw.hs b/src/Hoodle/View/Draw.hs
--- a/src/Hoodle/View/Draw.hs
+++ b/src/Hoodle/View/Draw.hs
@@ -1,14 +1,15 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DataKinds #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE Rank2Types #-} 
-{-# LANGUAGE TypeFamilies #-} 
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE TypeFamilies #-} 
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.View.Draw 
--- Copyright   : (c) 2011-2014 Ian-Woo Kim
+-- Copyright   : (c) 2011-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -28,14 +29,14 @@
 import           Data.Monoid
 import           Data.Sequence
 import qualified Graphics.Rendering.Cairo as Cairo
-import           Graphics.UI.Gtk hiding (get,set)
+import qualified Graphics.UI.Gtk as Gtk
 -- from hoodle-platform 
 import Data.Hoodle.BBox
 import Data.Hoodle.Generic
 import Data.Hoodle.Predefined
 import Data.Hoodle.Select
 import Data.Hoodle.Simple (Dimension(..),Stroke(..))
-import Data.Hoodle.Zipper (currIndex,current)
+import Data.Hoodle.Zipper (currIndex)
 import Graphics.Hoodle.Render
 import Graphics.Hoodle.Render.Generic
 import Graphics.Hoodle.Render.Highlight
@@ -63,8 +64,9 @@
 newtype SinglePageDraw a = 
   SinglePageDraw 
   { unSinglePageDraw :: RenderCache 
+                     -> CanvasId
                      -> Bool                               -- ^ isCurrentCanvas
-                     -> (DrawingArea, Maybe Cairo.Surface) 
+                     -> (Gtk.DrawingArea, Maybe Cairo.Surface) 
                      -> (PageNum, Page a) 
                      -> ViewInfo SinglePage 
                      -> Maybe BBox 
@@ -131,8 +133,16 @@
 doubleBufferFlush :: Cairo.Surface -> CanvasInfo a -> IO () 
 doubleBufferFlush sfc cinfo = do 
       let canvas = view drawArea cinfo 
-      win <- widgetGetDrawWindow canvas
-      renderWithDrawable win $ do 
+#ifdef GTK3
+      Just win <- Gtk.widgetGetWindow canvas
+#else 
+      win <- Gtk.widgetGetDrawWindow canvas
+#endif
+#ifdef GTK3
+      Gtk.renderWithDrawWindow win $ do 
+#else 
+      Gtk.renderWithDrawable win $ do 
+#endif
         Cairo.setSourceSurface sfc 0 0 
         Cairo.setOperator Cairo.OperatorSource 
         Cairo.paint
@@ -140,11 +150,12 @@
 
 
 -- | common routine for double buffering 
-doubleBufferDraw :: (DrawWindow, Maybe Cairo.Surface)  
-                    -> CanvasGeometry -> Cairo.Render () -> Cairo.Render a
+doubleBufferDraw :: (Gtk.DrawWindow, Maybe Cairo.Surface)  
+                    -> CanvasGeometry 
+                    -> Cairo.Render a
                     -> IntersectBBox
                     -> IO (Maybe a)
-doubleBufferDraw (win,msfc) geometry _xform rndr (Intersect ibbox) = do 
+doubleBufferDraw (win,msfc) geometry rndr (Intersect ibbox) = do 
   let Dim cw ch = unCanvasDimension . canvasDim $ geometry 
       mbbox' = case ibbox of 
         Top -> Just (BBox (0,0) (cw,ch))
@@ -153,7 +164,11 @@
   let action = do 
         case msfc of 
 	  Nothing -> do 
-	    renderWithDrawable win $ do 
+#ifdef GTK3            
+            Gtk.renderWithDrawWindow win $ do
+#else
+	    Gtk.renderWithDrawable win $ do 
+#endif
 	      clipBBox mbbox'
               Cairo.setSourceRGBA 0.5 0.5 0.5 1
               Cairo.rectangle 0 0 cw ch 
@@ -167,7 +182,11 @@
               Cairo.fill
               clipBBox mbbox' 
 	      rndr 
-	    renderWithDrawable win $ do 
+#ifdef GTK3
+            Gtk.renderWithDrawWindow win $ do
+#else
+	    Gtk.renderWithDrawable win $ do 
+#endif 
 	      Cairo.setSourceSurface sfc 0 0   
 	      Cairo.setOperator Cairo.OperatorSource 
 	      Cairo.paint 
@@ -177,7 +196,7 @@
     Middle _ -> Just <$> action 
     Bottom   -> return Nothing 
 
-
+-- |
 mkXform4Page :: CanvasGeometry -> PageNum -> Xform4Page
 mkXform4Page geometry pnum = 
     let CvsCoord (x0,y0) = desktop2Canvas geometry . page2Desktop geometry $ (pnum,PageCoord (0,0))
@@ -186,27 +205,18 @@
         sy = y1-y0
     in Xform4Page x0 y0 sx sy
 
-
 -- | 
 cairoXform4PageCoordinate :: Xform4Page -> Cairo.Render () 
 cairoXform4PageCoordinate xform = do
     Cairo.translate (transx xform) (transy xform)
     Cairo.scale (scalex xform) (scaley xform)
 
- {- do 
-  let CvsCoord (x0,y0) = desktop2Canvas geometry . page2Desktop geometry $ (pnum,PageCoord (0,0))
-      CvsCoord (x1,y1) = desktop2Canvas geometry . page2Desktop geometry $ (pnum,PageCoord (1,1))
-      sx = x1-x0 
-      sy = y1-y0
-  Cairo.translate x0 y0      
-  Cairo.scale sx sy
--}
 -- |   
 data PressureMode = NoPressure | Pressure
   
 -- | 
 drawCurvebitGen  :: PressureMode 
-                    -> DrawingArea
+                    -> Gtk.DrawingArea
                     -> CanvasGeometry 
                     -> Double 
                     -> (Double,Double,Double,Double) 
@@ -216,9 +226,17 @@
                     -> ((Double,Double),Double) 
                     -> IO () 
 drawCurvebitGen pmode canvas geometry wdth (r,g,b,a) pnum pdraw ((x0,y0),z0) ((x,y),z) = do 
-  win <- widgetGetDrawWindow canvas
-  renderWithDrawable win $ do
-    cairoXform4PageCoordinate (mkXform4Page geometry pnum)
+#ifdef GTK3  
+  Just win <- Gtk.widgetGetWindow canvas
+#else 
+  win <- Gtk.widgetGetDrawWindow canvas
+#endif 
+#ifdef GTK3
+  Gtk.renderWithDrawWindow win $ do 
+#else 
+  Gtk.renderWithDrawable win $ do
+#endif
+    cairoXform4PageCoordinate (mkXform4Page geometry pnum) 
     Cairo.setSourceRGBA r g b a
     case pmode of 
       NoPressure -> do 
@@ -243,36 +261,40 @@
 
 -- | 
 drawFuncGen :: em 
-               -> (RenderCache -> (PageNum,Page em) -> Maybe BBox 
+               -> (RenderCache -> CanvasId -> (PageNum,Page em) -> Maybe BBox 
                    -> DrawFlag -> Cairo.Render (Page em)) 
                -> DrawingFunction SinglePage em
 drawFuncGen _typ render = SinglePageDraw func 
-  where func cache isCurrentCvs (canvas,msfc) (pnum,page) vinfo mbbox flag = do 
+  where func cache cid isCurrentCvs (canvas,msfc) (pnum,page) vinfo mbbox flag = do 
           let arr = view pageArrangement vinfo
           geometry <- makeCanvasGeometry pnum arr canvas
-          win <- widgetGetDrawWindow canvas
+#ifdef GTK3          
+          Just win <- Gtk.widgetGetWindow canvas
+#else
+          win <- Gtk.widgetGetDrawWindow canvas
+#endif 
           let ibboxnew = getViewableBBox geometry mbbox 
           let mbboxnew = toMaybe ibboxnew 
               xformfunc = cairoXform4PageCoordinate (mkXform4Page geometry pnum)
               renderfunc = do
                 xformfunc 
-                pg <- render cache (pnum,page) mbboxnew flag
+                pg <- render cache cid (pnum,page) mbboxnew flag
                 -- Start Widget
                 when isCurrentCvs (emphasisCanvasRender ColorBlue geometry)  
                 -- End Widget
                 Cairo.resetClip 
                 return pg 
-          doubleBufferDraw (win,msfc) geometry xformfunc renderfunc ibboxnew 
+          doubleBufferDraw (win,msfc) geometry renderfunc ibboxnew 
           >>= maybe (return page) return 
 
 
 -- | 
-drawFuncSelGen :: (RenderCache -> (PageNum,Page SelectMode) -> Maybe BBox 
+drawFuncSelGen :: (RenderCache -> CanvasId -> (PageNum,Page SelectMode) -> Maybe BBox 
                    -> DrawFlag -> Cairo.Render ()) 
-                  -> (RenderCache -> (PageNum,Page SelectMode) -> Maybe BBox 
+                  -> (RenderCache -> CanvasId -> (PageNum,Page SelectMode) -> Maybe BBox 
                       -> DrawFlag -> Cairo.Render ())
                   -> DrawingFunction SinglePage SelectMode  
-drawFuncSelGen rencont rensel = drawFuncGen SelectMode (\c x y f -> rencont c x y f >> rensel c x y f >> return (snd x)) 
+drawFuncSelGen rencont rensel = drawFuncGen SelectMode (\c i x y f -> rencont c i x y f >> rensel c i x y f >> return (snd x)) 
 
 -- |
 emphasisCanvasRender :: PenColor -> CanvasGeometry -> Cairo.Render ()
@@ -312,14 +334,15 @@
 
 
 -- |
-drawContPageGen :: (RenderCache -> (PageNum,Page EditMode) -> Maybe BBox 
+drawContPageGen :: (RenderCache -> CanvasId -> (PageNum,Page EditMode) -> Maybe BBox 
                     -> DrawFlag -> Cairo.Render (Int,Page EditMode)) 
                    -> DrawingFunction ContinuousPage EditMode
 drawContPageGen render = ContPageDraw func 
   where func :: RenderCache -> Bool -> CanvasInfo ContinuousPage 
              -> Maybe BBox -> Hoodle EditMode -> DrawFlag -> IO (Hoodle EditMode)
         func cache isCurrentCvs cinfo mbbox hdl flag = do 
-          let arr = view (viewInfo.pageArrangement) cinfo
+          let cid = view canvasId cinfo
+              arr = view (viewInfo.pageArrangement) cinfo
               pnum = PageNum . view currentPageNum $ cinfo 
               canvas = view drawArea cinfo 
               msfc = view mDrawSurface cinfo
@@ -330,7 +353,11 @@
                         $ (getPagesInViewPortRange geometry hdl) 
                 where f k = maybe Nothing (\a->Just (k,a)) 
                             . M.lookup (unPageNum k) $ pgs
-          win <- widgetGetDrawWindow canvas
+#ifdef GTK3          
+          Just win <- Gtk.widgetGetWindow canvas
+#else
+          win <- Gtk.widgetGetDrawWindow canvas
+#endif
           let ibboxnew = getViewableBBox geometry mbbox 
           let mbboxnew = toMaybe ibboxnew 
               xformfunc = cairoXform4PageCoordinate (mkXform4Page geometry pnum)
@@ -338,7 +365,7 @@
                 Cairo.identityMatrix 
                 cairoXform4PageCoordinate (mkXform4Page geometry pn)
                 let pgmbbox = fmap (getBBoxInPageCoord geometry pn) mbboxnew
-                render cache (pn,pg) pgmbbox flag
+                render cache cid (pn,pg) pgmbbox flag
               renderfunc = do
                 xformfunc 
                 ndrawpgs <- mapM onepagerender drawpgs 
@@ -352,21 +379,22 @@
                 drawWidgets allWidgets hdl cinfo mbbox_canvas 
                 Cairo.resetClip 
                 return nhdl 
-          doubleBufferDraw (win,msfc) geometry xformfunc renderfunc ibboxnew
+          doubleBufferDraw (win,msfc) geometry renderfunc ibboxnew
           >>= maybe (return hdl) return  
 
 
 -- |
-drawContPageSelGen :: (RenderCache -> (PageNum,Page EditMode) -> Maybe BBox 
+drawContPageSelGen :: (RenderCache -> CanvasId -> (PageNum,Page EditMode) -> Maybe BBox 
                        -> DrawFlag -> Cairo.Render (Int,Page EditMode)) 
-                   -> (RenderCache -> (PageNum, Page SelectMode) -> Maybe BBox 
+                   -> (RenderCache -> CanvasId -> (PageNum, Page SelectMode) -> Maybe BBox 
                        -> DrawFlag -> Cairo.Render (Int,Page SelectMode))
                    -> DrawingFunction ContinuousPage SelectMode
 drawContPageSelGen rendergen rendersel = ContPageDraw func 
   where func :: RenderCache -> Bool -> CanvasInfo ContinuousPage 
              -> Maybe BBox -> Hoodle SelectMode ->DrawFlag -> IO (Hoodle SelectMode) 
         func cache isCurrentCvs cinfo mbbox thdl flag = do 
-          let arr = view (viewInfo.pageArrangement) cinfo
+          let cid = view canvasId cinfo
+              arr = view (viewInfo.pageArrangement) cinfo
               pnum = PageNum . view currentPageNum $ cinfo 
               mtpage = view gselSelected thdl 
               canvas = view drawArea cinfo 
@@ -379,21 +407,25 @@
                         $ (getPagesInViewPortRange geometry hdl) 
                 where f k = maybe Nothing (\a->Just (k,a)) 
                             . M.lookup (unPageNum k) $ pgs
-          win <- widgetGetDrawWindow canvas
+#ifdef GTK3                            
+          Just win <- Gtk.widgetGetWindow canvas
+#else
+          win <- Gtk.widgetGetDrawWindow canvas
+#endif
           let ibboxnew = getViewableBBox geometry mbbox
               mbboxnew = toMaybe ibboxnew
               onepagerender (pn,pg) = do  
                 Cairo.identityMatrix                 
                 let xform = mkXform4Page geometry pn
                 cairoXform4PageCoordinate xform
-                rendergen cache (pn,pg) (fmap (getBBoxInPageCoord geometry pn) mbboxnew) flag
+                rendergen cache cid (pn,pg) (fmap (getBBoxInPageCoord geometry pn) mbboxnew) flag
               selpagerender :: (PageNum, Page SelectMode) 
                             -> Cairo.Render (Int, Page SelectMode) 
               selpagerender (pn,pg) = do 
                 Cairo.identityMatrix
                 let xform = mkXform4Page geometry pn
                 cairoXform4PageCoordinate xform 
-                rendersel cache (pn,pg) (fmap (getBBoxInPageCoord geometry pn) mbboxnew) flag
+                rendersel cache cid (pn,pg) (fmap (getBBoxInPageCoord geometry pn) mbboxnew) flag
               renderfunc :: Cairo.Render (Hoodle SelectMode)
               renderfunc = do
                 let xform = mkXform4Page geometry pnum
@@ -413,8 +445,7 @@
                 drawWidgets allWidgets hdl cinfo mbbox_canvas
                 Cairo.resetClip 
                 return nthdl2  
-          doubleBufferDraw (win,msfc) geometry (cairoXform4PageCoordinate (mkXform4Page geometry pnum)) 
-            renderfunc ibboxnew
+          doubleBufferDraw (win,msfc) geometry renderfunc ibboxnew
           >>= maybe (return thdl) return 
 
 
@@ -422,28 +453,28 @@
 drawSinglePage :: CanvasGeometry -> DrawingFunction SinglePage EditMode
 drawSinglePage geometry = drawFuncGen EditMode f 
   where 
-    f cache (pnum,page) mbbox flag = do 
+    f cache cid (pnum,page) mbbox flag = do 
       let xform = mkXform4Page geometry pnum
       case flag of
-        Clear        -> do (pg',_) <- cairoRenderOption (RBkgDrawPDF,DrawFull) cache (page,Just xform) 
+        Clear        -> do (pg',_) <- cairoRenderOption (RBkgDrawPDF,DrawFull) cache cid (page,Just xform) 
                            return pg' 
-        BkgEfficient -> do (InBBoxBkgBuf pg',_) <- cairoRenderOption (InBBoxOption mbbox) cache (InBBoxBkgBuf page, Just xform) 
+        BkgEfficient -> do (InBBoxBkgBuf pg',_) <- cairoRenderOption (InBBoxOption mbbox) cache cid (InBBoxBkgBuf page, Just xform) 
                            return pg' 
-        Efficient    -> do (InBBox pg',_) <- cairoRenderOption (InBBoxOption mbbox) cache (InBBox page, Just xform)
+        Efficient    -> do (InBBox pg',_) <- cairoRenderOption (InBBoxOption mbbox) cache cid (InBBox page, Just xform)
                            return pg' 
 
 -- |
 drawSinglePageSel :: CanvasGeometry -> DrawingFunction SinglePage SelectMode    
 drawSinglePageSel geometry = drawFuncSelGen rendercontent renderselect
-  where rendercontent cache (pnum,tpg) mbbox flag = do
+  where rendercontent cache cid (pnum,tpg) mbbox flag = do
           let pg' = hPage2RPage tpg 
               xform = mkXform4Page geometry pnum
           case flag of 
-            Clear -> cairoRenderOption (RBkgDrawPDF,DrawFull) cache (pg',Just xform) >> return ()
-            BkgEfficient -> cairoRenderOption (InBBoxOption mbbox) cache (InBBoxBkgBuf pg',Just xform) >> return ()
-            Efficient -> cairoRenderOption (InBBoxOption mbbox) cache (InBBox pg',Just xform) >> return ()
+            Clear -> cairoRenderOption (RBkgDrawPDF,DrawFull) cache cid (pg',Just xform) >> return ()
+            BkgEfficient -> cairoRenderOption (InBBoxOption mbbox) cache cid (InBBoxBkgBuf pg',Just xform) >> return ()
+            Efficient -> cairoRenderOption (InBBoxOption mbbox) cache cid (InBBox pg',Just xform) >> return ()
           return ()
-        renderselect _cache (_pnum,tpg) mbbox _flag = do 
+        renderselect _cache _cid (_pnum,tpg) mbbox _flag = do 
           cairoHittedBoxDraw geometry tpg mbbox
           return ()
 
@@ -451,14 +482,14 @@
 drawContHoodle :: CanvasGeometry -> DrawingFunction ContinuousPage EditMode
 drawContHoodle geometry = drawContPageGen f  
   where 
-    f cache (pnum@(PageNum n),page) mbbox flag = do 
+    f cache cid (pnum@(PageNum n),page) mbbox flag = do 
       let xform = mkXform4Page geometry pnum
       case flag of
-        Clear        -> do (p',_) <- cairoRenderOption (RBkgDrawPDF,DrawFull) cache (page, Just xform) 
+        Clear        -> do (p',_) <- cairoRenderOption (RBkgDrawPDF,DrawFull) cache cid (page, Just xform) 
                            return (n, p')
-        BkgEfficient -> do (p',_) <- cairoRenderOption (InBBoxOption mbbox) cache (InBBoxBkgBuf page, Just xform)
+        BkgEfficient -> do (p',_) <- cairoRenderOption (InBBoxOption mbbox) cache cid (InBBoxBkgBuf page, Just xform)
                            return (n, unInBBoxBkgBuf p')
-        Efficient    -> do (p',_) <- cairoRenderOption (InBBoxOption mbbox) cache (InBBox page, Just xform)
+        Efficient    -> do (p',_) <- cairoRenderOption (InBBoxOption mbbox) cache cid (InBBox page, Just xform)
                            return (n, unInBBox p')
 
 
@@ -466,13 +497,13 @@
 drawContHoodleSel :: CanvasGeometry 
                   -> DrawingFunction ContinuousPage SelectMode
 drawContHoodleSel geometry = drawContPageSelGen renderother renderselect 
-  where renderother cache (pnum@(PageNum n),page) mbbox flag = do
+  where renderother cache cid (pnum@(PageNum n),page) mbbox flag = do
           let xform = mkXform4Page geometry pnum
           case flag of 
-            Clear -> (,) n . fst <$> cairoRenderOption (RBkgDrawPDF,DrawFull) cache (page,Just xform) 
-            BkgEfficient -> (,) n . unInBBoxBkgBuf . fst <$> cairoRenderOption (InBBoxOption mbbox) cache (InBBoxBkgBuf page,Just xform)
-            Efficient -> (,) n . unInBBox . fst <$> cairoRenderOption (InBBoxOption mbbox) cache (InBBox page,Just xform)
-        renderselect _cache (PageNum n,tpg) mbbox _flag = do
+            Clear -> (,) n . fst <$> cairoRenderOption (RBkgDrawPDF,DrawFull) cache cid (page,Just xform) 
+            BkgEfficient -> (,) n . unInBBoxBkgBuf . fst <$> cairoRenderOption (InBBoxOption mbbox) cache cid (InBBoxBkgBuf page,Just xform)
+            Efficient -> (,) n . unInBBox . fst <$> cairoRenderOption (InBBoxOption mbbox) cache cid (InBBox page,Just xform)
+        renderselect _cache _cid (PageNum n,tpg) mbbox _flag = do
           cairoHittedBoxDraw geometry tpg mbbox 
           return (n,tpg)
 
@@ -587,11 +618,12 @@
 
 -- | 
 canvasImageSurface :: RenderCache
+                   -> CanvasId
                    -> Maybe Double  -- ^ multiply 
                    -> CanvasGeometry
                    -> Hoodle EditMode 
                    -> IO (Cairo.Surface,Dimension)
-canvasImageSurface cache mmulti geometry hdl = do 
+canvasImageSurface cache cid mmulti geometry hdl = do 
   let ViewPortBBox bbx_desk = getCanvasViewPort geometry 
       nbbx_desk = case mmulti of
                     Nothing -> bbx_desk 
@@ -615,7 +647,7 @@
             Cairo.translate (z*ws_cvs) (z*hs_cvs)
         let xform = mkXform4Page geometry pn
         cairoXform4PageCoordinate xform
-        cairoRenderOption (InBBoxOption Nothing) cache (InBBox pg,Nothing :: Maybe Xform4Page)  -- Just xform
+        cairoRenderOption (InBBoxOption Nothing) cache cid (InBBox pg, Nothing :: Maybe Xform4Page)
       renderfunc = do 
         Cairo.setSourceRGBA 0.5 0.5 0.5 1
         Cairo.rectangle 0 0 w_cvs h_cvs        
@@ -646,8 +678,11 @@
   when (ClockWidget `elem` witms && view (canvasWidgets.widgetConfig.doesUseClockWidget) cinfo) $
     renderClockWidget mbbox (view (canvasWidgets.clockWidgetConfig) cinfo)    
 
+  when (ScrollWidget `elem` witms && view (canvasWidgets.widgetConfig.doesUseScrollWidget) cinfo) $
+    renderScrollWidget mbbox (view (canvasWidgets.scrollWidgetConfig) cinfo)    
 
 
+
 ---------------------
 -- Pan Zoom Widget --
 ---------------------
@@ -698,12 +733,12 @@
       pg <- MaybeT . return $ view (gpages.at cpn) hdl
       let lyrs = view glayers pg
           n = currIndex lyrs 
-          l = current lyrs 
-          LyBuf msfc = view gbuffer l
+          -- l = current lyrs 
       lift $ renderLayerWidget (show n) mbbox cvscoord 
       when (view layerWidgetShowContent lc) $ do 
-        sfc <- MaybeT . return $ msfc 
-        lift $ renderLayerContent mbbox (view gdimension pg) sfc cvscoord
+        liftIO $ putStrLn "drawLayerWidget: not implemented"
+        -- sfc <- MaybeT . return $ msfc 
+        -- lift $ renderLayerContent mbbox (view gdimension pg) sfc cvscoord
     return () 
 
 renderLayerContent :: Maybe BBox 
@@ -763,28 +798,28 @@
   Cairo.fill
   -- 
   Cairo.identityMatrix 
-  l1 <- createLayout "layer"
-  updateLayout l1 
-  (_,reclog) <- liftIO $ layoutGetExtents l1
-  let PangoRectangle _ _ w1 h1 = reclog 
+  l1 <- Gtk.createLayout "layer"
+  Gtk.updateLayout l1 
+  (_,reclog) <- liftIO $ Gtk.layoutGetExtents l1
+  let Gtk.PangoRectangle _ _ w1 h1 = reclog 
   Cairo.moveTo (x+15) y
   let sx1 = 50 / w1 
       sy1 = 20 / h1 
   Cairo.scale sx1 sy1 
-  layoutPath l1
+  Gtk.layoutPath l1
   Cairo.setSourceRGBA 0 0 0 0.4
   Cairo.fill
   -- 
   Cairo.identityMatrix
-  l <- createLayout str 
-  updateLayout l 
-  (_,reclog2) <- liftIO $ layoutGetExtents l
-  let PangoRectangle _ _ w h = reclog2 
+  l <- Gtk.createLayout str 
+  Gtk.updateLayout l 
+  (_,reclog2) <- liftIO $ Gtk.layoutGetExtents l
+  let Gtk.PangoRectangle _ _ w h = reclog2 
   Cairo.moveTo (x+30) (y+20)
   let sx = 40 / w 
       sy = 60 / h 
   Cairo.scale sx sy 
-  layoutPath l 
+  Gtk.layoutPath l
   Cairo.setSourceRGBA 0 0 0 0.4
   Cairo.fill
 
@@ -822,6 +857,24 @@
   Cairo.lineTo (x+30*sin (div2rad 12 h + div2rad 720 m)) 
                (y-30*cos (div2rad 12 h + div2rad 720 m)) 
   Cairo.stroke
+  -- 
+  Cairo.resetClip 
+
+
+
+------------------
+-- Clock Widget --
+------------------
+
+renderScrollWidget :: Maybe BBox -> ScrollWidgetConfig -> Cairo.Render () 
+renderScrollWidget mbbox _cfg = do 
+  Cairo.identityMatrix 
+  clipBBox mbbox 
+  Cairo.setSourceRGBA 0.5 0.5 0.2 0.3 
+  Cairo.moveTo 100 0
+  Cairo.lineTo 0 50 
+  Cairo.lineTo 200 50 
+  Cairo.fill 
   -- 
   Cairo.resetClip 
 
diff --git a/src/Hoodle/Widget/Clock.hs b/src/Hoodle/Widget/Clock.hs
--- a/src/Hoodle/Widget/Clock.hs
+++ b/src/Hoodle/Widget/Clock.hs
@@ -1,9 +1,9 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Widget.Clock
--- Copyright   : (c) 2013, 2014 Ian-Woo Kim
+-- Copyright   : (c) 2013-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -14,7 +14,7 @@
 
 module Hoodle.Widget.Clock where
 
-import           Control.Lens (view,set,over)
+import           Control.Lens (view,set,over,(.~))
 import           Control.Monad.State 
 import           Data.Functor.Identity (Identity(..))
 import           Data.List (delete)
@@ -25,6 +25,7 @@
 import           Data.Hoodle.Simple 
 import           Graphics.Hoodle.Render.Util.HitTest
 --
+import           Hoodle.Accessor
 import           Hoodle.Coroutine.Draw
 import           Hoodle.Coroutine.Pen
 import           Hoodle.Device
@@ -62,11 +63,13 @@
 startClockWidget :: (CanvasId,CanvasInfo a,CanvasGeometry)
                  -> CWAction 
                  -> MainCoroutine () 
-startClockWidget (cid,cinfo,geometry) (Move (oxy,owxy)) = do 
+startClockWidget (_cid,cinfo,geometry) (Move (oxy,owxy)) = do 
     xst <- get 
-    let hdl = getHoodle xst
-        cache = view renderCache xst
-    (srcsfc,Dim wsfc hsfc) <- liftIO (canvasImageSurface cache Nothing geometry hdl)
+    cache <- renderCache
+    let uhdl = view (unitHoodles.currentUnit) xst
+        hdl = getHoodle uhdl
+        cid = getCurrentCanvasId uhdl
+    (srcsfc,Dim wsfc hsfc) <- liftIO (canvasImageSurface cache cid Nothing geometry hdl)
     -- need to draw other widgets here                             
     let otherwidgets = delete ClockWidget allWidgets 
     liftIO $ Cairo.renderWith srcsfc (drawWidgets otherwidgets hdl cinfo Nothing) 
@@ -107,24 +110,26 @@
                    -> MainCoroutine ()
 moveClockWidget cid geometry (srcsfc,tgtsfc) (CvsCoord (xw,yw)) (CvsCoord (x0,y0)) pcoord = do 
     let CvsCoord (x,y) = (desktop2Canvas geometry . device2Desktop geometry) pcoord 
-    xst <- get 
-    let CanvasDimension (Dim cw ch) = canvasDim geometry 
-        cinfobox = getCanvasInfo cid xst 
-        nposx | xw+x-x0 < -50 = -50 
-              | xw+x-x0 > cw-50 = cw-50 
-              | otherwise = xw+x-x0
-        nposy | yw+y-y0 < -50 = -50 
-              | yw+y-y0 > ch-50 = ch-50 
-              | otherwise = yw+y-y0                             
-        nwpos = CvsCoord (nposx,nposy) 
-        changeact :: CanvasInfo a -> CanvasInfo a 
-        changeact cinfo =  
-          set (canvasWidgets.clockWidgetConfig.clockWidgetPosition) nwpos $ cinfo
-        ncinfobox = (runIdentity . forBoth unboxBiXform (return . changeact)) cinfobox
-    put (setCanvasInfo (cid,ncinfobox) xst)
+    modify $ \xst -> 
+      let uhdl = view (unitHoodles.currentUnit) xst
+          CanvasDimension (Dim cw ch) = canvasDim geometry 
+          cinfobox = getCanvasInfo cid uhdl
+          nposx | xw+x-x0 < -50 = -50 
+                | xw+x-x0 > cw-50 = cw-50 
+                | otherwise = xw+x-x0
+          nposy | yw+y-y0 < -50 = -50 
+                | yw+y-y0 > ch-50 = ch-50 
+                | otherwise = yw+y-y0                             
+          nwpos = CvsCoord (nposx,nposy) 
+          changeact :: CanvasInfo a -> CanvasInfo a 
+          changeact cinfo =  
+            set (canvasWidgets.clockWidgetConfig.clockWidgetPosition) nwpos $ cinfo
+          ncinfobox = (runIdentity . forBoth unboxBiXform (return . changeact)) cinfobox
+      in (unitHoodles.currentUnit .~ (setCanvasInfo (cid,ncinfobox) uhdl)) xst
     -- 
     xst2 <- get 
-    let cinfobox2 = getCanvasInfo cid xst2 
+    let uhdl = view (unitHoodles.currentUnit) xst2
+        cinfobox2 = getCanvasInfo cid uhdl
         cfg = view (unboxLens (canvasWidgets.clockWidgetConfig)) cinfobox2
     liftIO $ forBoth' unboxBiAct (\cinfo-> virtualDoubleBufferDraw srcsfc tgtsfc (return ()) 
                                     (renderClockWidget Nothing cfg) 
@@ -133,9 +138,10 @@
 -- | 
 toggleClock :: CanvasId -> MainCoroutine () 
 toggleClock cid = do 
-  modify (\xst -> 
-            let ncinfobox = (over (unboxLens (canvasWidgets.widgetConfig.doesUseClockWidget)) not 
-                             . getCanvasInfo cid ) xst 
-            in setCanvasInfo (cid,ncinfobox) xst)
+  modify $ \xst ->
+    let uhdl = view (unitHoodles.currentUnit) xst
+        ncinfobox = (over (unboxLens (canvasWidgets.widgetConfig.doesUseClockWidget)) not 
+                           . getCanvasInfo cid ) uhdl
+    in (unitHoodles.currentUnit .~ (setCanvasInfo (cid,ncinfobox) uhdl)) xst
   invalidateInBBox Nothing Efficient cid
 
diff --git a/src/Hoodle/Widget/Dispatch.hs b/src/Hoodle/Widget/Dispatch.hs
--- a/src/Hoodle/Widget/Dispatch.hs
+++ b/src/Hoodle/Widget/Dispatch.hs
@@ -7,7 +7,7 @@
 -- Module      : Hoodle.Widget.Dispatch 
 -- Copyright   : (c) 2011-2014 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -21,25 +21,22 @@
 import Control.Monad.State hiding (forM_)
 import Control.Monad.Trans.Maybe
 import qualified Data.ByteString.Char8 as B
+import qualified Data.Text.Encoding as TE
 import Data.Foldable (forM_)
-
-
--- 
+--
 import Data.Hoodle.BBox
 import Data.Hoodle.Simple 
 import Graphics.Hoodle.Render.Util.HitTest
 import Graphics.Hoodle.Render.Type.Item
 -- 
+import Hoodle.Coroutine.Link
 import Hoodle.Device 
-import Hoodle.ModelAction.ContextMenu
 import Hoodle.Type.Canvas
 import Hoodle.Type.Coroutine
 import Hoodle.Type.HoodleState
-
 import Hoodle.Type.PageArrangement
 import Hoodle.Util
 import Hoodle.View.Coordinate 
-
 import Hoodle.Widget.Clock
 import Hoodle.Widget.Layer
 import Hoodle.Widget.PanZoom
@@ -48,7 +45,8 @@
                -> PointerCoord 
                -> MainCoroutine ()    -- ^ default action 
                -> MainCoroutine ()
-widgetCheckPen cid pcoord defact = get >>= \xst -> forBoth' unboxBiAct (chk xst) (getCanvasInfo cid xst) 
+widgetCheckPen cid pcoord defact = 
+    get >>= \xst -> forBoth' unboxBiAct (chk xst) ((getCanvasInfo cid . view (unitHoodles.currentUnit)) xst)
   where 
     chk :: HoodleState -> CanvasInfo a -> MainCoroutine () 
     chk xstate cinfo = do 
@@ -74,12 +72,9 @@
                      let lnk = bbxed_content lnkbbx
                          loc = link_location lnk
                          mid = case lnk of 
-                           LinkAnchor {..} -> Just (link_linkeddocid,link_anchorid)
+                           LinkAnchor {..} -> Just (TE.decodeUtf8 link_linkeddocid,TE.decodeUtf8 link_anchorid)
                            _ -> Nothing
-
-                     forM_ 
-                       ((urlParse . B.unpack) loc)
-                       (\url -> liftIO (openLinkAction url mid))
+                     forM_  ((urlParse . B.unpack) loc) (\url -> lift (openLinkAction url mid))
                      MaybeT (return (Just ()))
                    _ -> MaybeT (return Nothing))
       case m of        
diff --git a/src/Hoodle/Widget/Layer.hs b/src/Hoodle/Widget/Layer.hs
--- a/src/Hoodle/Widget/Layer.hs
+++ b/src/Hoodle/Widget/Layer.hs
@@ -1,9 +1,9 @@
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Widget.Layer
--- Copyright   : (c) 2013, 2014 Ian-Woo Kim
+-- Copyright   : (c) 2013-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -14,7 +14,7 @@
 
 module Hoodle.Widget.Layer where
 
-import           Control.Lens (view,set,over)
+import           Control.Lens (view,set,over,(.~))
 import           Control.Monad.State 
 import           Data.Functor.Identity (Identity(..))
 import           Data.List (delete)
@@ -26,6 +26,7 @@
 import           Data.Hoodle.Simple 
 import           Graphics.Hoodle.Render.Util.HitTest
 --
+import           Hoodle.Accessor
 import           Hoodle.Coroutine.Draw
 import           Hoodle.Coroutine.Layer
 import           Hoodle.Coroutine.Pen
@@ -67,14 +68,15 @@
                  -> MainCoroutine () 
 startLayerWidget (cid,_cinfo,_geometry) Close = toggleLayer cid 
 startLayerWidget (cid,_cinfo,_geometry) ToggleShowContent = do 
-    liftIO $ putStrLn "ToggleShowContent hitted"
-    modify (over (currentCanvasInfo . unboxLens (canvasWidgets.layerWidgetConfig.layerWidgetShowContent)) not)
+    modify $ over (unitHoodles.currentUnit)
+             $ over (currentCanvasInfo . unboxLens (canvasWidgets.layerWidgetConfig.layerWidgetShowContent)) not
     invalidate cid 
 startLayerWidget (cid,cinfo,geometry) (Move (oxy,owxy)) = do 
     xst <- get 
-    let hdl = getHoodle xst
-        cache = view renderCache xst
-    (srcsfc,Dim wsfc hsfc) <- liftIO (canvasImageSurface cache Nothing geometry hdl)
+    cache <- renderCache
+    let uhdl = view (unitHoodles.currentUnit) xst
+        hdl = getHoodle uhdl
+    (srcsfc,Dim wsfc hsfc) <- liftIO (canvasImageSurface cache cid Nothing geometry hdl)
     -- need to draw other widgets here                             
     let otherwidgets = delete LayerWidget allWidgets 
     liftIO $ Cairo.renderWith srcsfc (drawWidgets otherwidgets hdl cinfo Nothing) 
@@ -121,34 +123,36 @@
                    -> MainCoroutine ()
 moveLayerWidget cid geometry (srcsfc,tgtsfc) (CvsCoord (xw,yw)) (CvsCoord (x0,y0)) pcoord = do 
     let CvsCoord (x,y) = (desktop2Canvas geometry . device2Desktop geometry) pcoord 
-    xst <- get 
-    let CanvasDimension (Dim cw ch) = canvasDim geometry 
-        cinfobox = getCanvasInfo cid xst 
-        nposx | xw+x-x0 < -50 = -50 
-              | xw+x-x0 > cw-50 = cw-50 
-              | otherwise = xw+x-x0
-        nposy | yw+y-y0 < -50 = -50 
-              | yw+y-y0 > ch-50 = ch-50 
-              | otherwise = yw+y-y0                             
-        nwpos = CvsCoord (nposx,nposy) 
-        changeact :: CanvasInfo a -> CanvasInfo a 
-        changeact cinfo =  
-          set (canvasWidgets.layerWidgetConfig.layerWidgetPosition) nwpos $ cinfo
-        ncinfobox = (runIdentity . forBoth unboxBiXform (return . changeact)) cinfobox
-    put (setCanvasInfo (cid,ncinfobox) xst)
-    let hdl = getHoodle xst 
-    -- 
-    xst2 <- get 
-    let cinfobox2 = getCanvasInfo cid xst2 
-    liftIO $ forBoth' unboxBiAct (\cinfo-> virtualDoubleBufferDraw srcsfc tgtsfc (return ()) 
-                                    (drawLayerWidget hdl cinfo Nothing nwpos) 
-                                  >> doubleBufferFlush tgtsfc cinfo) cinfobox2
+    get >>= \xst -> do
+      let uhdl = view (unitHoodles.currentUnit) xst
+          CanvasDimension (Dim cw ch) = canvasDim geometry 
+          cinfobox = getCanvasInfo cid uhdl
+          nposx | xw+x-x0 < -50 = -50 
+                | xw+x-x0 > cw-50 = cw-50 
+                | otherwise = xw+x-x0
+          nposy | yw+y-y0 < -50 = -50 
+                | yw+y-y0 > ch-50 = ch-50 
+                | otherwise = yw+y-y0                             
+          nwpos = CvsCoord (nposx,nposy) 
+          changeact :: CanvasInfo a -> CanvasInfo a 
+          changeact cinfo =  
+            set (canvasWidgets.layerWidgetConfig.layerWidgetPosition) nwpos $ cinfo
+          ncinfobox = (runIdentity . forBoth unboxBiXform (return . changeact)) cinfobox
+      put $ (unitHoodles.currentUnit .~ setCanvasInfo (cid,ncinfobox) uhdl) xst
+      -- 
+      xst2 <- get 
+      let uhdl2 = view (unitHoodles.currentUnit) xst2
+          hdl2 = getHoodle uhdl2
+          cinfobox2 = getCanvasInfo cid uhdl2
+      liftIO $ forBoth' unboxBiAct (\cinfo-> virtualDoubleBufferDraw srcsfc tgtsfc (return ()) 
+                                      (drawLayerWidget hdl2 cinfo Nothing nwpos) 
+                                    >> doubleBufferFlush tgtsfc cinfo) cinfobox2
   
 -- | 
 toggleLayer :: CanvasId -> MainCoroutine () 
 toggleLayer cid = do 
-  modify (\xst -> 
-            let ncinfobox = (over (unboxLens (canvasWidgets.widgetConfig.doesUseLayerWidget)) not 
-                             . getCanvasInfo cid ) xst 
-            in setCanvasInfo (cid,ncinfobox) xst)
-  invalidateInBBox Nothing Efficient cid
+    pureUpdateUhdl $ \uhdl -> 
+      let ncinfobox = (over (unboxLens (canvasWidgets.widgetConfig.doesUseLayerWidget)) not 
+                      . getCanvasInfo cid ) uhdl
+      in setCanvasInfo (cid,ncinfobox) uhdl
+    invalidateInBBox Nothing Efficient cid
diff --git a/src/Hoodle/Widget/PanZoom.hs b/src/Hoodle/Widget/PanZoom.hs
--- a/src/Hoodle/Widget/PanZoom.hs
+++ b/src/Hoodle/Widget/PanZoom.hs
@@ -1,9 +1,11 @@
+{-# LANGUAGE MultiWayIf #-}
+
 -----------------------------------------------------------------------------
 -- |
 -- Module      : Hoodle.Widget.PanZoom
--- Copyright   : (c) 2013, 2014 Ian-Woo Kim
+-- Copyright   : (c) 2013-2015 Ian-Woo Kim
 --
--- License     : GPL-3
+-- License     : BSD3
 -- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
 -- Stability   : experimental
 -- Portability : GHC
@@ -15,6 +17,7 @@
 module Hoodle.Widget.PanZoom where
 
 -- from other packages
+import           Control.Applicative
 import           Control.Lens (view,set,over,(.~))
 import           Control.Monad.Identity 
 import           Control.Monad.State 
@@ -84,15 +87,15 @@
 startPanZoomWidget tchmode (cid,cinfo,geometry) mmode = do 
     modify (doesNotInvalidate .~ True)
     xst <- get 
-    let hdl = getHoodle xst
-        cache = view renderCache xst
+    cache <- renderCache
+    let hdl = (getHoodle . view (unitHoodles.currentUnit)) xst
     case mmode of 
       Nothing -> togglePanZoom cid
       Just (mode,(oxy,owxy)) -> do 
         (srcsfc,Dim wsfc hsfc) <- case mode of 
-          Moving -> liftIO (canvasImageSurface cache Nothing geometry hdl)
-          Zooming -> liftIO (canvasImageSurface cache (Just 1) geometry hdl)
-          Panning _ -> liftIO (canvasImageSurface cache (Just 1) geometry hdl) 
+          Moving -> liftIO (canvasImageSurface cache cid Nothing geometry hdl)
+          Zooming -> liftIO (canvasImageSurface cache cid (Just 1) geometry hdl)
+          Panning _ -> liftIO (canvasImageSurface cache cid (Just 1) geometry hdl) 
         -- need to draw other widgets here                             
         let otherwidgets = delete PanZoomWidget allWidgets 
         liftIO $ Cairo.renderWith 
@@ -114,16 +117,10 @@
                -> (Double,(Double,Double))
 findZoomXform (Dim w h) ((xo,yo),(x0,_y0),(x,_y)) = 
     let tx = x - x0 
-        -- ty = y - y0 
         ztx = 1 + tx / 200
-        -- zty = 1 + ty / 200
         zx | ztx > 2 = 2  
            | ztx < 0.5 = 0.5
            | otherwise = ztx
-        -- zy | zty > 2 = 2  
-        --    | zty < 0.5 = 0.5
-        --    | otherwise = zty                                          
-        -- simplified
         z = zx 
         xtrans = (1 -z)*xo/z-w
         ytrans = (1- z)*yo/z-h 
@@ -187,19 +184,20 @@
           case mpnpgxy of 
             Nothing -> return () 
             Just pnpgxy -> do 
-              xstate <- get
-              geom' <- liftIO $ getCanvasGeometryCvsId cid xstate
+              uhdl <- view (unitHoodles.currentUnit) <$> get
+              geom' <- liftIO $ getCanvasGeometryCvsId cid uhdl
               let DeskCoord (xd,yd) = page2Desktop geom' pnpgxy
                   DeskCoord (xd0,yd0) = canvas2Desktop geom' ccoord 
-              moveViewPortBy (return ()) cid 
-                (\(xorig,yorig)->(xorig+xd-xd0,yorig+yd-yd0)) 
+              moveViewPortBy (return ()) cid (\(xorig,yorig)->(xorig+xd-xd0,yorig+yd-yd0)) 
         Panning _ -> do 
           let (x_d,y_d) = (unDeskCoord . device2Desktop geometry) pcoord  
               (x0_d,y0_d) = (unDeskCoord . canvas2Desktop geometry) 
                               (CvsCoord (x0,y0))
-              (dx_d,dy_d) = (x_d-x0_d,y_d-y0_d)
-          moveViewPortBy (return ()) cid 
-            (\(xorig,yorig)->(xorig-dx_d,yorig-dy_d))                 
+              (dx_d,dy_d) = let (dx_d1,dy_d1) = (x_d-x0_d,y_d-y0_d)
+                            in if | abs dx_d1 < 25 -> (0,dy_d1)
+                                  | abs dy_d1 < 25 -> (dx_d1,0)
+                                  | otherwise -> (dx_d1,dy_d1)
+          moveViewPortBy (return ()) cid (\(xorig,yorig)->(xorig-dx_d,yorig-dy_d))                 
         _ -> return ()
       invalidate cid 
 
@@ -212,11 +210,11 @@
              -> MainCoroutine () 
 movingRender mode cid geometry (srcsfc,tgtsfc) (CvsCoord (xw,yw)) (CvsCoord (x0,y0)) pcoord = do 
     let CvsCoord (x,y) = (desktop2Canvas geometry . device2Desktop geometry) pcoord 
-    xst <- get 
+    uhdl <- view (unitHoodles.currentUnit) <$> get 
     case mode of
       Moving -> do 
         let CanvasDimension (Dim cw ch) = canvasDim geometry 
-            cinfobox = getCanvasInfo cid xst 
+            cinfobox = getCanvasInfo cid uhdl
             nposx | xw+x-x0 < -50 = -50 
                   | xw+x-x0 > cw-50 = cw-50 
                   | otherwise = xw+x-x0
@@ -228,21 +226,21 @@
             changeact cinfo =  
               set (canvasWidgets.panZoomWidgetConfig.panZoomWidgetPosition) nwpos $ cinfo
             ncinfobox = (runIdentity . forBoth unboxBiXform (return.changeact)) cinfobox
-            isTouchZoom = view (unboxLens (canvasWidgets.panZoomWidgetConfig.panZoomWidgetTouchIsZoom)) cinfobox                         
-        put (setCanvasInfo (cid,ncinfobox) xst)
+            isTouchZoom = view (unboxLens (canvasWidgets.panZoomWidgetConfig.panZoomWidgetTouchIsZoom)) cinfobox
+        pureUpdateUhdl $ setCanvasInfo (cid,ncinfobox)
         virtualDoubleBufferDraw srcsfc tgtsfc (return ()) (renderPanZoomWidget isTouchZoom Nothing nwpos)
       Zooming -> do 
-        let cinfobox = getCanvasInfo cid xst               
+        let cinfobox = getCanvasInfo cid uhdl     
         let pos = runIdentity (forBoth' unboxBiAct (return.view (canvasWidgets.panZoomWidgetConfig.panZoomWidgetPosition)) cinfobox)
         let (xo,yo) = (xw+50,yw+50)
             CanvasDimension cdim = canvasDim geometry 
             (z,(xtrans,ytrans)) = findZoomXform cdim ((xo,yo),(x0,y0),(x,y))
-            isTouchZoom = view (unboxLens (canvasWidgets.panZoomWidgetConfig.panZoomWidgetTouchIsZoom)) cinfobox             
+            isTouchZoom = view (unboxLens (canvasWidgets.panZoomWidgetConfig.panZoomWidgetTouchIsZoom)) cinfobox
         virtualDoubleBufferDraw srcsfc tgtsfc 
           (Cairo.save >> Cairo.scale z z >> Cairo.translate xtrans ytrans)
           (Cairo.restore >> renderPanZoomWidget isTouchZoom Nothing pos)
       Panning b -> do 
-        let cinfobox = getCanvasInfo cid xst               
+        let cinfobox = getCanvasInfo cid uhdl               
             CanvasDimension cdim = canvasDim geometry 
             (xtrans,ytrans) = findPanXform cdim ((x0,y0),(x,y))
         let CanvasDimension (Dim cw ch) = canvasDim geometry 
@@ -258,29 +256,29 @@
                       runIdentity (forBoth' unboxBiAct (return.view (canvasWidgets.panZoomWidgetConfig.panZoomWidgetPosition)) cinfobox)
             ncinfobox = set (unboxLens (canvasWidgets.panZoomWidgetConfig.panZoomWidgetPosition)) nwpos cinfobox
             isTouchZoom = view (unboxLens (canvasWidgets.panZoomWidgetConfig.panZoomWidgetTouchIsZoom)) cinfobox 
-        put (setCanvasInfo (cid,ncinfobox) xst)
+        pureUpdateUhdl $ setCanvasInfo (cid,ncinfobox)
         virtualDoubleBufferDraw srcsfc tgtsfc 
           (Cairo.save >> Cairo.translate xtrans ytrans) 
           (Cairo.restore >> renderPanZoomWidget isTouchZoom Nothing nwpos)
     --   
     xst2 <- get 
-    let cinfobox = getCanvasInfo cid xst2 
+    let cinfobox = getCanvasInfo cid . view (unitHoodles.currentUnit) $ xst2 
     liftIO $ forBoth' unboxBiAct (doubleBufferFlush tgtsfc) cinfobox
 
   
 -- | 
 togglePanZoom :: CanvasId -> MainCoroutine () 
 togglePanZoom cid = do 
-    modify $ \xst -> 
-      let cinfobox = getCanvasInfo cid xst 
+    pureUpdateUhdl $ \uhdl -> 
+      let cinfobox = getCanvasInfo cid uhdl
           ncinfobox = over (unboxLens (canvasWidgets.widgetConfig.doesUsePanZoomWidget)) not cinfobox
-      in setCanvasInfo (cid,ncinfobox) xst 
+      in setCanvasInfo (cid,ncinfobox) uhdl
     invalidateInBBox Nothing Efficient cid 
 
 
 -- | 
 touchStart :: CanvasId -> PointerCoord -> MainCoroutine () 
-touchStart cid pcoord = forBoth' unboxBiAct chk =<< liftM (getCanvasInfo cid) get
+touchStart cid pcoord = forBoth' unboxBiAct chk =<< (getCanvasInfo cid . view (unitHoodles.currentUnit) <$> get)
   where
     chk :: CanvasInfo a -> MainCoroutine () 
     chk cinfo = do 
@@ -293,13 +291,13 @@
           CvsCoord (x0,y0) = view (canvasWidgets.panZoomWidgetConfig.panZoomWidgetPosition) cinfo  
           obbox = BBox (x0,y0) (x0+100,y0+100) 
       xst <- get
-          
       if (isPointInBBox obbox (x,y))     
         then do 
-          let changeact :: CanvasInfo a -> CanvasInfo a 
-              changeact = over (canvasWidgets.panZoomWidgetConfig.panZoomWidgetTouchIsZoom) not 
-              ncinfobox = runIdentity . forBoth unboxBiXform (return . changeact) . getCanvasInfo cid $ xst
-          put (setCanvasInfo (cid,ncinfobox) xst)
+          pureUpdateUhdl $ \uhdl -> 
+            let changeact :: CanvasInfo a -> CanvasInfo a 
+                changeact = over (canvasWidgets.panZoomWidgetConfig.panZoomWidgetTouchIsZoom) not 
+                ncinfobox = runIdentity . forBoth unboxBiXform (return . changeact) . getCanvasInfo cid $ uhdl
+            in setCanvasInfo (cid,ncinfobox) uhdl
           invalidateInBBox Nothing Efficient cid 
         else do 
           let b = view (settings.doesUseTouch) xst
@@ -310,7 +308,7 @@
             else do 
               let devlst = view deviceList xst 
               doIOaction $ \_ -> do
-                setToggleUIForFlag "HANDA" (settings.doesUseTouch) xst
+                lensSetToggleUIForFlag "HANDA" (settings.doesUseTouch) xst
                 -- ad hoc 
                 let touchstr = dev_touch_str devlst
                 when (touchstr /= "touch") $ do 
@@ -326,16 +324,16 @@
     updateFlagFromToggleUI "HANDA"  (settings.doesUseTouch)
     xst <- get 
     let devlst = view deviceList xst 
-    let b = view (settings.doesUseTouch) xst
-    when b $ do 
+        uhdl = view (unitHoodles.currentUnit) xst
+        (cid,_cinfobox) = view currentCanvas uhdl
+    when (view (settings.doesUseTouch) xst) $ do 
       -- ad hoc 
       let touchstr = dev_touch_str devlst      
       when (touchstr /= "touch") $ do 
         liftIO $ readProcess "xinput" [ "enable", dev_touch_str devlst ] ""   
         return ()
       --
-      let (cid,_cinfobox) = view currentCanvas xst 
-      put (set (currentCanvasInfo. unboxLens (canvasWidgets.widgetConfig.doesUsePanZoomWidget)) True xst)
+      pureUpdateUhdl $ (currentCanvasInfo. unboxLens (canvasWidgets.widgetConfig.doesUsePanZoomWidget)) .~ True
       invalidateInBBox Nothing Efficient cid   
       return ()
 
diff --git a/src/Hoodle/Widget/Scroll.hs b/src/Hoodle/Widget/Scroll.hs
new file mode 100644
--- /dev/null
+++ b/src/Hoodle/Widget/Scroll.hs
@@ -0,0 +1,36 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      : Hoodle.Widget.Scroll
+-- Copyright   : (c) 2014 Ian-Woo Kim
+--
+-- License     : BSD3
+-- Maintainer  : Ian-Woo Kim <ianwookim@gmail.com>
+-- Stability   : experimental
+-- Portability : GHC
+--
+-- Pan-Zoom widget drawing and action
+-- 
+-----------------------------------------------------------------------------
+
+module Hoodle.Widget.Scroll where
+
+import Control.Lens ((%~))
+--
+import Hoodle.Accessor
+import Hoodle.Coroutine.Draw
+import Hoodle.Type.Canvas
+import Hoodle.Type.Coroutine
+import Hoodle.Type.Enum
+import Hoodle.Type.HoodleState
+import Hoodle.Type.Widget
+
+
+-- | 
+toggleScroll :: CanvasId -> MainCoroutine () 
+toggleScroll cid = do 
+    pureUpdateUhdl $ \uhdl -> 
+      let ncinfobox = 
+            ( (unboxLens (canvasWidgets.widgetConfig.doesUseScrollWidget) %~ not)
+            . getCanvasInfo cid ) uhdl 
+      in setCanvasInfo (cid,ncinfobox) uhdl
+    invalidateInBBox Nothing Efficient cid
