(shift_state): Don't reset ic_info->vars.
[m17n/m17n-lib.git] / src / internal.h
1 /* internal.h -- common header file for the internal CORE and SHELL APIs.
2    Copyright (C) 2003, 2004                             
3      National Institute of Advanced Industrial Science and Technology (AIST)
4      Registration Number H15PRO112
5
6    This file is part of the m17n library.
7
8    The m17n library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public License
10    as published by the Free Software Foundation; either version 2.1 of
11    the License, or (at your option) any later version.
12
13    The m17n library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Lesser General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public
19    License along with the m17n library; if not, write to the Free
20    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21    02111-1307, USA.  */
22
23 #ifndef _M17N_INTERNAL_H_
24 #define _M17N_INTERNAL_H_
25
26 /** @file internal.h
27     @brief a documentation for internal.h
28
29     longer version of internal.h description 
30 */
31
32 extern int m17n__core_initialized;
33 extern int m17n__shell_initialized;
34 extern int m17n__gui_initialized;
35
36 extern int mdebug_hook ();
37
38 /** Return with code RET while setting merror_code to ERR.  */
39
40 #define MERROR(err, ret)        \
41   do {                          \
42     merror_code = (err);        \
43     mdebug_hook ();             \
44     return (ret);               \
45   } while (0)
46
47
48 #define MERROR_GOTO(err, label) \
49   do {                          \
50     if ((err))                  \
51       merror_code = (err);      \
52     mdebug_hook ();             \
53     goto label;                 \
54   } while (0)
55
56
57 #define MWARNING(err)   \
58   do {                  \
59     mdebug_hook ();     \
60     goto warning;       \
61   } while (0)
62
63 #define MFATAL(err)     \
64   do {                  \
65     mdebug_hook ();     \
66     exit (err);         \
67   } while (0)
68
69 #define M_CHECK_CHAR(c, ret)            \
70   if ((c) < 0 || (c) > MCHAR_MAX)       \
71     MERROR (MERROR_CHAR, (ret));        \
72   else
73
74 \f
75 /** Memory allocation stuffs.  */
76
77 /* Call a handler function for memory full situation with argument
78    ERR.  ERR must be one of enum MErrorCode.  By default, the
79    handler function just calls exit () with argument ERR.  */
80
81 #define MEMORY_FULL(err)                \
82   do {                                  \
83     (*m17n_memory_full_handler) (err);  \
84     exit (err);                         \
85   } while (0)
86
87
88 /** The macro MTABLE_MALLOC () allocates memory (by malloc) for an
89     array of SIZE objects.  The size of each object is determined by
90     the type of P.  Then, it sets P to the allocated memory.  ERR must
91     be one of enum MErrorCode.  If the allocation fails, the macro
92     MEMORY_FULL () is called with argument ERR.  */
93
94 #define MTABLE_MALLOC(p, size, err)             \
95   do {                                          \
96     int bytes = sizeof (*(p)) * (size);         \
97     if (! ((p) = (void *) malloc (bytes)))      \
98       MEMORY_FULL (err);                        \
99   } while (0)
100
101
102 /** The macro MTABLE_CALLOC() is like the macro MTABLE_MALLOC but use
103     calloc instead of malloc, thus the allocated memory are zero
104     cleared.  */
105
106 #define MTABLE_CALLOC(p, size, err)                             \
107   do {                                                          \
108     if (! ((p) = (void *) calloc (sizeof (*(p)), size)))        \
109       MEMORY_FULL (err);                                        \
110   } while (0)
111
112
113 /** The macro MTABLE_REALLOC () changes the size of memory block
114     pointed to by P to a size suitable for an array of SIZE objects.
115     The size of each object is determined by the type of P.  ERR must
116     be one of enum MErrorCode.  If the allocation fails, the macro
117     MEMORY_FULL () is called with argument ERR.  */
118
119 #define MTABLE_REALLOC(p, size, err)                                    \
120   do {                                                                  \
121     if (! ((p) = (void *) realloc ((p), sizeof (*(p)) * (size))))       \
122       MEMORY_FULL (err);                                                \
123   } while (0)
124
125
126 /** The macro MTABLE_ALLOCA () allocates memory (by alloca) for an
127     array of SIZE objects.  The size of each object is determined by
128     the type of P.  Then, it sets P to the allocated memory.  ERR must
129     be one of enum MErrorCode.  If the allocation fails, the macro
130     MEMORY_FULL () is called with argument ERR.  */
131
132 #define MTABLE_ALLOCA(p, size, err)             \
133   do {                                          \
134     int bytes = sizeof (*(p)) * (size);         \
135     if (! ((p) = (void *) alloca (bytes)))      \
136       MEMORY_FULL (err);                        \
137     memset ((p), 0, bytes);                     \
138   } while (0)
139
140
141 /** short description of MSTRUCT_MALLOC */
142 /** The macro MSTRUCT_MALLOC () allocates memory (by malloc) for an
143     object whose size is determined by the type of P, and sets P to
144     the allocated memory.  ERR must be one of enum MErrorCode.  If
145     the allocation fails, the macro MEMORY_FULL () is called with
146     argument ERR.  */
147
148 #define MSTRUCT_MALLOC(p, err)                          \
149   do {                                                  \
150     if (! ((p) = (void *) malloc (sizeof (*(p)))))      \
151       MEMORY_FULL (err);                                \
152   } while (0)
153
154
155 #define MSTRUCT_CALLOC(p, err) MTABLE_CALLOC ((p), 1, (err))
156
157 #define USE_SAFE_ALLOCA \
158   int sa_must_free = 0, sa_size = 0
159
160 /* P must be the same in all calls to SAFE_ALLOCA and SAFE_FREE in a
161    function.  */
162
163 #define SAFE_ALLOCA(P, SIZE)            \
164   do {                                  \
165     if (sa_size < (SIZE))               \
166       {                                 \
167         if (sa_must_free)               \
168           (P) = realloc ((P), (SIZE));  \
169         else                            \
170           {                             \
171             (P) = alloca ((SIZE));      \
172             if (! (P))                  \
173               {                         \
174                 (P) = malloc (SIZE);    \
175                 sa_must_free = 1;       \
176               }                         \
177           }                             \
178         if (! (P))                      \
179           MEMORY_FULL (1);              \
180         sa_size = (SIZE);               \
181       }                                 \
182   } while (0)
183
184 #define SAFE_FREE(P)                    \
185   do {                                  \
186     if (sa_must_free && sa_size > 0)    \
187       {                                 \
188         free ((P));                     \
189         sa_must_free = sa_size = 0;     \
190       }                                 \
191   } while (0)
192
193 \f
194 /** Extendable array.  */
195
196 #define MLIST_RESET(list)       \
197   ((list)->used = 0)
198
199
200 #define MLIST_INIT1(list, mem, increment)       \
201   do {                                          \
202     (list)->size = (list)->used = 0;            \
203     (list)->inc = (increment);                  \
204     (list)->mem = NULL;                         \
205   } while (0)
206
207
208 #define MLIST_APPEND1(list, mem, elt, err)                      \
209   do {                                                          \
210     if ((list)->inc <= 0)                                       \
211       mdebug_hook ();                                           \
212     if ((list)->size == (list)->used)                           \
213       {                                                         \
214         (list)->size += (list)->inc;                            \
215         MTABLE_REALLOC ((list)->mem, (list)->size, (err));      \
216       }                                                         \
217     (list)->mem[(list)->used++] = (elt);                        \
218   } while (0)
219
220
221 #define MLIST_PREPEND1(list, mem, elt, err)                     \
222   do {                                                          \
223     if ((list)->inc <= 0)                                       \
224       mdebug_hook ();                                           \
225     if ((list)->size == (list)->used)                           \
226       {                                                         \
227         (list)->size += (list)->inc;                            \
228         MTABLE_REALLOC ((list)->mem, (list)->size, (err));      \
229       }                                                         \
230     memmove ((list)->mem + 1, (list)->mem,                      \
231              sizeof *((list)->mem) * ((list)->used));           \
232     (list)->mem[0] = (elt);                                     \
233     (list)->used++;                                             \
234   } while (0)
235
236
237 #define MLIST_INSERT1(list, mem, idx, len, err)                         \
238   do {                                                                  \
239     while ((list)->used + (len) > (list)->size)                         \
240       {                                                                 \
241         (list)->size += (list)->inc;                                    \
242         MTABLE_REALLOC ((list)->mem, (list)->size, (err));              \
243       }                                                                 \
244     memmove ((list)->mem + ((idx) + (len)), (list)->mem + (idx),        \
245              (sizeof *((list)->mem)) * ((list)->used - (idx)));         \
246     (list)->used += (len);                                              \
247   } while (0)
248
249
250 #define MLIST_DELETE1(list, mem, idx, len)                              \
251   do {                                                                  \
252     memmove ((list)->mem + (idx), (list)->mem + (idx) + (len),          \
253              (sizeof *((list)->mem)) * ((list)->used - (idx) - (len))); \
254     (list)->used -= (len);                                              \
255   } while (0)
256
257
258 #define MLIST_COPY1(list0, list1, mem, err)                     \
259   do {                                                          \
260     (list0)->size = (list0)->used = (list1)->used;              \
261     (list0)->inc = 1;                                           \
262     MTABLE_MALLOC ((list0)->mem, (list0)->used, (err));         \
263     memcpy ((list0)->mem, (list1)->mem,                         \
264             (sizeof (list0)->mem) * (list0)->used);             \
265   } while (0)
266
267
268 #define MLIST_FREE1(list, mem)          \
269   if ((list)->size)                     \
270     {                                   \
271       free ((list)->mem);               \
272       (list)->mem = NULL;               \
273       (list)->size = (list)->used = 0;  \
274     }                                   \
275   else
276
277 \f
278
279 typedef struct
280 {
281   void (*freer) (void *);
282   int size, inc, used;
283   unsigned *counts;
284 } M17NObjectRecord;
285
286 typedef struct
287 {
288   /**en Reference count of the object.  */
289   /**ja ¥ª¥Ö¥¸¥§¥¯¥È¤Î»²¾È¿ô.  */
290   unsigned ref_count : 16;
291
292   unsigned ref_count_extended : 1;
293
294   /**en A flag bit used for various perpose.  */
295   /**ja ¤µ¤Þ¤¶¤Þ¤ÊÌÜŪ¤ËÍѤ¤¤é¤ì¤ë¥Õ¥é¥°¥Ó¥Ã¥È.  */
296   unsigned flag : 15;
297
298   union {
299     /**en If <ref_count_extended> is zero, a function to free the
300        object.  */
301     /**ja <ref_count_extended> ¤¬ 0 ¤Ê¤é¤Ð¥ª¥Ö¥¸¥§¥¯¥È¤ò²òÊü¤¹¤ë´Ø¿ô.  */
302     void (*freer) (void *);
303     /**en If <ref_count_extended> is nonzero, a pointer to the
304        struct M17NObjectRecord.  */
305     /**ja <ref_count_extended> ¤¬ 0 ¤Ç¤Ê¤±¤ì¤Ð¹½Â¤ÂΠM17NObjectRecord ¤Ø¤Î¥Ý¥¤¥ó¥¿.  */
306     M17NObjectRecord *record;
307   } u;
308 } M17NObject;
309
310
311 /** Allocate a managed object OBJECT which has freer FREE_FUNC.  */
312
313 #define M17N_OBJECT(object, free_func, err)             \
314   do {                                                  \
315     MSTRUCT_CALLOC ((object), (err));                   \
316     ((M17NObject *) (object))->ref_count = 1;           \
317     ((M17NObject *) (object))->u.freer = free_func;     \
318   } while (0)
319
320
321 /**en Increment the reference count of OBJECT if the count is not
322    0.  */
323 /**ja OBJECT ¤Î»²¾È¿ô¤¬ 0 ¤Ç¤Ê¤±¤ì¤Ð 1 Áý¤ä¤¹.  */
324
325 #define M17N_OBJECT_REF(object)                         \
326   do {                                                  \
327     if (((M17NObject *) (object))->ref_count_extended)  \
328       m17n_object_ref (object);                         \
329     else if (((M17NObject *) (object))->ref_count > 0)  \
330       {                                                 \
331         ((M17NObject *) (object))->ref_count++;         \
332         if (! ((M17NObject *) (object))->ref_count)     \
333           {                                             \
334             ((M17NObject *) (object))->ref_count--;     \
335             m17n_object_ref (object);                   \
336           }                                             \
337       }                                                 \
338   } while (0)
339
340
341 #define M17N_OBJECT_REF_NTIMES(object, n)                               \
342   do {                                                                  \
343     int i;                                                              \
344                                                                         \
345     if (((M17NObject *) (object))->ref_count_extended)                  \
346       for (i = 0; i < n; i++)                                           \
347         m17n_object_ref (object);                                       \
348     else if (((M17NObject *) (object))->ref_count > 0)                  \
349       {                                                                 \
350         int orig_ref_count = ((M17NObject *) (object))->ref_count;      \
351                                                                         \
352         for (i = 0; i < n; i++)                                         \
353           if (! ++((M17NObject *) (object))->ref_count)                 \
354             {                                                           \
355               ((M17NObject *) (object))->ref_count = orig_ref_count;    \
356               for (i = 0; i < n; i++)                                   \
357                 m17n_object_ref (object);                               \
358             }                                                           \
359       }                                                                 \
360   } while (0)
361
362
363 /**en Decrement the reference count of OBJECT if the count is greater
364       than 0.  In that case, if the count becomes 0, free OBJECT.  */
365 /**ja OBJECT ¤Î»²¾È¿ô¤¬ 0 ¤è¤êÂ礭¤±¤ì¤Ð 1 ¸º¤é¤¹¡£¸º¤é¤·¤Æ 0 ¤Ë¤Ê¤ì¤Ð
366       OBJECT ¤ò²òÊü¤¹¤ë.  */
367
368 #define M17N_OBJECT_UNREF(object)                                       \
369   do {                                                                  \
370     if (object)                                                         \
371       {                                                                 \
372         if (((M17NObject *) (object))->ref_count_extended)              \
373           m17n_object_unref (object);                                   \
374         else if (((M17NObject *) (object))->ref_count == 0)             \
375           break;                                                        \
376         else                                                            \
377           {                                                             \
378             ((M17NObject *) (object))->ref_count--;                     \
379             if (((M17NObject *) (object))->ref_count == 0)              \
380               {                                                         \
381                 if (((M17NObject *) (object))->u.freer)                 \
382                   (((M17NObject *) (object))->u.freer) (object);        \
383                 else                                                    \
384                   free (object);                                        \
385                 (object) = NULL;                                        \
386               }                                                         \
387           }                                                             \
388       }                                                                 \
389   } while (0)
390
391 typedef struct _M17NObjectArray M17NObjectArray;
392
393 struct _M17NObjectArray
394 {
395   char *name;
396   int count;
397   int size, inc, used;
398   void **objects;
399   M17NObjectArray *next;
400 };
401
402 extern void mdebug__add_object_array (M17NObjectArray *array, char *name);
403
404 #define M17N_OBJECT_ADD_ARRAY(array, name)      \
405   if (mdebug__flag & MDEBUG_FINI)               \
406     mdebug__add_object_array (&array, name);    \
407   else
408
409 extern void mdebug__register_object (M17NObjectArray *array, void *object);
410
411 #define M17N_OBJECT_REGISTER(array, object)     \
412   if (mdebug__flag & MDEBUG_FINI)               \
413     mdebug__register_object (&array, object);   \
414   else
415
416 extern void mdebug__unregister_object (M17NObjectArray *array, void *object);
417
418 #define M17N_OBJECT_UNREGISTER(array, object)   \
419   if (mdebug__flag & MDEBUG_FINI)               \
420     mdebug__unregister_object (&array, object); \
421   else
422
423 \f
424
425 struct MTextPlist;
426
427 struct MText
428 {
429   M17NObject control;
430
431   enum MTextFormat format;
432
433   /**en Number of characters in the M-text */
434   /**ja M-text Ãæ¤Îʸ»ú¿ô */
435   int nchars;
436
437   /**en Number of bytes used to represent the characters in the M-text. */
438   /**ja M-text Ãæ¤Îʸ»ú¤òɽ¤ï¤¹¤¿¤á¤ËÍѤ¤¤é¤ì¤ë¥Ð¥¤¥È¿ô */
439   int nbytes;
440
441   /**en Character sequence of the M-text. */
442   /**ja M-text Ãæ¤Îʸ»úÎó */
443   unsigned char *data;
444
445   /**en Number of bytes allocated for the @c data member. */
446   /**ja ¥á¥ó¥Ð @c data ¤Ë³ä¤êÅö¤Æ¤é¤ì¤¿¥Ð¥¤¥È¿ô */
447   int allocated;
448
449   /**en Pointer to the property list of the M-text. */
450   /**ja M-text ¤Î¥×¥í¥Ñ¥Æ¥£¥ê¥¹¥È¤Ø¤Î¥Ý¥¤¥ó¥¿ */
451   struct MTextPlist *plist;
452
453   /**en Caches of the character position and the corresponding byte position. */
454   /**ja Ê¸»ú°ÌÃÖ¤ª¤è¤ÓÂбþ¤¹¤ë¥Ð¥¤¥È°ÌÃ֤Υ­¥ã¥Ã¥·¥å */
455   int cache_char_pos, cache_byte_pos;
456 };
457
458 /** short description of M_CHECK_POS */
459 /** longer description of M_CHECK_POS */
460
461 #define M_CHECK_POS(mt, pos, ret)               \
462   do {                                          \
463     if ((pos) < 0 || (pos) >= (mt)->nchars)     \
464       MERROR (MERROR_RANGE, (ret));             \
465   } while (0)
466
467
468 /** short description of M_CHECK_POS_X */
469 /** longer description of M_CHECK_POS_X */
470
471 #define M_CHECK_POS_X(mt, pos, ret)             \
472   do {                                          \
473     if ((pos) < 0 || (pos) > (mt)->nchars)      \
474       MERROR (MERROR_RANGE, (ret));             \
475   } while (0)
476
477
478 /** short description of M_CHECK_RANGE */
479 /** longer description of M_CHECK_RANGE */
480
481 #define M_CHECK_RANGE(mt, from, to, ret, ret2)                  \
482   do {                                                          \
483     if ((from) < 0 || (to) < (from) || (to) > (mt)->nchars)     \
484       MERROR (MERROR_RANGE, (ret));                             \
485     if ((from) == (to))                                         \
486       return (ret2);                                            \
487   } while (0)
488
489 #define M_CHECK_RANGE_X(mt, from, to, ret)                      \
490   do {                                                          \
491     if ((from) < 0 || (to) < (from) || (to) > (mt)->nchars)     \
492       MERROR (MERROR_RANGE, (ret));                             \
493   } while (0)
494
495
496 #define M_CHECK_POS_NCHARS(mt, pos, nchars, ret, ret2)  \
497   do {                                                  \
498     int to = (pos) + (nchars);                  \
499                                                         \
500     M_CHECK_RANGE ((mt), (pos), (to), (ret), (ret2));   \
501   } while (0)
502
503
504 #define MTEXT_READ_ONLY_P(mt) ((mt)->allocated < 0)
505
506 #define M_CHECK_READONLY(mt, ret)       \
507   do {                                  \
508     if ((mt)->allocated < 0)            \
509       MERROR (MERROR_MTEXT, (ret));     \
510   } while (0)
511
512 #define mtext_nchars(mt) ((mt)->nchars)
513
514 #define mtext_nbytes(mt) ((mt)->nbytes)
515
516 #define mtext_allocated(mt) ((mt)->allocated)
517
518 #define mtext_reset(mt) (mtext_del ((mt), 0, (mt)->nchars))
519
520 \f
521
522 enum MDebugMaskBit
523   {
524     MDEBUG_INIT =       0x01,
525     MDEBUG_FINI =       0x02,
526     MDEBUG_CHARSET =    0x04,
527     MDEBUG_CODING =     0x08,
528     MDEBUG_DATABASE =   0x10,
529     MDEBUG_FONT =       0x0100,
530     MDEBUG_FONT_FLT =   0x0200,
531     MDEBUG_FONT_OTF =   0x0400,
532     MDEBUG_INPUT =      0x0800,
533     MDEBUG_MAX
534   };
535
536 extern int mdebug__flag;
537 extern void mdebug__push_time ();
538 extern void mdebug__pop_time ();
539 extern void mdebug__print_time ();
540
541 #define MDEBUG_PRINT(msg)               \
542   do {                                  \
543     if (mdebug__flag & mdebug_mask)     \
544       fprintf (stderr, (msg));          \
545   } while (0)
546
547 #define MDEBUG_PRINT1(fmt, arg)         \
548   do {                                  \
549     if (mdebug__flag & mdebug_mask)     \
550       fprintf (stderr, (fmt), (arg));   \
551   } while (0)
552
553 #define MDEBUG_PRINT2(fmt, arg1, arg2)          \
554   do {                                          \
555     if (mdebug__flag & mdebug_mask)             \
556       fprintf (stderr, (fmt), (arg1), (arg2));  \
557   } while (0)
558
559 #define MDEBUG_PRINT3(fmt, arg1, arg2, arg3)            \
560   do {                                                  \
561     if (mdebug__flag & mdebug_mask)                     \
562       fprintf (stderr, (fmt), (arg1), (arg2), (arg3));  \
563   } while (0)
564
565 #define MDEBUG_PRINT4(fmt, arg1, arg2, arg3, arg4)              \
566   do {                                                          \
567     if (mdebug__flag & mdebug_mask)                             \
568       fprintf (stderr, (fmt), (arg1), (arg2), (arg3), (arg4));  \
569   } while (0)
570
571 #define MDEBUG_PRINT5(fmt, arg1, arg2, arg3, arg4, arg5)                \
572   do {                                                                  \
573     if (mdebug__flag & mdebug_mask)                                     \
574       fprintf (stderr, (fmt), (arg1), (arg2), (arg3), (arg4), (arg5));  \
575   } while (0)
576
577
578 #define MDEBUG_PUSH_TIME()              \
579   do {                                  \
580     if (mdebug__flag & mdebug_mask)     \
581       mdebug__push_time ();             \
582   } while (0)
583
584
585 #define MDEBUG_POP_TIME()               \
586   do {                                  \
587     if (mdebug__flag & mdebug_mask)     \
588       mdebug__pop_time ();              \
589   } while (0)
590
591
592 #define MDEBUG_PRINT_TIME(tag, ARG_LIST)        \
593   do {                                          \
594     if (mdebug__flag & mdebug_mask)             \
595       {                                         \
596         fprintf (stderr, " [%s] ", tag);        \
597         mdebug__print_time ();                  \
598         fprintf ARG_LIST;                       \
599         fprintf (stderr, "\n");                 \
600       }                                         \
601   } while (0)
602
603
604 #define SWAP_16(c) (((c) >> 8) | (((c) & 0xFF) << 8))
605
606 #define SWAP_32(c)                      \
607   (((c) >> 24) | (((c) >> 8) & 0xFF00)  \
608    | (((c) & 0xFF00) << 8) | (((c) & 0xFF) << 24))
609
610
611 extern void *(*mdatabase__finder) (MSymbol tag1, MSymbol tag2,
612                                    MSymbol tag3, MSymbol tag4);
613 extern void *(*mdatabase__loader) (void *);
614
615 /* Initialize/finalize function.  */
616
617 extern int msymbol__init ();
618 extern void msymbol__fini ();
619
620 extern int mplist__init ();
621 extern void mplist__fini ();
622
623 extern int mtext__init ();
624 extern void mtext__fini ();
625
626 extern int mtext__prop_init ();
627 extern void mtext__prop_fini ();
628
629 extern int mchartable__init ();
630 extern void mchartable__fini ();
631
632 extern int mcharset__init ();
633 extern void mcharset__fini ();
634
635 extern int mcoding__init ();
636 extern void mcoding__fini ();
637
638 extern int mdatabase__init (void);
639 extern void mdatabase__fini (void);
640
641 extern int mchar__init ();
642 extern void mchar__fini ();
643
644 extern int mlang__init ();
645 extern void mlang__fini ();
646
647 extern int mlocale__init ();
648 extern void mlocale__fini ();
649
650 extern int minput__init ();
651 extern void minput__fini ();
652
653 #endif /* _M17N_INTERNAL_H_ */
654
655 /*
656   Local Variables:
657   coding: euc-japan
658   End:
659 */