00001
00002
00003
00004
00005
00019 #ifndef HGUI_H
00020 #define HGUI_H
00021
00022 namespace HGUI
00023 {
00024 const uint32 MARGIN_THIN = 2;
00025 const uint32 MARGIN = 4;
00026 const uint32 MARGIN_THICK = 8;
00027 };
00034 class HFont : public HObjNoCopy
00035 {
00036 typedef HObjNoCopy base_class;
00037 static StringPtr ClassName(void) { return "HFont"; }
00038
00039
00040
00041 public:
00042 int32 m_nFont;
00043
00044
00045
00046 public:
00047 HFont(void) : m_nFont(0)
00048 { }
00049 virtual
00050 ~HFont(void)
00051 { (void) Destroy(); }
00052
00053
00054
00055 public:
00063 ErrCode
00064 Create(StringPtr pstrFamily, StringPtr pstrStyle, StringPtr pstrFile)
00065 {
00066 ASSERT( !IsValid() );
00067 return Set(pstrFamily, pstrStyle, pstrFile);
00068 }
00069
00079 ErrCode
00080 Destroy(void)
00081 {
00082 ErrCode ec = HError::NoError();
00083
00084 if (IsValid())
00085 m_nFont = 0;
00086
00087 return ec;
00088 }
00089
00090
00091
00094 inline int32 Get(void) const
00095 { return m_nFont; }
00098 inline HANDLE GetHandle(void) const
00099 { return reinterpret_cast<HANDLE>(m_nFont); }
00107 ErrCode Set(StringPtr pstrFamily, StringPtr pstrStyle, StringPtr pstrFile)
00108 {
00109 ErrCode ec = HError::NoError();
00110
00111 ASSERT_PTR(pstrFile);
00112
00113 if ((ec = Destroy()) == NO_ERROR)
00114 {
00115 DEBUG_LOG("HFont::Set() => \"%s\"\n", pstrFile);
00116 m_nFont = GI_create_font( TEXT(pstrFamily),
00117 TEXT(pstrStyle),
00118 TEXT(pstrFile));
00119 }
00120
00121 return ec;
00122 }
00127 ErrCode SetDefault(void)
00128 {
00129 ErrCode ec = HError::NoError();
00130
00131 if ((ec = Destroy()) == NO_ERROR)
00132 m_nFont = GI_GetDefaultFont();
00133
00134 return ec;
00135 }
00136
00137
00138
00141 inline bool IsValid(void) const
00142 { return m_nFont ? true : false; }
00143 };
00152 class HPoint : public HObj
00153 {
00154 typedef HObj base_class;
00155 static StringPtr ClassName(void) { return "HPoint"; }
00156
00157
00158
00159 public:
00160 int32 x;
00161 int32 y;
00162
00163
00164
00165 public:
00166 HPoint(void) : x(0), y(0)
00167 { }
00168 HPoint(int32 nX, int32 nY) : x(nX), y(nY)
00169 { }
00170
00171
00172
00173 public:
00182 void
00183 Offset(int32 nXDelta, int32 nYDelta)
00184 { x += nXDelta; y += nYDelta; }
00190 virtual StringPtr
00191 ToString(void) const
00192 {
00193 HString strTmp;
00194
00195 (void) strTmp.Format("(%ld, %ld)", x, y);
00196 return strTmp.GetString();
00197 }
00198
00199
00200
00204 inline void Set(int32 nX, int32 nY)
00205 { x = nX; y = nY; }
00207 inline void SetEmpty(void)
00208 { x = y = 0; }
00209
00210
00211
00214 inline bool IsZero(void) const
00215 { return (x == 0 && y == 0); }
00216
00217
00218
00219 bool operator == (const HPoint & rhs) const
00220 { return (x == rhs.x && y == rhs.y); }
00221
00222 bool operator != (const HPoint & rhs) const
00223 { return (x != rhs.x || y != rhs.y); }
00224
00225 HPoint & operator += (const HPoint & rhs)
00226 { x += rhs.x; y += rhs.y; return *this; }
00227
00228 HPoint & operator -= (const HPoint & rhs)
00229 { x -= rhs.x; y -= rhs.y; return *this; }
00230
00231 HPoint & operator += (const int32 nDelta)
00232 { x += nDelta; y += nDelta; return *this; }
00233
00234 HPoint & operator -= (const int32 nDelta)
00235 { x -= nDelta; y -= nDelta; return *this; }
00236 };
00245 class HRect : public s_region,
00246 public HObj
00247 {
00248 typedef HObj base_class;
00249 static StringPtr ClassName(void) { return "HRect"; }
00250
00251
00252
00253
00254
00255
00256
00257 public:
00258 HRect(void)
00259 { SetEmpty(); }
00260 HRect(int32 nL, int32 nT, int32 nR, int32 nB)
00261 { Set(nL, nT, nR, nB); }
00262 HRect(const s_region & rhs)
00263 { x1 = rhs.x1; y1 = rhs.y1; x2 = rhs.x2; y2 = rhs.y2; }
00264 HRect(const HPoint & ptTL, const HPoint & ptBR)
00265 { Set(ptTL, ptBR); }
00266 virtual
00267 ~HRect(void)
00268 { }
00269
00270
00271
00272 public:
00281 ErrCode
00282 CenterToScreen(void)
00283 {
00284 s_resolution screen;
00285 ErrCode ec = HError::NoError();
00286
00287 if (GI_get_resolution(&screen) == S_OK)
00288 {
00289 Normalize();
00290 Offset( (screen.width - GetWidth()) / 2,
00291 (screen.height - GetHeight()) / 2);
00292 }
00293 else
00294 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00295
00296 return ec;
00297 }
00308 bool
00309 Inflate(int32 nXDelta, int32 nYDelta)
00310 {
00311 x1 -= nXDelta;
00312 x2 += nXDelta;
00313 y1 -= nYDelta;
00314 y2 += nYDelta;
00315
00316 return IsNotEmpty();
00317 }
00327 void
00328 MoveTo(int32 nX, int32 nY)
00329 { Offset(nX - x1, nY - y1); }
00338 void
00339 MoveTo(const HPoint & pt)
00340 { MoveTo(pt.x, pt.y); }
00348 void
00349 Normalize(void)
00350 {
00351 if (x1 > x2) Humble::swap(x1, x2);
00352 if (y1 > y2) Humble::swap(y1, y2);
00353
00354 if (x1)
00355 x2 -= x1, x1 = 0;
00356
00357 if (y1)
00358 y2 -= y1, y1 = 0;
00359 }
00366 void
00367 Offset(int32 nXDelta, int32 nYDelta)
00368 {
00369 if (nXDelta)
00370 x1 += nXDelta, x2 += nXDelta;
00371
00372 if (nYDelta)
00373 y1 += nYDelta, y2 += nYDelta;
00374 }
00380 void
00381 Offset(HPoint const & ptDelta)
00382 { Offset(ptDelta.x, ptDelta.y); }
00388 virtual StringPtr
00389 ToString(void) const
00390 {
00391 HString strTmp;
00392
00393 (void) strTmp.Format("(%d,%d)-(%d,%d)", x1, y1, x2, y2);
00394 return strTmp.GetString();
00395 }
00396
00397
00398
00402 inline bool Get(s_region & rect) const
00403 {
00404 rect.x1 = x1, rect.y1 = y1;
00405 rect.x2 = x2, rect.y2 = y2;
00406 return IsNotEmpty();
00407 }
00411 inline HPoint GetBottomRight(void) const
00412 { return HPoint(x2, y2); }
00415 inline HPoint GetDimensions(void) const
00416 { return HPoint(GetWidth(), GetHeight()); }
00420 inline int32 GetHeight(void) const
00421 { return (y2 > y1) ? y2 - y1 : 0; }
00424 inline HPoint GetOrigin(void) const
00425 { return HPoint( min(x1, x2), min(y1, y2) ); }
00429 inline HPoint GetTopLeft(void) const
00430 { return HPoint(x1, y1); }
00434 inline int32 GetWidth(void) const
00435 { return (x2 > x1) ? x2 - x1 : 0; }
00445 bool Set(int32 nL, int32 nT, int32 nR, int32 nB)
00446 {
00447 x1 = nL; y1 = nT;
00448 x2 = nR; y2 = nB;
00449 return IsNotEmpty();
00450 }
00461 bool Set(const HPoint & ptTL, const HPoint & ptBR)
00462 {
00463 x1 = ptTL.x; y1 = ptTL.y;
00464 x2 = ptBR.x; y2 = ptBR.y;
00465 return IsNotEmpty();
00466 }
00470 void SetEmpty(void)
00471 { x1 = y1 = x2 = y2 = 0; }
00472
00473
00474
00478 inline bool Contains(const HPoint & pt) const
00479 { return (pt.x >= x1 && pt.x <= x2 && pt.y >= y1 && pt.y <= y2); }
00483 inline bool IsEmpty(void) const
00484 { return (x1 >= x2 || y1 >= y2); }
00488 inline bool IsNotEmpty(void) const
00489 { return (x1 < x2 && y1 < y2); }
00490
00491
00492
00493 HRect & operator += (const HRect & rhs)
00494 { x1 += rhs.x1; y1 += rhs.y1; x2 += rhs.x2; y2 += rhs.y2; return *this; }
00495
00496 HRect & operator -= (const HRect & rhs)
00497 { x1 -= rhs.x1; y1 -= rhs.y1; x2 -= rhs.x2; y2 -= rhs.y2; return *this; }
00498
00499 bool operator == (const HRect & rhs) const
00500 { return (x1 == rhs.x1 && y1 == rhs.y1 && x2 == rhs.x2 && y2 == rhs.y2); }
00501
00502 bool operator != (const HRect & rhs) const
00503 { return (x1 != rhs.x1 || y1 != rhs.y1 || x2 != rhs.x1 || y2 != rhs.y2); }
00504 };
00512 class HDib : public HObjNoCopy
00513 {
00514 typedef HObjNoCopy base_class;
00515 static StringPtr ClassName(void) { return "HDib"; }
00516
00517
00518
00519 protected:
00520 DIB * m_pDIB;
00521
00522
00523
00524 public:
00525 HDib(void) : m_pDIB(NULL)
00526 { }
00527 virtual
00528 ~HDib(void)
00529 { (void) Destroy(); }
00530
00531
00532
00533 public:
00543 ErrCode
00544 Destroy(void)
00545 {
00546 ErrCode ec = HError::NoError();
00547
00548 if (GOOD_PTR(m_pDIB))
00549 {
00550 if (GI_destroy_DIB(m_pDIB) == S_OK)
00551 m_pDIB = NULL;
00552 else
00553 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00554 }
00555
00556 return ec;
00557 }
00564 ErrCode
00565 LoadFromFile(StringPtr pstrFile)
00566 {
00567 ErrCode ec = HError::NoError();
00568
00569 if (STR_VALID(pstrFile))
00570 {
00571 Destroy();
00572
00573 m_pDIB = GI_load_bitmap(const_cast<TextPtr>(pstrFile), 0);
00574 if (GOOD_PTR(m_pDIB))
00575 {
00576 DEBUG_LOG( "HDIB::LoadFromFile(\"%s\") => %d x %d pixels\n",
00577 pstrFile, m_pDIB->width, m_pDIB->height);
00578 }
00579 else
00580 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00581 }
00582 else
00583 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00584
00585 return ec;
00586 }
00587
00588
00589
00592 inline DIB * GetPtr(void) const
00593 { return m_pDIB; }
00596 void GetDimensions(HRect & rBounds) const
00597 {
00598 if (GOOD_PTR(m_pDIB))
00599 rBounds.Set(0, 0, m_pDIB->width, m_pDIB->height);
00600 else
00601 rBounds.SetEmpty();
00602 }
00605 void GetDimensions(HPoint & ptDim) const
00606 {
00607 if (GOOD_PTR(m_pDIB))
00608 ptDim.Set(m_pDIB->width, m_pDIB->height);
00609 else
00610 ptDim.SetEmpty();
00611 }
00614 inline int32 GetHeight(void) const
00615 { return GOOD_PTR(m_pDIB) ? m_pDIB->height : 0; }
00618 int32 GetWidth(void) const
00619 { return GOOD_PTR(m_pDIB) ? m_pDIB->width : 0; }
00620
00621
00622
00625 inline bool IsValid(void) const
00626 {
00627 return (GOOD_PTR(m_pDIB) &&
00628 m_pDIB->height > 0 && m_pDIB->width > 0);
00629 }
00630
00631
00632
00633 operator DIB *() const
00634 { return GetPtr(); }
00635 };
00643 class HGC : public HObjNoCopy
00644 {
00645 typedef HObjNoCopy base_class;
00646 static StringPtr ClassName(void) { return "HGC"; }
00647
00648
00649
00650 protected:
00651 GC * m_pGC;
00652 int32 m_nFontSize;
00653
00654
00655
00656 public:
00657 HGC(void) : m_pGC(NULL), m_nFontSize(0)
00658 { }
00659 virtual
00660 ~HGC(void)
00661 { (void) Destroy(); }
00662
00663
00664
00665 public:
00670 ErrCode
00671 Create(int32 nType, int32 nWidth, int32 nHeight, HANDLE hWnd)
00672 {
00673 ErrCode ec = HError::NoError();
00674
00675 if (IsValid())
00676 {
00677 DEBUG_LOG("HGC[%p]::Create() => stepping on existing GC\n", this);
00678 (void) Destroy();
00679 }
00680
00681 m_pGC = GC_create_connected(nType, nWidth, nHeight, hWnd);
00682 if (GOOD_PTR(m_pGC))
00683 {
00684 DEBUG_LOG("HGC[%p]::Create() => created GC\n", this);
00685 }
00686 else
00687 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00688
00689 return ec;
00690 }
00695 ErrCode
00696 Destroy(void)
00697 {
00698 ErrCode ec = HError::NoError();
00699
00700 if (GOOD_PTR(m_pGC))
00701 {
00702 if (GC_destroy(m_pGC) == S_OK)
00703 {
00704 m_pGC = NULL;
00705 DEBUG_LOG("HGC[%p]::Destroy() => destroyed GC\n", this);
00706 }
00707 else
00708 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00709 }
00710
00711 return ec;
00712 }
00725 ErrCode
00726 DrawDib(const HDib & dib, const HPoint & ptOrg, HRect const * prSrc = NULL)
00727 {
00728 ErrCode ec = HError::NoError();
00729
00730 if (!IsValid())
00731 ec = HError::Set(ERR_NOT_INITIALIZED, __FILE__, __LINE__);
00732 else if (!dib.IsValid())
00733 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00734 else
00735 {
00736 sBlit blit;
00737
00738 GC_ResetBlit(&blit);
00739
00740 blit.hDIB = dib.GetPtr();
00741 blit.iDestX = ptOrg.x;
00742 blit.iDestY = ptOrg.y;
00743
00744 if (GOOD_PTR(prSrc))
00745 {
00746 blit.iSrcX = prSrc->x1;
00747 blit.iSrcY = prSrc->y1;
00748 blit.iWidth = prSrc->GetWidth() + 1;
00749 blit.iHeight = prSrc->GetHeight() + 1;
00750 }
00751 else
00752 {
00753 blit.iSrcX = blit.iSrcY = 0;
00754 blit.iHeight = dib.GetHeight();
00755 blit.iWidth = dib.GetWidth();
00756 }
00757
00758 if (GC_blit(m_pGC, &blit) != S_OK)
00759 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00760 }
00761
00762 return ec;
00763 }
00775 ErrCode
00776 DrawDib(const HDib & dib, const HRect & rDraw)
00777 {
00778 ErrCode ec = HError::NoError();
00779
00780 if (!IsValid())
00781 ec = HError::Set(ERR_NOT_INITIALIZED, __FILE__, __LINE__);
00782 else if (!dib.IsValid())
00783 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00784 else
00785 {
00786 sBlit blit;
00787
00788 GC_ResetBlit(&blit);
00789
00790 blit.hDIB = dib.GetPtr();
00791 blit.iDestX = rDraw.x1;
00792 blit.iDestY = rDraw.y1;
00793 blit.iSrcX = rDraw.x1;
00794 blit.iSrcY = rDraw.y1;
00795 blit.iWidth = rDraw.GetWidth() + 1;
00796 blit.iHeight = rDraw.GetHeight() + 1;
00797
00798 if (GC_blit(m_pGC, &blit) != S_OK)
00799 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00800 }
00801
00802 return ec;
00803 }
00812 ErrCode
00813 DrawLine(int32 nXFrom, int32 nYFrom, int32 nXTo, int32 nYTo) const
00814 {
00815 ErrCode ec = HError::NoError();
00816
00817 if (!IsValid())
00818 ec = HError::Set(ERR_NOT_INITIALIZED, __FILE__, __LINE__);
00819 else if (GC_draw_line(m_pGC, nXFrom, nYFrom, nXTo, nYTo) != S_OK)
00820 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00821 else
00822 {
00823 }
00824
00825 return ec;
00826 }
00833 inline ErrCode
00834 DrawLine(const HPoint & ptFrom, const HPoint & ptTo) const
00835 {
00836 return DrawLine(ptFrom.x, ptFrom.y, ptTo.x, ptTo.y);
00837 }
00846 ErrCode
00847 DrawRect(int32 nX, int32 nY, int32 nXDim, int32 nYDim) const
00848 {
00849 ErrCode ec = HError::NoError();
00850
00851 if (!IsValid())
00852 ec = HError::Set(ERR_NOT_INITIALIZED, __FILE__, __LINE__);
00853 else if (GC_draw_rect(m_pGC, nX, nY, nXDim, nYDim) != S_OK)
00854 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00855 else
00856 {
00857 }
00858
00859 return ec;
00860 }
00866 inline ErrCode
00867 DrawRect(const HRect & rDraw) const
00868 {
00869 return DrawRect(rDraw.x1, rDraw.y1, rDraw.GetWidth(), rDraw.GetHeight());
00870 }
00877 ErrCode
00878 DrawText(const HRect & rText, StringPtr pstr)
00879 {
00880 s_region rect;
00881 ErrCode ec = HError::NoError();
00882
00883 if (!IsValid())
00884 ec = HError::Set(ERR_NOT_INITIALIZED, __FILE__, __LINE__);
00885 else if (rText.Get(rect) && GC_draw_text(m_pGC, &rect, TEXT(pstr)) != S_OK)
00886 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00887
00888 return ec;
00889 }
00898 ErrCode
00899 FillRect(int32 nX, int32 nY, int32 nXDim, int32 nYDim) const
00900 {
00901 ErrCode ec = HError::NoError();
00902
00903 if (!IsValid())
00904 ec = HError::Set(ERR_NOT_INITIALIZED, __FILE__, __LINE__);
00905 else if (nXDim <= 0 || nYDim <= 0)
00906 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
00907 else if (GC_draw_rect_fill(m_pGC, nX, nY, nXDim, nYDim) != S_OK)
00908 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00909 else
00910 {
00911 }
00912
00913 return ec;
00914 }
00920 inline ErrCode
00921 FillRect(const HRect & rFill) const
00922 {
00923 return FillRect(rFill.x1, rFill.y1, rFill.GetWidth(), rFill.GetHeight());
00924 }
00925
00926
00927
00930 inline GC * Get(void) const
00931 { return m_pGC; }
00932
00935 inline int32 GetFontSize(void) const
00936 { return m_nFontSize; }
00937
00943 ErrCode SetBackColor(COLOR clrBG) const
00944 {
00945 ErrCode ec = HError::NoError();
00946
00947 if (!IsValid())
00948 ec = HError::Set(ERR_NOT_INITIALIZED, __FILE__, __LINE__);
00949 else if (GC_set_bg_color(m_pGC, clrBG) != S_OK)
00950 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00951 else
00952 {
00953
00954 }
00955
00956 return ec;
00957 }
00963 ErrCode SetClipRect(const HRect & rClip) const
00964 {
00965 s_region rect;
00966 ErrCode ec = HError::NoError();
00967
00968 if (!IsValid())
00969 ec = HError::Set(ERR_NOT_INITIALIZED, __FILE__, __LINE__);
00970 else if (rClip.Get(rect) && GC_set_clip(m_pGC, &rect) != S_OK)
00971 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00972 else
00973 {
00974
00975 }
00976
00977 return ec;
00978 }
00986 ErrCode SetColors(COLOR clrBG, COLOR clrFG, uint32 uTrans = ~0)
00987 {
00988 ErrCode ec = HError::NoError();
00989
00990 if (!IsValid())
00991 ec = HError::Set(ERR_NOT_INITIALIZED, __FILE__, __LINE__);
00992 else if (GC_set_fgbgtr_color(m_pGC, clrFG, clrBG, uTrans) != S_OK)
00993 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
00994
00995 return ec;
00996 }
01005 ErrCode SetFont(HFont & font, uint32 uSize = 0, uint32 uFlags = 0, uint32 uTrans = 1) const
01006 {
01007 ErrCode ec = HError::NoError();
01008
01009 if (!IsValid())
01010 ec = HError::Set(ERR_NOT_INITIALIZED, __FILE__, __LINE__);
01011 else if (!font.IsValid())
01012 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
01013 else if (uSize || uFlags)
01014 {
01015 if (GC_set_font_param(m_pGC, font.Get(), uSize, uFlags, uTrans) != S_OK)
01016 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
01017 }
01018 else if (GC_set_font(m_pGC, font.Get()) != S_OK)
01019 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
01020
01021 return ec;
01022 }
01028 ErrCode SetFontFlags(int32 nFlags)
01029 {
01030 ErrCode ec = HError::NoError();
01031
01032 if (!IsValid())
01033 ec = HError::Set(ERR_NOT_INITIALIZED, __FILE__, __LINE__);
01034 else if (GC_set_font_flags(m_pGC, nFlags) != S_OK)
01035 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
01036 else
01037 {
01038
01039 }
01040
01041 return ec;
01042 }
01048 ErrCode SetFontSize(int32 nSize)
01049 {
01050 ErrCode ec = HError::NoError();
01051
01052 if (!IsValid())
01053 ec = HError::Set(ERR_NOT_INITIALIZED, __FILE__, __LINE__);
01054 else if (nSize <= 0)
01055 ec = HError::Set(ERR_BAD_PARAMETER, __FILE__, __LINE__);
01056 else if (GC_set_font_size(m_pGC, nSize) != S_OK)
01057 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
01058 else
01059 {
01060 m_nFontSize = nSize;
01061 }
01062
01063 return ec;
01064 }
01070 ErrCode SetForeColor(COLOR clrFG) const
01071 {
01072 ErrCode ec = HError::NoError();
01073
01074 if (!IsValid())
01075 ec = HError::Set(ERR_NOT_INITIALIZED, __FILE__, __LINE__);
01076 else if (GC_set_fg_color(m_pGC, clrFG) != S_OK)
01077 ec = HError::Set(ERR_API_ERROR, __FILE__, __LINE__);
01078 else
01079 {
01080
01081 }
01082
01083 return ec;
01084 }
01085
01086
01087
01090 inline bool IsValid(void) const
01091 { return GOOD_PTR(m_pGC); }
01092
01093
01094
01095 operator GC *() const
01096 { return Get(); }
01097 };
01098 #endif // HGUI_H
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135