[3.0] Fix build error when using --enable-debug option
[platform/core/uifw/dali-adaptor.git] / adaptors / wayland / input / text / imf / imf-manager-impl-wl.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <imf-manager-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <dali/public-api/object/type-registry.h>
23 #include <dali/integration-api/debug.h>
24
25 // INTERNAL INCLUDES
26 #include <singleton-service-impl.h>
27 #include <adaptor-impl.h>
28 #include <string.h>
29
30 namespace Dali
31 {
32
33 namespace Internal
34 {
35
36 namespace Adaptor
37 {
38
39 namespace
40 {
41
42 #if defined(DEBUG_ENABLED)
43 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_IMF_MANAGER");
44 #endif
45
46 // Currently this code is internal to dali/dali/internal/event/text/utf8.h but should be made Public and used from there instead.
47 size_t Utf8SequenceLength(const unsigned char leadByte)
48 {
49   size_t length = 0;
50
51   if ((leadByte & 0x80) == 0 )          //ASCII character (lead bit zero)
52   {
53     length = 1;
54   }
55   else if (( leadByte & 0xe0 ) == 0xc0 ) //110x xxxx
56   {
57     length = 2;
58   }
59   else if (( leadByte & 0xf0 ) == 0xe0 ) //1110 xxxx
60   {
61     length = 3;
62   }
63   else if (( leadByte & 0xf8 ) == 0xf0 ) //1111 0xxx
64   {
65     length = 4;
66   }
67
68   return length;
69 }
70
71 unsigned int ConvertByteToVisualPosition( const char* utf8String, unsigned int cursorBytePosition )
72 {
73
74   // check first byte so know how many bytes a character is represented by as keyboard returns cursor position in bytes. Which is different for some languages.
75   size_t visualCharacterIndex = 0;
76   size_t byteIndex = 0;
77
78   // iterate through null terminated string checking each character's position against the given byte position ( attr->end_index ).
79   const char leadByte = utf8String[byteIndex];
80   while( leadByte != '\0' )
81   {
82     // attr->end_index is provided as a byte position not character and we need to know the character position.
83     const size_t currentSequenceLength = Utf8SequenceLength( leadByte ); // returns number of bytes used to represent character.
84     if ( byteIndex == cursorBytePosition )
85     {
86       return visualCharacterIndex;
87       // end loop as found cursor position that matches byte position
88     }
89     else
90     {
91       byteIndex += currentSequenceLength; // jump to next character
92       visualCharacterIndex++;  // increment character count so we know our position for when we get a match
93     }
94     DALI_ASSERT_DEBUG( visualCharacterIndex < strlen( utf8String ));
95   }
96
97   return visualCharacterIndex;
98 }
99
100 BaseHandle Create()
101 {
102   return ImfManager::Get();
103 }
104
105 TypeRegistration IMF_MANAGER_TYPE( typeid(Dali::ImfManager), typeid(Dali::BaseHandle), Create );
106
107
108 }
109 bool ImfManager::IsAvailable()
110 {
111   bool available( false );
112
113   Dali::SingletonService service( SingletonService::Get() );
114   if ( service )
115   {
116     available = service.GetSingleton( typeid( Dali::ImfManager ) );
117   }
118   return available;
119 }
120
121 Dali::ImfManager ImfManager::Get()
122 {
123   Dali::ImfManager manager;
124
125   Dali::SingletonService service( SingletonService::Get() );
126   if (! service )
127   {
128     return manager;
129   }
130
131   // Check whether the singleton is already created
132   Dali::BaseHandle handle = service.GetSingleton( typeid( Dali::ImfManager ) );
133   if( handle )
134   {
135     // If so, downcast the handle
136     manager = Dali::ImfManager( dynamic_cast< ImfManager* >( handle.GetObjectPtr() ) );
137   }
138   else if ( Adaptor::IsAvailable() )
139   {
140     // Create instance and register singleton only if the adaptor is available
141     manager = Dali::ImfManager( new ImfManager() );
142     service.Register( typeid( manager ), manager );
143   }
144   else
145   {
146     DALI_LOG_ERROR("Failed to get native window handle\n");
147   }
148   return manager;
149 }
150 ImfManager::ImfManager()
151 : mTextInputManager( TextInputManager::Get() ),
152   mPreEditCursorPosition( 0 ),
153   mEditCursorPosition( 0 ),
154   mRestoreAfterFocusLost( false )
155 {
156   ConnectCallbacks();
157 }
158 ImfManager::~ImfManager()
159 {
160   DisconnectCallbacks();
161 }
162
163 void ImfManager::ConnectCallbacks()
164 {
165   mTextInputManager.PreEditStringSignal().Connect( this, &ImfManager::PreEditStringChange );
166   mTextInputManager.PreEditCursorSignal().Connect( this, &ImfManager::PreEditCursorChange );
167   mTextInputManager.CommitStringSignal().Connect( this, &ImfManager::CommitString );
168   mTextInputManager.DeleteSurroundingTextSignal().Connect( this, &ImfManager::DeleteSurroundingText );
169
170 }
171 void ImfManager::DisconnectCallbacks()
172 {
173   mTextInputManager.PreEditStringSignal().Disconnect( this, &ImfManager::PreEditStringChange );
174   mTextInputManager.PreEditCursorSignal().Disconnect( this, &ImfManager::PreEditCursorChange );
175   mTextInputManager.CommitStringSignal().Disconnect( this, &ImfManager::CommitString );
176   mTextInputManager.DeleteSurroundingTextSignal().Disconnect( this, &ImfManager::DeleteSurroundingText );
177 }
178
179 void ImfManager::PreEditStringChange( unsigned int serial, const std::string text, const std::string commit  )
180 {
181
182   int visualCursorPosition = 0;
183   if( text.length() > 0 )
184   {
185     visualCursorPosition = ConvertByteToVisualPosition( text.c_str(), mPreEditCursorPosition );
186   }
187   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::PreEditChanged to %s, pre-edit cursor %d \n",text.c_str(), mPreEditCursorPosition );
188
189
190   // get the latest visual cursor pre-edit position
191
192   Dali::ImfManager handle( this );
193   Dali::ImfManager::ImfEventData imfEventData( Dali::ImfManager::PREEDIT, text, visualCursorPosition, visualCursorPosition );
194   Dali::ImfManager::ImfCallbackData callbackData = mEventSignal.Emit( handle, imfEventData );
195
196   if( callbackData.update )
197   {
198     mEditCursorPosition = callbackData.cursorPosition;
199     mSurroundingText = callbackData.currentText;
200   }
201
202   if( callbackData.preeditResetRequired )
203   {
204     mPreEditCursorPosition = 0;
205   }
206 }
207 void ImfManager::PreEditCursorChange( int cursor )
208 {
209   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::PreEditCursorChange %d\n", cursor );
210
211   mPreEditCursorPosition = cursor;
212
213 }
214
215 void ImfManager::CommitString( unsigned int serial, const std::string commit )
216 {
217   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::CommitString\n", commit.c_str() );
218
219   Dali::ImfManager handle( this );
220   Dali::ImfManager::ImfEventData imfEventData( Dali::ImfManager::COMMIT, commit, 0, 0 );
221   Dali::ImfManager::ImfCallbackData callbackData = mEventSignal.Emit( handle, imfEventData );
222
223   if( callbackData.update )
224   {
225     SetCursorPosition( callbackData.cursorPosition );
226     SetSurroundingText( callbackData.currentText );
227     mEditCursorPosition = callbackData.cursorPosition;
228     mPreEditCursorPosition = mEditCursorPosition;
229     NotifyCursorPosition();
230   }
231
232 }
233 void ImfManager::NotifyCursorPosition()
234 {
235   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::NotifyCursorPosition \n" );
236
237   // Set surrounding text also sets the cursor/ anchor position
238   SetSurroundingText( mSurroundingText );
239 }
240
241 void ImfManager::DeleteSurroundingText( int index, unsigned int length )
242 {
243   DALI_LOG_INFO( gLogFilter, Debug::General, "ImfManager::DeleteSurroundingText %d %d \n", index, length );
244
245   Dali::ImfManager::ImfEventData imfData( Dali::ImfManager::DELETESURROUNDING, std::string(),index, length );
246   Dali::ImfManager handle( this );
247   mEventSignal.Emit( handle, imfData );
248 }
249
250 void ImfManager::Activate()
251 {
252   Dali::ImfManager handle( this );
253   mActivatedSignal.Emit( handle );
254
255 }
256
257 void ImfManager::Deactivate()
258 {
259   // do nothing for now
260 }
261
262 void ImfManager::Reset()
263 {
264   mSurroundingText = "";
265   mPreEditCursorPosition = 0;
266   mEditCursorPosition  = 0;
267   mTextInputManager.Reset();
268 }
269
270 void* ImfManager::GetContext()
271 {
272   return this;
273 }
274
275 bool ImfManager::RestoreAfterFocusLost() const
276 {
277   return mRestoreAfterFocusLost;
278 }
279
280 void ImfManager::SetRestoreAfterFocusLost( bool toggle )
281 {
282   mRestoreAfterFocusLost = toggle;
283 }
284
285 unsigned int ImfManager::GetCursorPosition() const
286 {
287   return mEditCursorPosition;
288 }
289
290 void ImfManager::SetCursorPosition( unsigned int cursorPosition )
291 {
292   mEditCursorPosition = cursorPosition;
293 }
294
295 void ImfManager::SetSurroundingText(  const std::string& text )
296 {
297   mSurroundingText = text;
298   mTextInputManager.SetSurroundingText( text, mEditCursorPosition, mEditCursorPosition /*anchor*/ );
299 }
300
301 const std::string& ImfManager::GetSurroundingText() const
302 {
303   return mSurroundingText;
304 }
305
306 void ImfManager::NotifyTextInputMultiLine( bool multiLine )
307 {
308 }
309
310 } // Adaptor
311
312 } // Internal
313
314 } // Dali