Text_cpp.cpp

C:\home\SVGCats_src\src\Text_cpp.cpp

[大目次 | 目次 | 関数]

大目次

目次

関数一覧


   1|/***********************************************************************
   2|  1. <<< 文字列(表示用) (Text) >>> 
   3|************************************************************************/
   4|
   5|#include "mixer_precomp.h"  /* Auto precompiled header, Look at mixer-... folder */
   6|// #pragma hdrstop
   7|
   8|#if defined(USES_MXP_AUTOINC)
   9| #include "text.ah"  /* Auto include header, Look at mixer-... folder */
  10|#endif
  11| 
  12|/*-------------------------------------------------------------------------*/
  13|/* 2. <<<< ◆ (Text_Box) 枠付き文字列(ディスプレイ表示用) >>>>  */ 
  14|/*-------------------------------------------------------------------------*/
  15| 
  16|#ifdef  TEXT_USES_WINDOWS_DC 
  17|
  18|
  19| 
  20|Text_Box::Text_Box() 
  21|{
  22|  m_bInUndoBuf = false;
  23|  m_bHold = false;
  24|  m_bSelected = false;
  25|
  26|  m_Text = "abc";
  27|  m_CenterX = 0,  m_Y = 0;  m_DiffW = 0;
  28|  m_W = 32, m_10H = 320;
  29|  m_10H1 = -1;  /* Draw 前を示す */
  30|  m_10Descent = 0;
  31|  m_Top = 0;
  32|  m_BetweenOfLine = 14;
  33|  m_RotateDegree = 0;
  34|  m_Color = 0x000000;
  35|  m_Font = "MS Pゴシック";
  36|  m_Size = 12;
  37|  m_bBold = false;
  38|  m_bItalic = false;
  39|  m_BasePos = Text_Box_LeftAlign;
  40|  m_bTategaki = false;
  41|
  42|  m_CaretStart = 0;
  43|  m_CaretEnd = 0;
  44|
  45|  m_BoxShape = Text_Box_RectShape;
  46|  m_BoxMarginX = 2,  m_BoxMarginY = 2;
  47|  m_BorderWidth = 1;
  48|  m_BorderColor = 0x000000;
  49|  m_FillColor = 0xFFFFFF;
  50|  m_FillNTrans = 100;
  51|
  52|  m_URL = "";
  53|  m_Target = "_blank";
  54|  m_IdLabel = "";
  55|  ListX_init( &m_Links );
  56|  m_Controler = NULL;
  57|  m_Controler_id = 0;
  58|  StdPlus_onMalloc( this );
  59|}
  60|
  61|
  62|Text_Box::~Text_Box()
  63|{
  64|  StdPlus_onFree( this );
  65|  if ( ! m_bInUndoBuf )   UnlinkAll();
  66|  ListX_finish2( &m_Links, CadPrim_Link, NULL );
  67|}
  68| 
  69|/***********************************************************************
  70|  2-1. <<< [Text_Box::print] CadPrim::print の実装部 >>> 
  71|************************************************************************/
  72|void  Text_Box::print( const char* title )
  73|{
  74|  #ifndef  NDEBUG
  75|    CadPrim_Link*  link;
  76|    RECT  rc;
  77|    int  x, y;
  78|
  79|    c_try {
  80|      GetBox( &rc );
  81|      x = (rc.left + rc.right) / 2;
  82|      y = (rc.top + rc.bottom) / 2;
  83|    }
  84|    c_catch ( Errors_Msg*, msg ) {
  85|      if ( msg->code == SVGCat_Err_NotSetDrawParam ) {
  86|        x = -1;  y = -1;
  87|      }
  88|      else  c_throw_again();
  89|    } c_end_catch;
  90|
  91|    Errors_printf( "%sText_Box[%d:%p]: (%d,%d) %s, hold=%d, sel=%d, undo=%d center=(%d,%d)",
  92|      title, m_id, this, m_CenterX, m_Y, m_Text, m_bHold, m_bSelected,
  93|      m_bInUndoBuf, x,y );
  94|    Errors_printf( "%s  m_Controler = %p, id=%d", title,
  95|      m_Controler, m_Controler_id );
  96|    for ( ListX_forEach( &m_Links, &link, CadPrim_Link ) ) {
  97|      link->print( title );
  98|    }
  99|  #endif
 100|}
 101|
 102|
 103|/***********************************************************************
 104|  2-2. <<< [Text_Box::GetID] CadPrim::GetID の実装部 >>>
 105|************************************************************************/
 106|int  Text_Box::GetID()
 107|{
 108|  return  m_id;
 109|}
 110|
 111|
 112|/***********************************************************************
 113|  2-3. <<< [Text_Box::SetID] CadPrim::SetID の実装部 >>>
 114|************************************************************************/
 115|void  Text_Box::SetID( int id )
 116|{
 117|  m_id = id;
 118|}
 119|
 120|
 121|/***********************************************************************
 122|  2-4. <<< [Text_Box::OnChgedLinkID] CadPrim::OnChgedLinkID の実装部 >>>
 123|************************************************************************/
 124|void  Text_Box::OnChgedLinkID( int oldID, int newID )
 125|{
 126|  CadPrim_Link*  link;
 127|
 128|  for ( ListX_forEach( &m_Links, &link, CadPrim_Link ) ) {
 129|    if ( link->prim_id == oldID )  link->prim_id = newID;
 130|  }
 131|  if ( m_Controler_id == oldID )  m_Controler_id = newID;
 132|}
 133|
 134|
 135|/***********************************************************************
 136|  2-5. <<< [Text_Box::GetTypeID] CadPrim::GetTypeID の実装部 >>>
 137|************************************************************************/
 138|int  Text_Box::GetTypeID()
 139|{
 140|  return  Text_Box_TypeID;
 141|}
 142|
 143|
 144|/***********************************************************************
 145|  2-6. <<< [Text_Box::GetTypeNameJp] CadPrim::GetTypeNameJp の実装部 >>>
 146|************************************************************************/
 147|char*  Text_Box::GetTypeNameJp()
 148|{
 149|  return  "テキスト";
 150|}
 151|
 152|
 153|/***********************************************************************
 154|  2-7. <<< [Text_Box::GetTypeNameEn] CadPrim::GetTypeNameEn の実装部 >>>
 155|************************************************************************/
 156|char*  Text_Box::GetTypeNameEn()
 157|{
 158|  return  "Text";
 159|}
 160|
 161|
 162|/***********************************************************************
 163|  2-8. <<< [Text_Box::SetBInUndoBuf] CadPrim::SetBInUndoBuf の実装部 >>>
 164|************************************************************************/
 165|void  Text_Box::SetBInUndoBuf( bool b )
 166|{
 167|  m_bInUndoBuf = b;
 168|}
 169|
 170|
 171|/***********************************************************************
 172|  2-9. <<< [Text_Box::GetLinkURL] CadPrim::GetLinkURL の実装部 >>>
 173|************************************************************************/
 174|char*  Text_Box::GetLinkURL()
 175|{
 176|  return  (char*)(const char*)m_URL;
 177|}
 178|
 179|
 180|/***********************************************************************
 181|  2-10. <<< [Text_Box::GetIdLabel] CadPrim::GetIdLabel の実装部 >>>
 182|************************************************************************/
 183|char*  Text_Box::GetIdLabel()
 184|{
 185|  return  (char*)(const char*)m_IdLabel;
 186|}
 187|
 188|
 189| 
 190|/***********************************************************************
 191|  2-11. <<< [Text_Box::OutSVG] SVGファイルに属性値を出力する >>> 
 192|【引数】
 193|  ・FILE*   f;    出力先のテキスト・ファイル
 194|************************************************************************/
 195|void  Text_Box::OutSVG( CadPrim_SaveParam* p )
 196|{
 197|  RECT  rc;
 198|  char* urlFName = ( m_URL == "" ? strchr( m_URL, '\0' ) : StrX_refFName(m_URL) );
 199|  bool  bScript = ( strnicmp( urlFName, "script:", 7 ) == 0 );
 200|  char* script = urlFName + 7;
 201|  char  eng_name[256];
 202|  char  trans[20];
 203|
 204|
 205|  /* フォントの英語名を取得する */
 206|  if ( m_Font == "MS ゴシック" )  strcpy( eng_name, "MS-Gothic" );
 207|  else if ( m_Font == "MS Pゴシック" )  strcpy( eng_name, "MS-PGothic" );
 208|  else if ( m_Font == "MS 明朝" )  strcpy( eng_name, "MS-Mincho" );
 209|  else if ( m_Font == "MS P明朝" )  strcpy( eng_name, "MS-PMincho" );
 210|  else  strcpy( eng_name, m_Font );
 211|
 212|
 213|  /* <g> タグをファイルに出力する */
 214|  if ( m_BoxShape != Text_Box_NoFrame || bScript || urlFName[0] == '#' ) {
 215|    fputs( "\t<g", p->f );
 216|    if ( m_IdLabel != "" )  fprintf( p->f, " id=\"%s\"", m_IdLabel );
 217|    if ( urlFName[0] == '#' )  fprintf( p->f, " href=\"%s\"", urlFName );
 218|    if ( p->iTargetPage >= 1 )  fprintf( p->f, " onclick=\"chgPage( evt, %d )\"", p->iTargetPage );
 219|    if ( bScript )  fprintf( p->f, " onclick=\"%s\"", script );
 220|    fputs( ">\n", p->f );
 221|  }
 222|
 223|  /* <a> タグをファイルに出力する */
 224|  if ( m_URL != "" ) {
 225|    if ( ! bScript && urlFName[0] != '#' ) {
 226|      char  stepPath[_MAX_PATH];
 227|      char  stepPath2[_MAX_PATH*2];
 228|
 229|      StrX_cpyStepPath2( stepPath, m_URL, sizeof(stepPath), p->path );
 230|      if ( p->bLower )  StrX_cpyLower( stepPath, stepPath );
 231|      StrX_toHtmlTxt( stepPath, stepPath2, sizeof(stepPath2) );
 232|      fprintf( p->f, "\t<a xlink:href=\"%s\"", stepPath2 );
 233|      if ( m_Target != "" )
 234|        fprintf( p->f, " target=\"%s\"", m_Target );
 235|      fputs( ">\n", p->f );
 236|    }
 237|    else {
 238|      fputs( "<a>\n", p->f );
 239|    }
 240|  }
 241|
 242|  /* 枠を出力する */
 243|  if ( m_BoxShape != Text_Box_NoFrame ) {
 244|    GetBox( &rc );
 245|
 246|    switch ( m_BoxShape ) {
 247|     case  Text_Box_RectShape:
 248|      fprintf( p->f, "\t<rect x=\"%d.5\" y=\"%d.5\" width=\"%d\" height=\"%d\"\n",
 249|        rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top );
 250|      break;
 251|
 252|     case  Text_Box_RoundRectShape:
 253|      fprintf( p->f, "\t<rect x=\"%d.5\" y=\"%d.5\" width=\"%d\" height=\"%d\""
 254|        " rx=\"10\" ry=\"10\"\n",
 255|        rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top );
 256|      break;
 257|
 258|     case  Text_Box_CircleShape:
 259|      if ( rc.right - rc.left == rc.bottom - rc.top ) {
 260|        fprintf( p->f, "\t<circle cx=\"%d.5\" cy=\"%d.5\" r=\"%d\"\n",
 261|          (rc.left + rc.right) / 2,  (rc.top + rc.bottom) / 2,
 262|          (rc.right - rc.left) / 2 );
 263|      }
 264|      else {
 265|        fprintf( p->f, "\t<ellipse cx=\"%d.5\" cy=\"%d.5\" rx=\"%d\" ry=\"%d\"\n",
 266|          (rc.left + rc.right) / 2,  (rc.top + rc.bottom) / 2,
 267|          (rc.right - rc.left) / 2, (rc.bottom - rc.top) / 2 );
 268|      }
 269|      break;
 270|
 271|     case  Text_Box_DiamondShape: {
 272|       int  hasuuX = ( rc.left + rc.right ) % 2;
 273|       int  hasuuY = ( rc.top + rc.bottom ) % 2;
 274|
 275|       fprintf( p->f, "\t<polygon points=\"%d.5,%d.5 %d.5,%d.5 %d.5,%d.5 %d.5,%d.5\"\n",
 276|          (rc.left + rc.right) / 2,  rc.top,
 277|          rc.right + hasuuX,         (rc.top + rc.bottom) / 2,
 278|          (rc.left + rc.right) / 2,  rc.bottom + hasuuY,
 279|          rc.left,                   (rc.top + rc.bottom) / 2 );
 280|      break;
 281|     }
 282|
 283|     case  Text_Box_Parallelogram: {
 284|      int  slide = ( rc.bottom - rc.top ) / 4;
 285|
 286|      fprintf( p->f, "\t<polygon points=\"%d.5,%d.5 %d.5,%d.5 %d.5,%d.5 %d.5,%d.5\"\n",
 287|        rc.left + slide, rc.top, rc.right + slide, rc.top,
 288|        rc.right - slide, rc.bottom, rc.left - slide, rc.bottom );
 289|      break;
 290|     }
 291|    }
 292|
 293|    sprintf( trans, ";fill-opacity:0.%02d", m_FillNTrans );
 294|
 295|    fprintf( p->f, "\t\tstyle=\"fill:rgb(%d,%d,%d);stroke:rgb(%d,%d,%d);"
 296|      "stroke-width:%d%s\"",
 297|      Color_WinRGB_getR( m_FillColor ), Color_WinRGB_getG( m_FillColor ),
 298|      Color_WinRGB_getB( m_FillColor ),
 299|      Color_WinRGB_getR( m_BorderColor ), Color_WinRGB_getG( m_BorderColor ),
 300|      Color_WinRGB_getB( m_BorderColor ),
 301|      m_BorderWidth,
 302|      m_FillNTrans == 100 ? "" : trans );
 303|
 304|    if ( m_RotateDegree != 0 ) {
 305|      fprintf( p->f, " transform=\"rotate(%d,%d,%d)\"",
 306|        m_RotateDegree, m_CenterX, m_Y );
 307|    }
 308|    fputs( "/>\n", p->f );
 309|  }
 310|
 311|
 312|  /* テキストを出力する */
 313|  {
 314|    char*  align;
 315|
 316|    fputs( "\t<text", p->f );
 317|
 318|    if ( !( m_BoxShape != Text_Box_NoFrame || bScript || urlFName[0] == '#' ) )
 319|      if ( m_IdLabel != "" )  fprintf( p->f, " id=\"%s\"", (const char*)m_IdLabel );
 320|
 321|    fprintf( p->f, " x=\"%d.5px\" y=\"%d.5px\"", m_CenterX, m_Y );
 322|
 323|    switch ( m_BasePos ) {
 324|     case  Text_Box_LeftAlign:  align = "start";  break;
 325|     case  Text_Box_CenterAlign:  align = "middle";  break;
 326|     case  Text_Box_RightAlign:  align = "end";  break;
 327|    }
 328|
 329|    fprintf( p->f, " style=\"fill:rgb(%d,%d,%d);font-family:%s;"
 330|      "font-size:%dpt;%s%stext-anchor:%s\"",
 331|      Color_WinRGB_getR( m_Color ), Color_WinRGB_getG( m_Color ),
 332|      Color_WinRGB_getB( m_Color ),
 333|      eng_name, m_Size,
 334|      m_bBold ? "font-weight:bold;" : "",
 335|      m_bItalic ? "font-style:italic;" : "",
 336|      align );
 337|
 338|    if ( m_RotateDegree != 0 ) {
 339|      GetBox( &rc );
 340|      fprintf( p->f, " transform=\"rotate(%d,%d,%d)\"",
 341|        m_RotateDegree, m_CenterX, m_Y );
 342|    }
 343|    if ( m_bTategaki ) {
 344|      fprintf( p->f, " writing-mode=\"tb\"" );
 345|    }
 346|    fputs( " xml:space=\"preserve\">", p->f );
 347|
 348|    {
 349|      const int  len = m_Text.GetLength();
 350|      char*  s1 = (char*)malloc( len + 11 + 1 );  /* +11はページ番号分 */
 351|      char*  s2 = (char*)malloc( len * 5 + 11 + 1 );
 352|      int  i;
 353|
 354|      StrX_cpy1Line( s1, len + 1, m_Text, 1 );
 355|      if ( m_IdLabel == "pagenum" ) {
 356|        sprintf( s1, "%d", p->iPage );
 357|      }
 358|      fputs( StrX_toHtmlTxt( s1, s2, len * 5 + 1 ), p->f );
 359|      if ( m_bTategaki ) {
 360|        for ( i = 2; ; i++ ) {
 361|          if ( StrX_cpy1Line( s1, len + 1, m_Text, i ) == NULL )  break;
 362|          fprintf( p->f, "%s<tspan x=\"%d.5px\" y=\"%d.5px\">%s</tspan>",
 363|            ( i==2 ? "" : "\n\t" ),
 364|            m_CenterX - m_BetweenOfLine * (i - 1),  m_Y,
 365|            StrX_toHtmlTxt( s1, s2, len * 5 + 1 ) );
 366|        }
 367|      }
 368|      else {
 369|        for ( i = 2; ; i++ ) {
 370|          if ( StrX_cpy1Line( s1, len + 1, m_Text, i ) == NULL )  break;
 371|          fprintf( p->f, "%s<tspan x=\"%d.5px\" y=\"%d.5px\">%s</tspan>",
 372|            ( i==2 ? "" : "\n\t" ),
 373|            m_CenterX,  m_Y + m_BetweenOfLine * (i - 1),
 374|            StrX_toHtmlTxt( s1, s2, len * 5 + 1 ) );
 375|        }
 376|      }
 377|      fputs( "</text>\n", p->f );
 378|      free( s2 );
 379|      free( s1 );
 380|    }
 381|  }
 382|
 383|
 384|  /* </a> タグをファイルに出力する */
 385|  if ( m_URL != "" )
 386|    fputs( "\t</a>\n", p->f );
 387|
 388|  /* </g> タグをファイルに出力する */
 389|  if ( m_BoxShape != Text_Box_NoFrame || bScript || urlFName[0] == '#' )
 390|    fprintf( p->f, "\t</g>\n" );
 391|}
 392| 
 393|/***********************************************************************
 394|  2-12. <<< [Text_Box::Draw] CadPrim::Draw の実装部 >>> 
 395|************************************************************************/
 396|void  Text_Box::Draw( CDC* dc, CadPrim_DrawParam* p )
 397|{
 398|  int     zoom = p->zoom;
 399|  RECT    textRect;
 400|  RECT    box;
 401|  CSize   size;
 402|  LOGFONT  logFont;
 403|  int      nTextLine;
 404|  TEXTMETRIC  tx;
 405|  int  i;
 406|  TwoD_XY  xy;
 407|  TwoD_XY  center;
 408|  TwoD_XY  center0;
 409|  ERRORS_FUNC_CPP_VAR( Text_Box_Draw );
 410|  ERRORS_FUNC_START_CPP( Text_Box_Draw );
 411|
 412|  TwoD_XY_init( &center, m_CenterX, m_Y );
 413|  TwoD_XY_init( &center0, 0, 0 );
 414|
 415|
 416|  /* フォントの属性を取得する(10倍の大きさのフォントで SVG Viewer や印刷との誤差を無くしている) */
 417|  {
 418|    CFont   font;
 419|    CFont   font2;
 420|    CFont*  oldFont;
 421|
 422|    font.CreatePointFont( m_Size*100, (m_bTategaki ? CString('@')+m_Font : m_Font), dc );
 423|    font.GetLogFont( &logFont );
 424|    logFont.lfWidth = 0;
 425|    logFont.lfHeight = m_Size * 100;
 426|    logFont.lfWeight = m_bBold ? FW_BOLD : FW_NORMAL;
 427|    logFont.lfItalic = m_bItalic;
 428|    logFont.lfEscapement = - m_RotateDegree * 10 + (m_bTategaki ? 2700 :0);
 429|    font2.CreatePointFontIndirect( &logFont, dc );
 430|    oldFont = dc->SelectObject( &font2 );
 431|
 432|    m_W = 0;  m_10H = 0;
 433|    for ( i = 1; i < 100; i++ ) {  /* 100行目以降の幅と高さは調査しない */
 434|      char  s[Text_Box_nByteInLine+4];
 435|      int   w,h;
 436|
 437|      if ( StrX_cpy1Line( s, sizeof(s), m_Text, i ) == NULL )  break;
 438|      if ( i == 1 && s[0] == '\0' )  strcpy( s, "X" );
 439|      size = dc->GetOutputTextExtent( s );  /* 現在選択しているフォントに影響する */
 440|      w = size.cx / 10;  if ( w > m_W )  m_W = w;
 441|      h = size.cy;  // if ( p->bPrint )  h = h * 100 / p->zoom;
 442|      if ( h > m_10H )  m_10H = h;
 443|      if ( i == 1 ) {
 444|        dc->GetOutputTextMetrics( &tx );
 445|        if ( p->bPrint ) {
 446|          m_Top = m_Y + (tx.tmDescent - h) * 10 / p->zoom;
 447|          m_10H1 = h * 100 / p->zoom;
 448|        }
 449|        else {
 450|          m_Top = m_Y + (tx.tmDescent - h ) / 10;
 451|          m_10H1 = h;
 452|        }
 453|      }
 454|    }
 455|    if ( i == 100 )  i = StrX_getNLine( m_Text );
 456|    if ( p->bPrint )  m_10H = m_10H + ( (i - 2) * m_BetweenOfLine * 10 ) * p->zoom / 100;
 457|    else  m_10H = m_10H + ( (i - 2) * m_BetweenOfLine * 10 );
 458|    nTextLine = i - 1;
 459|    dc->GetOutputTextMetrics( &tx );
 460|    m_10Descent = tx.tmDescent;
 461|    dc->SelectObject( oldFont );
 462|
 463|    if ( p->bPrint ) {
 464|      m_W = m_W * 100 / p->zoom;
 465|      m_10H = m_10H * 100 / p->zoom;
 466|      m_10Descent = m_10Descent * 100 / p->zoom;
 467|    }
 468|  }
 469|
 470|
 471|  /* フォントの属性に応じて Text_Box の属性の再設定を行う */
 472|  /* m_BoxMarginX, m_BoxMarginY を、Rect_Ex の左上座標からマージンに変える */
 473|  if ( m_BoxShape < 0 ) {
 474|    m_BoxShape = - m_BoxShape;
 475|    if ( m_bTategaki ) {
 476|      switch ( m_BasePos ) {
 477|        case  Text_Box_LeftAlign:
 478|          m_BoxMarginY = m_Y - m_BoxMarginY;
 479|          m_DiffW = m_DiffW - 1 - m_W - 2 * m_BoxMarginY;
 480|          break;
 481|        case  Text_Box_CenterAlign:
 482|          m_BoxMarginY = m_Y - (m_W + 1) / 2 - m_BoxMarginY;
 483|          m_DiffW = 0;
 484|          break;
 485|        case  Text_Box_RightAlign:
 486|          m_BoxMarginY = m_Y - m_W - m_BoxMarginY;
 487|          m_DiffW = m_W + 1 + 2 * m_BoxMarginY - m_DiffW;
 488|          m_BoxMarginY -= m_DiffW;
 489|          break;
 490|      }
 491|      m_BoxMarginX =  m_CenterX - (m_10H1 + m_10Descent+1)/20 - (nTextLine-1) * m_BetweenOfLine - m_BoxMarginX;
 492|      { int i = m_BoxMarginX;  m_BoxMarginX = m_BoxMarginY;  m_BoxMarginY = i; }
 493|    }
 494|    else {
 495|      switch ( m_BasePos ) {
 496|        case  Text_Box_LeftAlign:
 497|          m_BoxMarginX = m_CenterX - m_BoxMarginX;
 498|          m_DiffW = m_DiffW - m_W - 2 * m_BoxMarginX;
 499|          break;
 500|        case  Text_Box_CenterAlign:
 501|          m_BoxMarginX = m_CenterX - m_W / 2 - m_BoxMarginX;
 502|          m_DiffW = 0;
 503|          break;
 504|        case  Text_Box_RightAlign:
 505|          m_BoxMarginX = m_CenterX - m_W - m_BoxMarginX;
 506|          m_DiffW = m_W + 2 * m_BoxMarginX - m_DiffW;
 507|          m_BoxMarginX -= m_DiffW;
 508|          break;
 509|      }
 510|      m_BoxMarginY =  m_Y + (nTextLine - 1) * m_BetweenOfLine +
 511|        (m_10Descent - m_10H) / 10 - m_BoxMarginY;
 512|    }
 513|  }
 514|
 515|
 516|  /* 枠を表示する */
 517|  {
 518|    CPen     pen( PS_SOLID, m_BorderWidth * zoom / 100,
 519|      p->bWhiteToBGColor && m_BorderColor == 0x000000 ?
 520|      GetSysColor( COLOR_WINDOWTEXT ) : m_BorderColor );
 521|    CPen     nullPen( PS_NULL, (int)0, (int)0 );
 522|    CBrush   brush( p->bWhiteToBGColor && m_FillColor == 0xFFFFFF ?
 523|      GetSysColor( COLOR_WINDOW ) : m_FillColor );
 524|    CBrush   nullBrush;
 525|    CBrush   transBrush( HS_VERTICAL, p->bWhiteToBGColor && m_FillColor == 0xFFFFFF ?
 526|      GetSysColor( COLOR_WINDOW ) : m_FillColor );
 527|    CPen*    oldPen;
 528|    CBrush*  oldBrush;
 529|
 530|    nullBrush.CreateStockObject( NULL_BRUSH );
 531|
 532|    oldPen = dc->SelectObject( m_BorderWidth == 0 ? &nullPen : &pen );
 533|    if ( m_FillNTrans == 100 )
 534|      oldBrush = dc->SelectObject( &brush );
 535|    else if ( m_FillNTrans == 0 )
 536|       oldBrush = dc->SelectObject( &nullBrush );
 537|    else {
 538|      dc->SetBkMode( TRANSPARENT );
 539|      oldBrush = dc->SelectObject( &transBrush );
 540|    }
 541|
 542|    GetBox( &box );
 543|
 544|    switch ( m_BoxShape ) {
 545|     case  Text_Box_RectShape:
 546|      if ( m_RotateDegree == 0 ) {
 547|        dc->Rectangle( box.left * zoom / 100 - p->x0, box.top * zoom / 100 - p->y0,
 548|          box.right * zoom / 100 + 1 - p->x0, box.bottom * zoom / 100 + 1 - p->y0 );
 549|      }
 550|      else {
 551|        POINT    pts[4];
 552|        int  i;
 553|
 554|        pts[0].x = box.left;   pts[0].y = box.top;
 555|        pts[1].x = box.right;  pts[1].y = box.top;
 556|        pts[2].x = box.right;  pts[2].y = box.bottom;
 557|        pts[3].x = box.left;   pts[3].y = box.bottom;
 558|        for ( i = 0; i < 4; i++ ) {
 559|          TwoD_XY_init( &xy, pts[i].x, pts[i].y );
 560|          TwoD_XY_rot( &xy, &center, m_RotateDegree * (2 * 3.141592) / 360 );
 561|          pts[i].x = (long)(xy.x + 0.5) * zoom / 100 - p->x0;
 562|          pts[i].y = (long)(xy.y + 0.5) * zoom / 100 - p->y0;
 563|        }
 564|        dc->Polygon( pts, 4 );
 565|      }
 566|      break;
 567|
 568|     case  Text_Box_RoundRectShape:
 569|      if ( m_RotateDegree == 0 ) {
 570|        dc->RoundRect( box.left * zoom / 100 - p->x0, box.top * zoom / 100 - p->y0,
 571|          box.right * zoom / 100 + 1 - p->x0, box.bottom * zoom / 100 + 1 - p->y0,
 572|          20 * zoom / 100, 20 * zoom / 100 );
 573|      }
 574|      else {
 575|        POINT    pts[8];
 576|        int  i;
 577|
 578|        pts[0].x = box.left;       pts[0].y = box.top + 6;
 579|        pts[1].x = box.left + 6;   pts[1].y = box.top;
 580|        pts[2].x = box.right - 6;  pts[2].y = box.top;
 581|        pts[3].x = box.right;      pts[3].y = box.top + 6;
 582|        pts[4].x = box.right;      pts[4].y = box.bottom - 6;
 583|        pts[5].x = box.right - 6;  pts[5].y = box.bottom;
 584|        pts[6].x = box.left + 6;   pts[6].y = box.bottom;
 585|        pts[7].x = box.left;       pts[7].y = box.bottom - 6;
 586|        for ( i = 0; i < 8; i++ ) {
 587|          TwoD_XY_init( &xy, pts[i].x, pts[i].y );
 588|          TwoD_XY_rot( &xy, &center, m_RotateDegree * (2 * 3.141592) / 360 );
 589|          pts[i].x = (long)(xy.x + 0.5) * zoom / 100 - p->x0;
 590|          pts[i].y = (long)(xy.y + 0.5) * zoom / 100 - p->y0;
 591|        }
 592|        dc->Polygon( pts, 8 );
 593|      }
 594|      break;
 595|
 596|     case  Text_Box_CircleShape:
 597|      dc->Ellipse( box.left * zoom / 100 - p->x0, box.top * zoom / 100 - p->y0,
 598|        box.right * zoom / 100 + 1 - p->x0, box.bottom * zoom / 100 + 1 - p->y0 );
 599|      break;
 600|
 601|     case  Text_Box_DiamondShape: {
 602|      POINT  pts[4];
 603|      int  hasuuX = ( box.left + box.right ) % 2;
 604|      int  hasuuY = ( box.top + box.bottom ) % 2;
 605|      int  i;
 606|
 607|      pts[0].x = ( box.left + box.right ) / 2;
 608|      pts[0].y = box.top;
 609|      pts[1].x = box.right - hasuuX;
 610|      pts[1].y = ( box.top + box.bottom ) / 2;
 611|      pts[2].x = ( box.left + box.right ) / 2;
 612|      pts[2].y = box.bottom + hasuuY;
 613|      pts[3].x = box.left;
 614|      pts[3].y = ( box.top + box.bottom ) / 2;
 615|      for ( i = 0; i < 4; i++ ) {
 616|        TwoD_XY_init( &xy, pts[i].x, pts[i].y );
 617|        TwoD_XY_rot( &xy, &center, m_RotateDegree * (2 * 3.141592) / 360 );
 618|        pts[i].x = (long)(xy.x + 0.5) * zoom / 100 - p->x0;
 619|        pts[i].y = (long)(xy.y + 0.5) * zoom / 100 - p->y0;
 620|      }
 621|      dc->Polygon( pts, 4 );
 622|      break;
 623|     }
 624|     case  Text_Box_Parallelogram: {
 625|      POINT  pts[4];
 626|      int  i;
 627|      int  slide = ( box.bottom - box.top ) / 4;
 628|
 629|      pts[0].x = box.left + slide;
 630|      pts[0].y = box.top;
 631|      pts[1].x = box.right + slide;
 632|      pts[1].y = box.top;
 633|      pts[2].x = box.right - slide;
 634|      pts[2].y = box.bottom;
 635|      pts[3].x = box.left - slide;
 636|      pts[3].y = box.bottom;
 637|      for ( i = 0; i < 4; i++ ) {
 638|        TwoD_XY_init( &xy, pts[i].x, pts[i].y );
 639|        TwoD_XY_rot( &xy, &center, m_RotateDegree * (2 * 3.141592) / 360 );
 640|        pts[i].x = (long)(xy.x + 0.5) * zoom / 100 - p->x0;
 641|        pts[i].y = (long)(xy.y + 0.5) * zoom / 100 - p->y0;
 642|      }
 643|      dc->Polygon( pts, 4 );
 644|      break;
 645|     }
 646|    }
 647|
 648|    dc->SelectObject( oldBrush );
 649|    dc->SelectObject( oldPen );
 650|  }
 651|
 652|
 653|  {
 654|    /* フォントを設定する */
 655|    CFont   font;
 656|    CFont   font2;
 657|    CFont*  oldFont;
 658|    int  size = m_Size* 10 * ( p->bPrint ? 100 : zoom ) / 100;  if ( size == 0 )  size = 1;
 659|
 660|    font.CreatePointFont( size, (m_bTategaki ? CString('@')+m_Font : m_Font), dc );
 661|    font.GetLogFont( &logFont );
 662|    logFont.lfWidth = 0;
 663|    logFont.lfHeight = size;
 664|    logFont.lfWeight = m_bBold ? FW_BOLD : FW_NORMAL;
 665|    logFont.lfItalic = m_bItalic;
 666|    logFont.lfEscapement = - m_RotateDegree * 10 + (m_bTategaki ? 2700 :0);
 667|    font2.CreatePointFontIndirect( &logFont, dc );
 668|    oldFont = dc->SelectObject( &font2 );
 669|
 670|    if ( m_IdLabel == "pagenum" ) {
 671|      char  s[12];
 672|
 673|      sprintf( s, "%d", p->iPage );
 674|      m_Text = s;
 675|    }
 676|
 677|
 678|    /* 文字列を表示する */
 679|    {
 680|      COLORREF  textNormalColor = p->bWhiteToBGColor && m_Color == 0x000000 ?
 681|        GetSysColor( COLOR_WINDOWTEXT ) : m_Color;
 682|      COLORREF  textHighColor = GetSysColor( COLOR_HIGHLIGHTTEXT );
 683|      int  hx1, hy1, hx2, hy2;  /* ハイライト表示の区間(カラムと行)*/
 684|
 685|      if ( m_bTategaki ) {
 686|        TwoD_XY_init( &xy, m_10H1 / 20 - m_10Descent / 10, -2 );
 687|        TwoD_XY_rot( &xy, &center0, m_RotateDegree * (2 * 3.141592) / 360 );
 688|
 689|        textRect.left = (m_CenterX - (long)(xy.x + 0.5)) * zoom / 100 - p->x0;
 690|        textRect.top = (m_Y - (long)(xy.y + 0.5)) * zoom / 100 - p->y0;
 691|      }
 692|      else {
 693|        textRect.left = m_CenterX * zoom / 100 + 1 - p->x0;
 694|        textRect.top = m_Y * zoom / 100 - p->y0;
 695|      }
 696|      textRect.right = textRect.left;
 697|      textRect.bottom = textRect.top;
 698|
 699|      dc->SetTextColor( textNormalColor );
 700|      dc->SetBkMode( TRANSPARENT );
 701|      dc->SetBkColor( GetSysColor( COLOR_HIGHLIGHT ) );
 702|      GetTXYByIndex( m_CaretStart < m_CaretEnd ? m_CaretStart : m_CaretEnd, &hx1, &hy1 );
 703|      GetTXYByIndex( m_CaretStart < m_CaretEnd ? m_CaretEnd : m_CaretStart, &hx2, &hy2 );
 704|
 705|      switch ( m_BasePos ) {
 706|        case  Text_Box_LeftAlign:
 707|          dc->SetTextAlign( TA_BASELINE | TA_LEFT );
 708|          break;
 709|        case  Text_Box_CenterAlign:
 710|          dc->SetTextAlign( TA_BASELINE | TA_CENTER );
 711|          break;
 712|        case  Text_Box_RightAlign:
 713|          dc->SetTextAlign( TA_BASELINE | TA_RIGHT );
 714|          break;
 715|      }
 716|      dc->SetTextCharacterExtra( 0 );
 717|      for ( i = 1; i <= nTextLine; i++ ) {
 718|        RECT  rc;
 719|        char  s[Text_Box_nByteInLine+4];
 720|
 721|        if ( m_RotateDegree == 0 ) {
 722|          rc.left = textRect.left;
 723|          rc.top = textRect.top;
 724|          if ( m_bTategaki ) {
 725|            rc.left -= ( (i - 1) * m_BetweenOfLine ) * zoom / 100;
 726|            if ( i > 100 )  break;
 727|          }
 728|          else {
 729|            rc.top += ( (i - 1) * m_BetweenOfLine ) * zoom / 100;
 730|            if ( rc.top + m_BetweenOfLine < p->clip_top )
 731|              continue;
 732|            if ( rc.top - m_BetweenOfLine > p->clip_bottom )
 733|              break;
 734|          }
 735|        }
 736|        else {
 737|          if ( m_bTategaki )  TwoD_XY_init( &xy, - (i - 1) * m_BetweenOfLine, 0 );
 738|          else  TwoD_XY_init( &xy, 0, (i - 1) * m_BetweenOfLine );
 739|          TwoD_XY_rot( &xy, &center0, m_RotateDegree * (2 * 3.141592) / 360 );
 740|          rc.left = (textRect.left + (long)(xy.x + 0.5)) * zoom / 100 - p->x0;
 741|          rc.top = (textRect.top + (long)(xy.y + 0.5)) * zoom / 100 - p->y0;
 742|          if ( i > 100 )  break;
 743|        }
 744|        rc.right = rc.left;
 745|        rc.bottom = rc.top;
 746|
 747|        if ( StrX_cpy1Line( s, sizeof(s), m_Text, i ) == NULL )  break;
 748|
 749|        #if  1  /* Highlight */
 750|        {
 751|          char  c;
 752|          int   gx, gy, left;
 753|          DWORD  flag = DT_LEFT | DT_SINGLELINE | DT_TOP |
 754|                        DT_NOCLIP | DT_NOPREFIX | DT_EXTERNALLEADING;
 755|
 756|          if ( hy1 == i - 1 ) {
 757|            if ( hx1 > 0 ) {
 758|              /* ハイライトより左を書く */
 759|              c = s[hx1];  s[hx1] = '\0';
 760|              dc->DrawText( s, -1, &rc, flag );
 761|              s[hx1] = c;
 762|            }
 763|
 764|            dc->SetTextColor( textHighColor );
 765|            dc->SetBkMode( OPAQUE );
 766|
 767|            if ( hy2 == hy1 ) {
 768|              /* 行内のハイライトを書く */
 769|              left = rc.left;
 770|              GetGXYByTXY( dc, hx1, hy1, &gx, &gy );
 771|              rc.left = left + gx;
 772|              rc.right = rc.left;
 773|              c = s[hx2];  s[hx2] = '\0';
 774|              dc->DrawText( s + hx1, -1, &rc, flag );
 775|              s[hx2] = c;
 776|
 777|              /* ハイライトより右を書く */
 778|              dc->SetTextColor( textNormalColor );
 779|              dc->SetBkMode( TRANSPARENT );
 780|              GetGXYByTXY( dc, hx2, hy2, &gx, &gy );
 781|              rc.left = left + gx;
 782|              rc.right = rc.left;
 783|              dc->DrawText( s + hx2, -1, &rc, flag );
 784|            }
 785|            else {
 786|              /* 行末までハイライトを書く */
 787|              GetGXYByTXY( dc, hx1, hy1, &gx, &gy );
 788|              rc.left = left + gx;
 789|              rc.right = rc.left;
 790|              dc->DrawText( s + hx1, -1, &rc, flag );
 791|            }
 792|          }
 793|          else if ( hy2 == i - 1 ) {
 794|            /* 行頭からハイライトを書く */
 795|            c = s[hx2];  s[hx2] = '\0';
 796|            dc->DrawText( s, -1, &rc, flag );
 797|            s[hx2] = c;
 798|
 799|            /* ハイライトより右を書く */
 800|            dc->SetTextColor( textNormalColor );
 801|            dc->SetBkMode( TRANSPARENT );
 802|            GetGXYByTXY( dc, hx2, hy2, &gx, &gy );
 803|            rc.left = left + gx;
 804|            rc.right = rc.left;
 805|            dc->DrawText( s + hx2, -1, &rc, flag );
 806|          }
 807|          else {
 808|            /* ノーマルまたはハイライトで1行全体を書く */
 809|            dc->DrawText( s, -1, &rc, flag );
 810|          }
 811|        }
 812|        #else
 813|          dc->DrawText( s, -1, &rc, DT_LEFT | DT_SINGLELINE | DT_TOP |
 814|            DT_NOCLIP | DT_NOPREFIX | DT_EXTERNALLEADING );
 815|        #endif
 816|      }
 817|      dc->SelectObject( oldFont );
 818|    }
 819|  }
 820|
 821|  if ( m_bHold && p->bDrawHandle )
 822|    DrawHandles( dc, p, ~GetSysColor( COLOR_HIGHLIGHT ) & 0xFFFFFF, false );
 823|
 824|  ERRORS_FUNC_END_CPP( Text_Box_Draw );
 825|}
 826|
 827|
 828| 
 829|/***********************************************************************
 830|  2-13. <<< [Text_Box::DrawHandles] CadPrim::DrawJamdles の実装部 >>> 
 831|【引数】
 832|  ・CDC*    dc;      デバイスコンテキスト
 833|  ・int     color;   ハンドルの色
 834|************************************************************************/
 835|void  Text_Box::DrawHandles( CDC* dc, CadPrim_DrawParam* p, COLORREF color,
 836|  bool bDrawFrame )
 837|{
 838|  CPen     pen( PS_SOLID, 1, color ^ 0xFFFFFF );
 839|  CBrush   brush( color );
 840|  CPen*    oldPen;
 841|  CBrush*  oldBrush;
 842|  RECT  box;
 843|  int   x1, x2, x3, y1, y2, y3, x, y;
 844|
 845|  oldPen = dc->SelectObject( &pen );
 846|  oldBrush = dc->SelectObject( &brush );
 847|
 848|  GetBox( &box );
 849|  x1 = box.left;
 850|  x3 = box.right;
 851|  y1 = box.top;
 852|  y3 = box.bottom;
 853|  x2 = (x1 + x3) / 2;
 854|  y2 = (y1 + y3) / 2;
 855|
 856|  if ( m_RotateDegree == 0 && m_BoxShape != Text_Box_Parallelogram ) {
 857|    x1 = x1 * p->zoom / 100 - p->x0;  y1 = y1 * p->zoom / 100 - p->y0;
 858|    x2 = x2 * p->zoom / 100 - p->x0;  y2 = y2 * p->zoom / 100 - p->y0;
 859|    x3 = x3 * p->zoom / 100 - p->x0;  y3 = y3 * p->zoom / 100 - p->y0;
 860|
 861|    dc->Rectangle( x1 - 3,  y1 - 3,  x1 + 3,  y1 + 3 );
 862|    dc->Rectangle( x2 - 3,  y1 - 3,  x2 + 3,  y1 + 3 );
 863|    dc->Rectangle( x3 - 3,  y1 - 3,  x3 + 3,  y1 + 3 );
 864|    dc->Rectangle( x1 - 3,  y2 - 3,  x1 + 3,  y2 + 3 );
 865|    dc->Rectangle( x3 - 3,  y2 - 3,  x3 + 3,  y2 + 3 );
 866|    dc->Rectangle( x1 - 3,  y3 - 3,  x1 + 3,  y3 + 3 );
 867|    dc->Rectangle( x2 - 3,  y3 - 3,  x2 + 3,  y3 + 3 );
 868|    dc->Rectangle( x3 - 3,  y3 - 3,  x3 + 3,  y3 + 3 );
 869|  }
 870|  else {
 871|    TwoD_XY  xy, center;
 872|    double   angle = m_RotateDegree * (2 * 3.141592) / 360;
 873|    int      slide;
 874|    CPen     dashPen( PS_DOT, 1, color );
 875|    TwoD_XY  corner[4];
 876|
 877|    if ( m_BoxShape == Text_Box_Parallelogram )  slide = (y3 - y1) / 4;
 878|    else  slide = 0;
 879|
 880|    TwoD_XY_init( &center, m_CenterX, m_Y );
 881|
 882|    TwoD_XY_init( &xy, x1 + slide, y1 );  TwoD_XY_rot( &xy, &center, angle );
 883|    x = (long)xy.x * p->zoom / 100 - p->x0;  y = (long)xy.y * p->zoom / 100 - p->y0;
 884|    dc->Rectangle( x - 3,  y - 3,  x + 3,  y + 3 );
 885|    corner[0].x = x;  corner[0].y = y;
 886|
 887|    TwoD_XY_init( &xy, x2 + slide, y1 );  TwoD_XY_rot( &xy, &center, angle );
 888|    x = (long)xy.x * p->zoom / 100 - p->x0;  y = (long)xy.y * p->zoom / 100 - p->y0;
 889|    dc->Rectangle( x - 3,  y - 3,  x + 3,  y + 3 );
 890|
 891|    TwoD_XY_init( &xy, x3 + slide, y1 );  TwoD_XY_rot( &xy, &center, angle );
 892|    x = (long)xy.x * p->zoom / 100 - p->x0;  y = (long)xy.y * p->zoom / 100 - p->y0;
 893|    dc->Rectangle( x - 3,  y - 3,  x + 3,  y + 3 );
 894|    corner[1].x = x;  corner[1].y = y;
 895|
 896|    TwoD_XY_init( &xy, x1, y2 );  TwoD_XY_rot( &xy, &center, angle );
 897|    x = (long)xy.x * p->zoom / 100 - p->x0;  y = (long)xy.y * p->zoom / 100 - p->y0;
 898|    dc->Rectangle( x - 3,  y - 3,  x + 3,  y + 3 );
 899|
 900|    TwoD_XY_init( &xy, x3, y2 );  TwoD_XY_rot( &xy, &center, angle );
 901|    x = (long)xy.x * p->zoom / 100 - p->x0;  y = (long)xy.y * p->zoom / 100 - p->y0;
 902|    dc->Rectangle( x - 3,  y - 3,  x + 3,  y + 3 );
 903|
 904|    TwoD_XY_init( &xy, x1 - slide, y3 );  TwoD_XY_rot( &xy, &center, angle );
 905|    x = (long)xy.x * p->zoom / 100 - p->x0;  y = (long)xy.y * p->zoom / 100 - p->y0;
 906|    dc->Rectangle( x - 3,  y - 3,  x + 3,  y + 3 );
 907|    corner[2].x = x;  corner[2].y = y;
 908|
 909|    TwoD_XY_init( &xy, x2 - slide, y3 );  TwoD_XY_rot( &xy, &center, angle );
 910|    x = (long)xy.x * p->zoom / 100 - p->x0;  y = (long)xy.y * p->zoom / 100 - p->y0;
 911|    dc->Rectangle( x - 3,  y - 3,  x + 3,  y + 3 );
 912|
 913|    TwoD_XY_init( &xy, x3 - slide, y3 );  TwoD_XY_rot( &xy, &center, angle );
 914|    x = (long)xy.x * p->zoom / 100 - p->x0;  y = (long)xy.y * p->zoom / 100 - p->y0;
 915|    dc->Rectangle( x - 3,  y - 3,  x + 3,  y + 3 );
 916|    corner[3].x = x;  corner[3].y = y;
 917|
 918|    if ( bDrawFrame && m_RotateDegree != 0 &&
 919|         ( m_BoxShape == Text_Box_RoundRectShape || m_BoxShape == Text_Box_CircleShape ) ) {
 920|      dc->SelectObject( dashPen );
 921|      dc->MoveTo( (int)corner[0].x, (int)corner[0].y );
 922|      dc->LineTo( (int)corner[1].x, (int)corner[1].y );
 923|      dc->LineTo( (int)corner[3].x, (int)corner[3].y );
 924|      dc->LineTo( (int)corner[2].x, (int)corner[2].y );
 925|      dc->LineTo( (int)corner[0].x, (int)corner[0].y );
 926|    }
 927|  }
 928|
 929|  dc->SelectObject( oldBrush );
 930|  dc->SelectObject( oldPen );
 931|}
 932|
 933| 
 934|/***********************************************************************
 935|  2-14. <<< [Text_Box::copy] CadPrim::copy の実装部 >>> 
 936|************************************************************************/
 937|void  Text_Box::copy( CadPrim* a, ListX* prims )
 938|{
 939|  CadPrim_Link*  link1;
 940|  CadPrim_Link*  link2;
 941|  Text_Box*  t = (Text_Box*)a;
 942|
 943|  m_id = t->m_id;
 944|  m_IdLabel = "";
 945|  m_URL = t->m_URL;
 946|  m_Target = t->m_Target;
 947|  m_Text = t->m_Text;
 948|  m_CenterX = t->m_CenterX;
 949|  m_Y = t->m_Y;
 950|  m_DiffW = t->m_DiffW;
 951|  m_W = t->m_W;
 952|  m_10H = t->m_10H;
 953|  m_10Descent = t->m_10Descent;
 954|  m_BetweenOfLine = t->m_BetweenOfLine;
 955|  m_RotateDegree = t->m_RotateDegree;
 956|  m_Color = t->m_Color;
 957|  m_Font = t->m_Font;
 958|  m_Size = t->m_Size;
 959|  m_bBold = t->m_bBold;
 960|  m_bItalic = t->m_bItalic;
 961|  m_BasePos = t->m_BasePos;
 962|  m_bTategaki = t->m_bTategaki;
 963|
 964|  m_BoxShape = t->m_BoxShape;
 965|  m_BoxMarginX = t->m_BoxMarginX;
 966|  m_BoxMarginY = t->m_BoxMarginY;
 967|  m_BorderWidth = t->m_BorderWidth;
 968|  m_BorderColor = t->m_BorderColor;
 969|  m_FillColor = t->m_FillColor;
 970|  m_FillNTrans = t->m_FillNTrans;
 971|
 972|  ListX_toEmptyDelete( &m_Links, CadPrim_Link, NULL );
 973|  for ( ListX_forEach( &t->m_Links, &link2, CadPrim_Link ) ) {
 974|    link1 = ListX_addLastMalloc( &m_Links, CadPrim_Link );
 975|    CadPrim_Link_copy( link1, link2 );
 976|    link1->prim = Undo_Uty_getPrimPtr( prims, link1->prim_id );
 977|  }
 978|  m_Controler_id = t->m_Controler_id;
 979|  m_Controler = Undo_Uty_getPrimPtr( prims, m_Controler_id );
 980|}
 981|
 982|/***********************************************************************
 983|  2-15. <<< [Text_Box::copyStyle] CadPrim::copyStyle の実装部 >>>
 984|************************************************************************/
 985|void  Text_Box::copyStyle( CadPrim* a, ListX* prims )
 986|{
 987|  Text_Box*  t = (Text_Box*)a;
 988|
 989|  m_BetweenOfLine = t->m_BetweenOfLine;
 990|  m_Color = t->m_Color;
 991|  m_Font = t->m_Font;
 992|  m_Size = t->m_Size;
 993|  m_bBold = t->m_bBold;
 994|  m_bItalic = t->m_bItalic;
 995|
 996|  m_BoxMarginX = t->m_BoxMarginX;
 997|  m_BoxMarginY = t->m_BoxMarginY;
 998|  m_BorderWidth = t->m_BorderWidth;
 999|  m_BorderColor = t->m_BorderColor;
1000|  m_FillColor = t->m_FillColor;
1001|  m_FillNTrans = t->m_FillNTrans;
1002|}
1003|
1004|/***********************************************************************
1005|  2-16. <<< [Text_Box::isEqual] CadPrim::isEqual の実装部 >>>
1006|************************************************************************/
1007|bool  Text_Box::isEqual( CadPrim* a )
1008|{
1009|  Text_Box*  t = (Text_Box*)a;
1010|  CadPrim_Link*  link;
1011|  CadPrim_Link*  link2;
1012|
1013|  if ( a->GetTypeID() != Text_Box_TypeID )  return  false;
1014|
1015|  link2 = ListX_getFirst( &t->m_Links, CadPrim_Link );
1016|  for ( ListX_forEach( &m_Links, &link, CadPrim_Link ) ) {
1017|    if ( link2 == NULL )  return false;
1018|    if ( link->prim_id != link2->prim_id ||
1019|         link->iHandle != link2->iHandle ||
1020|         link->x != link2->x || link->y != link2->y )
1021|      return false;
1022|
1023|    link2 = ListX_Elem_getNextT( link2, CadPrim_Link );
1024|  }
1025|  if ( link2 != NULL )  return  false;
1026|
1027|
1028|  return (
1029|    m_Text == t->m_Text &&
1030|    m_IdLabel == t->m_IdLabel &&
1031|    m_URL == t->m_URL &&
1032|    m_Target == t->m_Target &&
1033|    m_CenterX == t->m_CenterX &&
1034|    m_Y == t->m_Y &&
1035|    m_DiffW == t->m_DiffW &&
1036|    m_BetweenOfLine == t->m_BetweenOfLine &&
1037|    m_RotateDegree == t->m_RotateDegree &&
1038|    m_Color == t->m_Color &&
1039|    m_Font == t->m_Font &&
1040|    m_Size == t->m_Size &&
1041|    m_bBold == t->m_bBold &&
1042|    m_bItalic == t->m_bItalic &&
1043|    m_BasePos == t->m_BasePos &&
1044|    m_bTategaki == t->m_bTategaki &&
1045|    m_BoxShape == t->m_BoxShape &&
1046|    m_BoxMarginX == t->m_BoxMarginX &&
1047|    m_BoxMarginY == t->m_BoxMarginY &&
1048|    m_BorderWidth == t->m_BorderWidth &&
1049|    m_BorderColor == t->m_BorderColor &&
1050|    m_FillColor == t->m_FillColor &&
1051|    m_FillNTrans == t->m_FillNTrans &&
1052|
1053|    m_Controler_id == t->m_Controler_id );
1054|}
1055|
1056|
1057|/***********************************************************************
1058|  2-17. <<< [Text_Box::GetNewCopy] CadPrim::GetNewCopy の実装部 >>>
1059|************************************************************************/
1060|CadPrim*  Text_Box::GetNewCopy( ListX* prims )
1061|{
1062|  Text_Box*  r = new Text_Box;
1063|
1064|  r->copy( this, prims );
1065|  return  r;
1066|}
1067|
1068|
1069|/***********************************************************************
1070|  2-18. <<< [Text_Box::GetSerializedSize] CadPrim::GetSerializedSize の実装部 >>>
1071|************************************************************************/
1072|int  Text_Box::GetSerializedSize()
1073|{
1074|  return  ( sizeof(Text_Box) + m_IdLabel.GetLength() + 1 + m_Text.GetLength() + 1 +
1075|    m_URL.GetLength() + 1 + m_Target.GetLength() + 1 + m_Font.GetLength() + 1 +
1076|    sizeof(CadPrim_Link) * ListX_getN( &m_Links, CadPrim_Link )
1077|    + 3 ) & ~3;
1078|}
1079|
1080|
1081|/***********************************************************************
1082|  2-19. <<< [Text_Box::CopyToSerial] CadPrim::CopyToSerial の実装部 >>>
1083|************************************************************************/
1084|void  Text_Box::CopyToSerial( void* a )
1085|{
1086|  Text_Box*  t = (Text_Box*)a;
1087|  char*  s = (char*)a + sizeof(Text_Box);
1088|  CadPrim_Link*  link;
1089|
1090|  t->m_id = m_id;
1091|  // t->m_IdLabel = m_IdLabel;
1092|  // t->m_Text = m_Text;
1093|  // t->m_URL = m_URL;
1094|  // t->m_Target = m_Target;
1095|  t->m_CenterX = m_CenterX;
1096|  t->m_Y = m_Y;
1097|  t->m_DiffW = m_DiffW;
1098|  t->m_W = m_W;
1099|  t->m_10H = m_10H;
1100|  t->m_10Descent = m_10Descent;
1101|  t->m_BetweenOfLine = m_BetweenOfLine;
1102|  t->m_RotateDegree = m_RotateDegree;
1103|  t->m_Color = m_Color;
1104|  // t->m_Font = m_Font;
1105|  t->m_Size = m_Size;
1106|  t->m_bBold = m_bBold;
1107|  t->m_bItalic = m_bItalic;
1108|  t->m_BasePos = m_BasePos;
1109|  t->m_bTategaki = m_bTategaki;
1110|
1111|  t->m_BoxShape = m_BoxShape;
1112|  t->m_BoxMarginX = m_BoxMarginX;
1113|  t->m_BoxMarginY = m_BoxMarginY;
1114|  t->m_BorderWidth = m_BorderWidth;
1115|  t->m_BorderColor = m_BorderColor;
1116|  t->m_FillColor = m_FillColor;
1117|  t->m_FillNTrans = m_FillNTrans;
1118|
1119|  t->m_Links.first = (void*)ListX_getN( &m_Links, CadPrim_Link );
1120|  t->m_Controler_id = m_Controler_id;
1121|
1122|  strcpy( s, m_Text );
1123|  s = strchr( s, '\0' ) + 1;
1124|  strcpy( s, m_Font );
1125|  s = strchr( s, '\0' ) + 1;
1126|  strcpy( s, m_IdLabel );
1127|  s = strchr( s, '\0' ) + 1;
1128|  strcpy( s, m_URL );
1129|  s = strchr( s, '\0' ) + 1;
1130|  strcpy( s, m_Target );
1131|  s = strchr( s, '\0' ) + 1;
1132|
1133|  for ( ListX_forEach( &m_Links, &link, CadPrim_Link ) ) {
1134|    CadPrim_Link_copy( (CadPrim_Link*)s, link );
1135|    s += sizeof(CadPrim_Link);
1136|  }
1137|}
1138|
1139|
1140|/***********************************************************************
1141|  2-20. <<< [Text_Box::CopyFromSerial] CadPrim::CopyFromSerial の実装部 >>>
1142|************************************************************************/
1143|void  Text_Box::CopyFromSerial( void* a )
1144|{
1145|  Text_Box*  t = (Text_Box*)a;
1146|  char*  s = (char*)a + sizeof(Text_Box);
1147|  CadPrim_Link*  link;
1148|  int  i, n;
1149|
1150|  m_id = t->m_id;
1151|  // m_IdLabel = t->m_IdLabel;
1152|  // m_URL = t->m_URL;
1153|  // m_Target = t->m_Target;
1154|  // m_Text = t->m_Text;
1155|  m_CenterX = t->m_CenterX;
1156|  m_Y = t->m_Y;
1157|  m_DiffW = t->m_DiffW;
1158|  m_W = t->m_W;
1159|  m_10H = t->m_10H;
1160|  m_10Descent = t->m_10Descent;
1161|  m_BetweenOfLine = t->m_BetweenOfLine;
1162|  m_RotateDegree = t->m_RotateDegree;
1163|  m_Color = t->m_Color;
1164|  // m_Font = t->m_Font;
1165|  m_Size = t->m_Size;
1166|  m_bBold = t->m_bBold;
1167|  m_bItalic = t->m_bItalic;
1168|  m_BasePos = t->m_BasePos;
1169|  m_bTategaki = t->m_bTategaki;
1170|
1171|  m_BoxShape = t->m_BoxShape;
1172|  m_BoxMarginX = t->m_BoxMarginX;
1173|  m_BoxMarginY = t->m_BoxMarginY;
1174|  m_BorderWidth = t->m_BorderWidth;
1175|  m_BorderColor = t->m_BorderColor;
1176|  m_FillColor = t->m_FillColor;
1177|  m_FillNTrans = t->m_FillNTrans;
1178|
1179|  // m_URL = t->m_URL;
1180|
1181|  n = (int)t->m_Links.first;
1182|  m_Controler_id = t->m_Controler_id;
1183|
1184|  m_Text = s;
1185|  s = strchr( s, '\0' ) + 1;
1186|  m_Font = s;
1187|  s = strchr( s, '\0' ) + 1;
1188|  m_IdLabel = s;
1189|  s = strchr( s, '\0' ) + 1;
1190|  m_URL = s;
1191|  s = strchr( s, '\0' ) + 1;
1192|  m_Target = s;
1193|  s = strchr( s, '\0' ) + 1;
1194|
1195|  ListX_init( &m_Links );
1196|  for ( i = 0; i < n; i++ ) {
1197|    link = ListX_addFirstMalloc( &m_Links, CadPrim_Link );
1198|    CadPrim_Link_copy( link, (CadPrim_Link*)s );
1199|    s += sizeof(CadPrim_Link);
1200|  }
1201|}
1202|
1203| 
1204|/***********************************************************************
1205|  2-21. <<< [Text_Box::GetHitHandleNum] CadPrim::GetHitHandleNum の実装部 >>> 
1206|【補足】
1207|・ハンドル番号は、1=左上、2=上、3=右上、4=左、5=右、6=左下、
1208|  7=下、8=右下 です。
1209|************************************************************************/
1210|int  Text_Box::GetHitHandleNum( int x, int y, int zoom, int mode, int* dx, int* dy, int* diff, int* arrow )
1211|{
1212|  RECT  box;
1213|  int   dx1, dy1, dx2, dy2, dx3, dy3;
1214|  int  diff1;
1215|  int  diff2;
1216|  int  minDiff;
1217|  int  d;
1218|  int  slide;
1219|  int  ret = 0;
1220|  TwoD_XY  xy, center;
1221|
1222|  diff1 = 8 * 100 / zoom;  if ( diff1 < 1 )  diff1 = 1;
1223|  diff2 = 2 * 100 / zoom;  if ( diff2 < 1 )  diff2 = 1;
1224|  minDiff = 2 * diff1 + 1;
1225|
1226|  TwoD_XY_init( &xy, x, y );
1227|  TwoD_XY_init( &center, m_CenterX, m_Y );
1228|  TwoD_XY_rot( &xy, &center, - m_RotateDegree * (2 * 3.141592) / 360 );
1229|  x = (int)xy.x;  y = (int)xy.y;
1230|
1231|  GetBox( &box );
1232|  dx1 = x - box.left;
1233|  dy1 = y - box.top;
1234|  dx2 = x - ( (box.left + box.right) / 2 );
1235|  dy2 = y - ( (box.top + box.bottom) / 2 );
1236|  dx3 = x - box.right;
1237|  dy3 = y - box.bottom;
1238|  if ( m_BoxShape == Text_Box_Parallelogram )  slide = (box.bottom - box.top) / 4;
1239|  else  slide = 0;
1240|
1241|  *dx = 0;  *dy = 0;
1242|
1243|  /* 小さいときは、一部のハンドルのみ使えるようにする */
1244|  if ( box.right - box.left < diff1 && box.bottom - box.top < diff1 ) {
1245|    if ( dx3 >= -diff2 && dx3 <= diff1 && dy3 >= -diff2 && dy3 <= diff1 )
1246|      { *arrow = CadPrim_RightDownArrow;  ret = 8; }
1247|    else
1248|      { *arrow = CadPrim_NormalArrow;  ret = 0; }
1249|  }
1250|
1251|  /* 通常の大きさのとき */
1252|  else {
1253|
1254|    if ( m_BoxShape != Text_Box_NoFrame || mode == CadPrim_RotateMode ) {
1255|
1256|      /* 8箇所のハンドルにヒットしたか確認する */
1257|      if ( dx3 >= -diff2 && dx3 <= diff1 && dy2 >= -diff1 && dy2 <= diff1 ) {
1258|        d = abs(dx3) + abs(dy2);
1259|        if ( d < minDiff )  /* 最も近いハンドルを採用する */
1260|          { *arrow = CadPrim_HorizontalArrow;  minDiff = d;  ret = 5; }
1261|      }
1262|      if ( dx2 + slide >= -diff1 && dx2 + slide <= diff1 && dy3 >= -diff2 && dy3 <= diff1 ) {
1263|        d = abs(dx2 + slide) + abs(dy3);
1264|        if ( d < minDiff )
1265|          { *arrow = CadPrim_VerticalArrow;  minDiff = d;  ret = 7; }
1266|      }
1267|      if ( dx1 >= -diff1 && dx1 <= diff2 && dy2 >= -diff1 && dy2 <= diff1 ) {
1268|        d = abs(dx1) + abs(dy2);
1269|        if ( d < minDiff )
1270|          { *arrow = CadPrim_HorizontalArrow;  minDiff = d;  ret = 4; }
1271|      }
1272|      if ( dx2 - slide >= -diff1 && dx2 - slide <= diff1 && dy1 >= -diff1 && dy1 <= diff2 ) {
1273|        d = abs(dx2 - slide) + abs(dy1);
1274|        if ( d < minDiff )
1275|          { *arrow = CadPrim_VerticalArrow;  minDiff = d;  ret = 2; }
1276|      }
1277|      if ( dx3 + slide >= -diff2 && dx3 + slide <= diff1 && dy3 >= -diff2 && dy3 <= diff1 ) {
1278|        d = abs(dx3 + slide) + abs(dy3);
1279|        if ( d < minDiff )
1280|          { *arrow = CadPrim_RightDownArrow;  minDiff = d;  ret = 8; }
1281|      }
1282|      if ( dx1 - slide >= -diff1 && dx1 - slide <= diff2 && dy1 >= -diff1 && dy1 <= diff2 ) {
1283|        d = abs(dx1 - slide) + abs(dy1);
1284|        if ( d < minDiff )
1285|          { *arrow = CadPrim_RightDownArrow;  minDiff = d;  ret = 1; }
1286|      }
1287|      if ( dx3 - slide >= -diff2 && dx3 - slide <= diff1 && dy1 >= -diff1 && dy1 <= diff2 ) {
1288|        d = abs(dx3 - slide) + abs(dy1);
1289|        if ( d < minDiff )
1290|          { *arrow = CadPrim_RightUpArrow;  minDiff = d;  ret = 3; }
1291|      }
1292|      if ( dx1 + slide >= -diff1 && dx1 + slide <= diff2 && dy3 >= -diff2 && dy3 <= diff1 ) {
1293|        d = abs(dx1 + slide) + abs(dy3);
1294|        if ( d < minDiff )
1295|          { *arrow = CadPrim_RightUpArrow;  minDiff = d;  ret = 6; }
1296|      }
1297|    }
1298|
1299|    if ( ret == 0 ) {
1300|      bool  f;
1301|
1302|      /* ハンドル以外(図形の上)にヒットしたか確かめる */
1303|      if ( m_BoxShape != Text_Box_Parallelogram )
1304|        f = ( box.left <= x && x <= box.right &&  box.top <= y && y <= box.bottom );
1305|      else {
1306|        int  dy = y - ( box.top + box.bottom ) / 2;
1307|
1308|        f = ( box.left-dy/2 <= x && x <= box.right-dy/2 && box.top <= y && y <= box.bottom );
1309|      }
1310|
1311|      if ( f ) {
1312|        *dx = m_CenterX - x;
1313|        *dy = m_Y - y;
1314|        *arrow = CadPrim_MovableArrow;
1315|        ret = -1;
1316|      }
1317|      else {
1318|        *arrow = CadPrim_NormalArrow;
1319|        ret = 0;
1320|      }
1321|    }
1322|  }
1323|
1324|
1325|  /* 角度編集モードのとき、カーソルを変更する */
1326|  if ( mode == CadPrim_RotateMode ) {
1327|    if ( ret == -1 )
1328|      *arrow = CadPrim_NormalArrow;
1329|    else if ( ret > 0 ) {
1330|      if ( m_BoxShape == Text_Box_NoFrame || m_BoxShape == Text_Box_RectShape ||
1331|           m_BoxShape == Text_Box_RoundRectShape || m_BoxShape == Text_Box_DiamondShape ||
1332|           m_BoxShape == Text_Box_Parallelogram ) {
1333|        *arrow = CadPrim_MovableArrow;
1334|      }
1335|      else {
1336|        *arrow = CadPrim_NoArrow;
1337|      }
1338|    }
1339|  }
1340|
1341|  return  ret;
1342|}
1343|
1344|
1345|/***********************************************************************
1346|  2-22. <<< [Text_Box::Move] CadPrim::Move の実装部 >>>
1347|************************************************************************/
1348|void  Text_Box::Move( int dx, int dy )
1349|{
1350|  m_CenterX += dx;  m_Y += dy;
1351|  MoveLinks( true );
1352|}
1353|
1354|
1355|
1356|/***********************************************************************
1357|  2-23. <<< [Text_Box::MoveByHandle] ハンドルを動かしてパラメータを変える >>>
1358|************************************************************************/
1359|void  Text_Box::MoveByHandle( int iHandle, int x, int y, bool bShift, bool bRotate )
1360|{
1361|  RECT  box;
1362|  int   n = StrX_getNLine( m_Text );
1363|
1364|  GetBox( &box );
1365|
1366|  /* 平行四辺形のずれを直す */
1367|  if ( m_BoxShape == Text_Box_Parallelogram ) {
1368|    int  slide = (box.bottom - box.top) / 4;
1369|
1370|    if ( iHandle >= 1 && iHandle <= 3 )  x -= slide;
1371|    else if ( iHandle >= 6 )  x += slide;
1372|  }
1373|
1374|  if ( bRotate ) {
1375|    int   x1, y1, x2, y2, x3, y3;
1376|    int   hx, hy;
1377|    double  curAng, hdlAng;
1378|
1379|    x1 = box.left;
1380|    y1 = box.top;
1381|    x2 = (box.left + box.right) / 2;
1382|    y2 = (box.top + box.bottom) / 2;
1383|    x3 = box.right;
1384|    y3 = box.bottom;
1385|
1386|    switch ( iHandle ) {
1387|      case  1:  hx = x1;  hy = y1;  break;
1388|      case  2:  hx = x2;  hy = y1;  break;
1389|      case  3:  hx = x3;  hy = y1;  break;
1390|      case  4:  hx = x1;  hy = y2;  break;
1391|      case  5:  hx = x3;  hy = y2;  break;
1392|      case  6:  hx = x1;  hy = y3;  break;
1393|      case  7:  hx = x2;  hy = y3;  break;
1394|      case  8:  hx = x3;  hy = y3;  break;
1395|    }
1396|
1397|    curAng = atan2( y - y2, x - x2 );
1398|    hdlAng = atan2( hy - y2, hx - x2 );
1399|    m_RotateDegree = (int)( ( curAng - hdlAng ) * 360.0 / ( 2 * 3.141592 ) );
1400|    if ( ! bShift ) {
1401|      hx = m_RotateDegree % 90;
1402|      if ( hx < 0 )  hx += 90;
1403|      if ( hx < 8 )  m_RotateDegree -= hx;
1404|      else if ( hx > 82 )  m_RotateDegree += 90 - hx;
1405|    }
1406|  }
1407|  else {
1408|    if ( m_bTategaki && iHandle > 0 ) {
1409|      int   x1, y1, x2, y2, x3, y3;
1410|
1411|      x1 = box.left;
1412|      y1 = box.top;
1413|      x2 = (box.left + box.right) / 2;
1414|      y2 = (box.top + box.bottom) / 2;
1415|      x3 = box.right;
1416|      y3 = box.bottom;
1417|
1418|      switch ( iHandle ) {
1419|       case 1:  m_BoxMarginX += y1 - y;  m_BoxMarginY += x1 - x;  break;
1420|       case 2:  m_BoxMarginX += y1 - y;  break;
1421|       case 3:  m_BoxMarginX += y1 - y;  m_BoxMarginY += x - x3;  break;
1422|       case 4:                           m_BoxMarginY += x1 - x;  break;
1423|       case 5:                           m_BoxMarginY += x - x3;  break;
1424|       case 6:  m_BoxMarginX += y - y3;  m_BoxMarginY += x1 - x;  break;
1425|       case 7:  m_BoxMarginX += y - y3;  break;
1426|       case 8:  m_BoxMarginX += y - y3;  m_BoxMarginY += x - x3;  break;
1427|      }
1428|      if ( m_BoxMarginX < 0 )  m_BoxMarginX = 0;
1429|      if ( m_BoxMarginY < 0 )  m_BoxMarginY = 0;
1430|    }
1431|    else {
1432|      if ( iHandle > 0 ) {
1433|        switch ( m_BasePos ) {
1434|          case  Text_Box_LeftAlign:    x -= (m_W + 1) / 2;  break;
1435|          case  Text_Box_CenterAlign:  break;
1436|          case  Text_Box_RightAlign:   x += m_W / 2;  break;
1437|        }
1438|      }
1439|      switch ( iHandle ) {
1440|       case 1:
1441|        m_BoxMarginX = m_CenterX - (m_W + 1) / 2 - x;
1442|        m_BoxMarginY = m_Y + m_10Descent/10 + (n-1) * m_BetweenOfLine - m_10H/10 - y;
1443|        break;
1444|       case 2:
1445|        m_BoxMarginY = m_Y + m_10Descent/10 + (n-1) * m_BetweenOfLine - m_10H/10 - y;
1446|        break;
1447|       case 3:
1448|        m_BoxMarginX = x - m_CenterX - m_W / 2;
1449|        m_BoxMarginY = m_Y + m_10Descent/10 + (n-1) * m_BetweenOfLine - m_10H/10 - y;
1450|        break;
1451|       case 4:
1452|        m_BoxMarginX = m_CenterX - (m_W + 1) / 2 - x;
1453|        break;
1454|       case 5:
1455|        m_BoxMarginX = x - m_CenterX - m_W / 2;
1456|        break;
1457|       case 6:
1458|        m_BoxMarginX = m_CenterX - (m_W + 1) / 2 - x;
1459|        m_BoxMarginY = y - ( m_Y + m_10Descent/10 + (n-1) * m_BetweenOfLine );
1460|        break;
1461|       case 7:
1462|        m_BoxMarginY = y - ( m_Y + m_10Descent/10 + (n-1) * m_BetweenOfLine );
1463|        break;
1464|       case 8:
1465|        m_BoxMarginX = x - m_CenterX - m_W / 2;
1466|        m_BoxMarginY = y - ( m_Y + m_10Descent/10 + (n-1) * m_BetweenOfLine );
1467|        break;
1468|       case -1:
1469|        if ( ! bShift )  AutoAdjustXY( &x, &y );
1470|        GetBox( &box );
1471|        switch ( m_BasePos ) {
1472|          case  Text_Box_LeftAlign:    m_CenterX += x - box.left - m_BoxMarginX;  break;
1473|          case  Text_Box_CenterAlign:  m_CenterX += x - ( box.left + box.right ) / 2;  break;
1474|          case  Text_Box_RightAlign:   m_CenterX += x - box.right + m_BoxMarginX;  break;
1475|        }
1476|        m_Y = y;
1477|        break;
1478|      }
1479|      if ( m_BoxMarginX < 0 )  m_BoxMarginX = 0;
1480|      if ( m_BoxMarginY < 0 )  m_BoxMarginY = 0;
1481|      MoveLinks( true );
1482|    }
1483|  }
1484|}
1485|
1486|
1487|/***********************************************************************
1488|  2-24. <<< [Text_Box::GetCenterOfHandle] CadPrim::GetCenterOfHandle >>>
1489|************************************************************************/
1490|void  Text_Box::GetCenterOfHandle( int iHandle, int* x, int* y )
1491|{
1492|  RECT  box;
1493|
1494|  GetBox( &box );
1495|
1496|  switch ( iHandle ) {
1497|    case 1:  *x = box.left;                    *y = box.top;  break;
1498|    case 2:  *x = (box.left + box.right) / 2;  *y = box.top;  break;
1499|    case 3:  *x = box.right;                   *y = box.top;  break;
1500|    case 4:  *x = box.left;                    *y = (box.top + box.bottom) / 2;  break;
1501|    case 5:  *x = box.right;                   *y = (box.top + box.bottom) / 2;
1502|    case 6:  *x = box.left;                    *y = box.bottom;  break;
1503|    case 7:  *x = (box.left + box.right) / 2;  *y = box.bottom;  break;
1504|    case 8:  *x = box.right;                   *y = box.bottom;  break;
1505|  }
1506|}
1507|
1508|
1509|/***********************************************************************
1510|  2-25. <<< [Text_Box::MoveLinks] リンクしている図形への影響を処理する >>>
1511|************************************************************************/
1512|void  Text_Box::MoveLinks( bool bShift )
1513|{
1514|  if ( ListX_getN( &m_Links, CadPrim_Link ) > 0 ) {
1515|    RECT  rc;
1516|    int  x,y;
1517|    CadPrim_Link*  link;
1518|
1519|    GetBox( &rc );
1520|    x = (rc.left + rc.right) / 2;
1521|    y = (rc.top + rc.bottom) / 2;
1522|    for ( ListX_forEach( &m_Links, &link, CadPrim_Link ) ) {
1523|      if ( link->prim->GetHold() )  continue;
1524|      link->x = x;  link->y = y;
1525|      link->prim->MoveByHandle( link->iHandle, x, y, bShift, false );
1526|    }
1527|  }
1528|}
1529|
1530|
1531|/***********************************************************************
1532|  2-26. <<< [Text_Box::AutoAdjustXY] 位置を自動調整する >>>
1533|************************************************************************/
1534|void  Text_Box::AutoAdjustXY( int* x, int* y )
1535|{
1536|  CSVGCatApp*  app = (CSVGCatApp*)AfxGetApp();
1537|  CadPrim_Link*  link;
1538|  int   xx, yy;
1539|  bool  bb;
1540|  int   dx = INT_MAX, dy = INT_MAX;
1541|  int   dcy;
1542|  RECT  rc;
1543|  enum { diff = 6 };
1544|
1545|  GetBox( &rc );
1546|  dcy = ( rc.top + rc.bottom ) / 2 - m_Y;
1547|  *y += dcy;
1548|
1549|  for ( ListX_forEach( &m_Links, &link, CadPrim_Link ) ) {
1550|    bb = false;
1551|    switch ( link->prim->GetTypeID() ) {
1552|
1553|     /* リンクラインの反対側の頂点の座標を xx, yy に格納する */
1554|     case  Line_Ex_TypeID: {
1555|      Line_Ex*  line = (Line_Ex*)link->prim;
1556|
1557|      if ( link->iHandle == 1 )  { xx = line->m_Line.x2;  yy = line->m_Line.y2; }
1558|      else  { xx = line->m_Line.x1;  yy = line->m_Line.y1; }
1559|      bb = true;
1560|      break;
1561|     }
1562|     case  Line_Corner_TypeID: {
1563|      Line_Corner*  line = (Line_Corner*)link->prim;
1564|
1565|      if ( link->iHandle == 1 )  { xx = line->m_Line.x2;  yy = line->m_Line.y2; }
1566|      else  { xx = line->m_Line.x1;  yy = line->m_Line.y1; }
1567|      bb = true;
1568|      break;
1569|     }
1570|    }
1571|
1572|    /* 最も差の小さい dx, dy を得る */
1573|    if ( bb ) {
1574|      if ( abs( xx - *x ) < abs( dx ) )  dx = xx - *x;
1575|      if ( abs( yy - *y ) < abs( dy ) )  dy = yy - *y;
1576|    }
1577|  }
1578|
1579|  if ( dx < diff && dx > -diff )  *x += dx;
1580|  if ( dy < diff && dy > -diff )  *y += dy;
1581|
1582|  *y -= dcy;
1583|}
1584|
1585|
1586|
1587| 
1588|/***********************************************************************
1589|  2-27. <<< [Text_Box::SetHold] CadPrim::SetHold の実装部 >>> 
1590|************************************************************************/
1591|void  Text_Box::SetHold( bool b )
1592|{
1593|  m_bHold = b;
1594|}
1595|
1596|/***********************************************************************
1597|  2-28. <<< [Text_Box::GetHold] CadPrim::GetHold の実装部 >>>
1598|************************************************************************/
1599|bool  Text_Box::GetHold()
1600|{
1601|  return  m_bHold;
1602|}
1603|
1604|/***********************************************************************
1605|  2-29. <<< [Text_Box::IsHoldable] CadPrim::IsHoldable の実装部 >>>
1606|************************************************************************/
1607|bool  Text_Box::IsHoldable()
1608|{
1609|  CadPrim_Link*  link;
1610|
1611|  for ( ListX_forEach( &m_Links, &link, CadPrim_Link ) ) {
1612|    if ( link->prim != NULL && link->prim->GetHold() ) {
1613|      switch ( link->prim->GetTypeID() ) {
1614|       case  Line_Ex_TypeID: {
1615|        Line_Ex*  line = (Line_Ex*)link->prim;
1616|        if ( line->m_Controler[0] != NULL && line->m_Controler[1] != NULL )
1617|          return  false;
1618|       }
1619|       case  Line_Corner_TypeID: {
1620|        Line_Corner*  line = (Line_Corner*)link->prim;
1621|        if ( line->m_Controler[0] != NULL && line->m_Controler[1] != NULL )
1622|          return  false;
1623|       }
1624|      }
1625|    }
1626|  }
1627|  return  true;
1628|}
1629|
1630|/***********************************************************************
1631|  2-30. <<< [Text_Box::SetSelected] CadPrim::SetSelected の実装部 >>>
1632|************************************************************************/
1633|void  Text_Box::SetSelected( bool b )
1634|{
1635|  m_bSelected = b;
1636|}
1637|
1638|/***********************************************************************
1639|  2-31. <<< [Text_Box::GetSelected] CadPrim::GetSelected の実装部 >>>
1640|************************************************************************/
1641|bool  Text_Box::GetSelected()
1642|{
1643|  return  m_bSelected;
1644|}
1645|
1646| 
1647|/***********************************************************************
1648|  2-32. <<< [Text_Box::IsMultiSelect] CadPrim::IsMultiSelect の実装部 >>> 
1649|************************************************************************/
1650|bool  Text_Box::IsMultiSelect( Rect* rect )
1651|{
1652|  Rect  com;
1653|  RECT  me;
1654|  Rect  me2;
1655|
1656|  GetBox( &me );
1657|  Rect_init( &me2,  me.left, me.top,
1658|    me.right - me.left + 1,  me.bottom - me.top + 1 );
1659|  Rect_toAnd( &com, &me2, rect );
1660|  return  ( com.w > 0 && com.h > 0 );
1661|}
1662|
1663|
1664|/***********************************************************************
1665|  2-33. <<< [Text_Box::GetForAlign] CadPrim::GetForAlign の実装部 >>>
1666|************************************************************************/
1667|int   Text_Box::GetForAlign( int iPos )
1668|{
1669|  RECT  me;
1670|  GetBox( &me );
1671|
1672|  switch ( iPos ) {
1673|    case  CadPrim_AlignLeft:    return  me.left;
1674|    case  CadPrim_AlignRight:   return  me.right;
1675|    case  CadPrim_AlignTop:     return  me.top;
1676|    case  CadPrim_AlignBottom:  return  me.bottom;
1677|    case  CadPrim_AlignVertical:    return  ( me.left + me.right ) / 2;
1678|    case  CadPrim_AlignHorizontal:  return  ( me.top + me.bottom ) / 2;
1679|    default:  error();  return  0;
1680|  }
1681|}
1682|
1683|/***********************************************************************
1684|  2-34. <<< [Text_Box::SetForAlign] CadPrim::SetForAlign の実装部 >>>
1685|************************************************************************/
1686|void  Text_Box::SetForAlign( int iPos, int value )
1687|{
1688|  RECT  me;
1689|  GetBox( &me );
1690|
1691|  switch ( iPos ) {
1692|    case  CadPrim_AlignLeft:    m_CenterX += value - me.left;  break;
1693|    case  CadPrim_AlignRight:   m_CenterX += value - me.right;  break;
1694|    case  CadPrim_AlignTop:     m_Y += value - me.top;  break;
1695|    case  CadPrim_AlignBottom:  m_Y += value - me.bottom;  break;
1696|    case  CadPrim_AlignVertical:    m_CenterX += value - ( me.left + me.right ) / 2;  break;
1697|    case  CadPrim_AlignHorizontal:  m_Y += value - ( me.top + me.bottom ) / 2;  break;
1698|    default:  error();
1699|  }
1700|  MoveLinks( true );
1701|}
1702|
1703|/***********************************************************************
1704|  2-35. <<< [Text_Box::GetForFitSize] CadPrim::GetForFitSize の実装部 >>>
1705|************************************************************************/
1706|int   Text_Box::GetForFitSize( int iAttr )
1707|{
1708|  RECT  me;
1709|  GetBox( &me );
1710|
1711|  if ( iAttr == CadPrim_Horizontal )  return  me.right - me.left + 1;
1712|  else  return  me.bottom - me.top + 1;
1713|}
1714|
1715|/***********************************************************************
1716|  2-36. <<< [Text_Box::SetForFitSize] CadPrim::SetForFitSize の実装部 >>>
1717|************************************************************************/
1718|void  Text_Box::SetForFitSize( int iAttr, int value )
1719|{
1720|  RECT  me;
1721|  GetBox( &me );
1722|
1723|  if ( iAttr == CadPrim_Horizontal )
1724|    m_BoxMarginX += ( value - (me.right - me.left + 1) ) / 2;
1725|  else
1726|    m_BoxMarginY += ( value - (me.bottom - me.top + 1) ) / 2;
1727|
1728|  MoveLinks( true );
1729|}
1730|
1731| 
1732|/***********************************************************************
1733|  2-37. <<< [Text_Box::GetNProp] プロパティの要素数を返す >>> 
1734|************************************************************************/
1735|int  Text_Box::GetNProp()
1736|{
1737|  #ifdef  NDEBUG
1738|    return  23;
1739|  #else
1740|    return  26;
1741|  #endif
1742|}
1743|
1744|
1745|/***********************************************************************
1746|  2-38. <<< [Text_Box::GetProp] プロパティの名前と値を取得する >>>
1747|************************************************************************/
1748|int  Text_Box::GetProp( int iProp, bool bJapanese, char* name, int name_size,
1749|  char* value, int value_size, const char* path, void** option )
1750|{
1751|  int  r = CadPrim_ReadOnly;
1752|
1753|  static ListX  list;
1754|  static StrX_ListElem  strs[6];
1755|  static int   range[2];
1756|
1757|  switch ( iProp ) {
1758|    case 0:
1759|      if ( bJapanese )
1760|        strncpy( name, "テキスト", name_size );
1761|      else
1762|        strncpy( name, "Text", name_size );
1763|      strncpy( value, m_Text, value_size );
1764|      r = CadPrim_TextML;
1765|      break;
1766|    case 1:
1767|      strncpy( name, "id", name_size );
1768|      strncpy( value, m_IdLabel, value_size );
1769|      *option = NULL;
1770|      r = CadPrim_Text;
1771|      break;
1772|    case 2:
1773|      strncpy( name, "URL/onclick", name_size );
1774|      #if 1
1775|        if ( path[0] == '\0' )  strcpy( value, m_URL );
1776|        else  StrX_cpyStepPath2( value, m_URL, value_size, path );
1777|        if ( bJapanese )
1778|          *option = (void*)"すべてのファイル (*.*)|*.*||";
1779|        else
1780|          *option = (void*)"All Files (*.*)|*.*||";
1781|        r = CadPrim_Path;
1782|      #else
1783|        strncpy( value, m_URL, value_size );
1784|        r = CadPrim_Text;
1785|      #endif
1786|      break;
1787|    case 3:
1788|      strncpy( name, "target", name_size );
1789|      strncpy( value, m_Target, value_size );
1790|      *option = NULL;
1791|      r = CadPrim_Text;
1792|      break;
1793|    case 4:
1794|      ListX_init( &list );
1795|      if ( bJapanese ) {
1796|        strncpy( name, "枠の形状", name_size );
1797|        ListX_addLast( &list, &strs[0] );  strs[0].p = "  枠なし";
1798|        ListX_addLast( &list, &strs[1] );  strs[1].p = "□ 矩形、長方形";
1799|        ListX_addLast( &list, &strs[2] );  strs[2].p = "ロ 丸矩形";
1800|        ListX_addLast( &list, &strs[3] );  strs[3].p = "○ 円、楕円";
1801|        ListX_addLast( &list, &strs[4] );  strs[4].p = "◇ ひし形";
1802|        ListX_addLast( &list, &strs[5] );  strs[5].p = "// 平行四辺形";
1803|      }
1804|      else {
1805|        strncpy( name, "Shape of Frame", name_size );
1806|        ListX_addLast( &list, &strs[0] );  strs[0].p = "No Frame";
1807|        ListX_addLast( &list, &strs[1] );  strs[1].p = "Rectangle";
1808|        ListX_addLast( &list, &strs[2] );  strs[2].p = "Round Rectangle";
1809|        ListX_addLast( &list, &strs[3] );  strs[3].p = "Circle, Ellipse";
1810|        ListX_addLast( &list, &strs[4] );  strs[4].p = "Diamond";
1811|        ListX_addLast( &list, &strs[5] );  strs[5].p = "Parallelogram";
1812|      }
1813|      sprintf( value, "%d", m_BoxShape );
1814|      *option = &list;
1815|      r = CadPrim_Select;
1816|      break;
1817|    case 5:
1818|      if ( bJapanese )
1819|        strncpy( name, "x (横基準点)", name_size );
1820|      else
1821|        strncpy( name, "x (Base Point)", name_size );
1822|      sprintf( value, "%d", m_CenterX );
1823|      range[0] = INT_MIN;  range[1] = INT_MAX;
1824|      *option = range;
1825|      r = CadPrim_Int;
1826|      break;
1827|    case 6:
1828|      if ( bJapanese )
1829|        strncpy( name, "y (縦基準点)", name_size );
1830|      else
1831|        strncpy( name, "y (Base Point)", name_size );
1832|      sprintf( value, "%d", m_Y );
1833|      range[0] = INT_MIN;  range[1] = INT_MAX;
1834|      *option = range;
1835|      r = CadPrim_Int;
1836|      break;
1837|    case 7:
1838|      if ( bJapanese )
1839|        strncpy( name, "幅の誤差", name_size );
1840|      else
1841|        strncpy( name, "Difference of width", name_size );
1842|      sprintf( value, "%d", m_DiffW );
1843|      range[0] = INT_MIN;  range[1] = INT_MAX;
1844|      *option = range;
1845|      r = CadPrim_Int;
1846|      break;
1847|    case 8:
1848|      if ( bJapanese )
1849|        strncpy( name, "行間", name_size );
1850|      else
1851|        strncpy( name, "Between of Line", name_size );
1852|      sprintf( value, "%d", m_BetweenOfLine );
1853|      range[0] = 1;  range[1] = INT_MAX;
1854|      *option = range;
1855|      r = CadPrim_Int;
1856|      break;
1857|    case 9:
1858|      ListX_init( &list );
1859|      if ( bJapanese ) {
1860|        strncpy( name, "基準点位置", name_size );
1861|        if ( m_bTategaki ) {
1862|          ListX_addLast( &list, &strs[0] );  strs[0].p = "上端";
1863|          ListX_addLast( &list, &strs[1] );  strs[1].p = "中央";
1864|          ListX_addLast( &list, &strs[2] );  strs[2].p = "下端";
1865|        }
1866|        else {
1867|          ListX_addLast( &list, &strs[0] );  strs[0].p = "左端";
1868|          ListX_addLast( &list, &strs[1] );  strs[1].p = "中央";
1869|          ListX_addLast( &list, &strs[2] );  strs[2].p = "右端";
1870|        }
1871|      }
1872|      else {
1873|        strncpy( name, "Base Position", name_size );
1874|        if ( m_bTategaki ) {
1875|          ListX_addLast( &list, &strs[0] );  strs[0].p = "Top";
1876|          ListX_addLast( &list, &strs[1] );  strs[1].p = "Center";
1877|          ListX_addLast( &list, &strs[2] );  strs[2].p = "Bottom";
1878|        }
1879|        else {
1880|          ListX_addLast( &list, &strs[0] );  strs[0].p = "Left";
1881|          ListX_addLast( &list, &strs[1] );  strs[1].p = "Center";
1882|          ListX_addLast( &list, &strs[2] );  strs[2].p = "Right";
1883|        }
1884|      }
1885|      sprintf( value, "%d", m_BasePos );
1886|      *option = &list;
1887|      r = CadPrim_Select;
1888|      break;
1889|    case 10:
1890|      if ( bJapanese )
1891|        strncpy( name, "角度", name_size );
1892|      else
1893|        strncpy( name, "Angle", name_size );
1894|      sprintf( value, "%d", m_RotateDegree );
1895|      range[0] = INT_MIN;  range[1] = INT_MAX;
1896|      *option = range;
1897|      r = CadPrim_Int;
1898|      break;
1899|    case 11:
1900|      if ( bJapanese )
1901|        strncpy( name, "テキストの色", name_size );
1902|      else
1903|        strncpy( name, "Text Color", name_size );
1904|      StrX_getColorStr( value, m_Color );
1905|      r = CadPrim_Color;
1906|      break;
1907|    case 12:
1908|      if ( bJapanese )
1909|        strncpy( name, "フォント", name_size );
1910|      else
1911|        strncpy( name, "Font", name_size );
1912|      StrX_getFontStr( value, m_Font, m_Size*10, m_bBold, m_bItalic );
1913|      r = CadPrim_Font;
1914|      break;
1915|    case 13:
1916|      if ( bJapanese )
1917|        strncpy( name, "サイズ", name_size );
1918|      else
1919|        strncpy( name, "Size", name_size );
1920|      sprintf( value, "%d", m_Size );
1921|      range[0] = 1;  range[1] = INT_MAX;
1922|      *option = range;
1923|      r = CadPrim_Int;
1924|      break;
1925|    case 14:
1926|      if ( bJapanese )
1927|        strncpy( name, "太字", name_size );
1928|      else
1929|        strncpy( name, "Bold", name_size );
1930|      sprintf( value, "%d", m_bBold );
1931|      r = CadPrim_Bool;
1932|      break;
1933|    case 15:
1934|      if ( bJapanese )
1935|        strncpy( name, "斜体", name_size );
1936|      else
1937|        strncpy( name, "Itaric", name_size );
1938|      sprintf( value, "%d", m_bItalic );
1939|      r = CadPrim_Bool;
1940|      break;
1941|    case 16:
1942|      ListX_init( &list );
1943|      if ( bJapanese ) {
1944|        strncpy( name, "方向", name_size );
1945|        ListX_addLast( &list, &strs[0] );  strs[0].p = "横書き";
1946|        ListX_addLast( &list, &strs[1] );  strs[1].p = "縦書き";
1947|      }
1948|      else {
1949|        strncpy( name, "Direction", name_size );
1950|        ListX_addLast( &list, &strs[0] );  strs[0].p = "Horizontal";
1951|        ListX_addLast( &list, &strs[1] );  strs[1].p = "Vertical";
1952|      }
1953|      sprintf( value, "%d", m_bTategaki );
1954|      *option = &list;
1955|      r = CadPrim_Select;
1956|      break;
1957|    case 17:
1958|      if ( bJapanese )
1959|        strncpy( name, "横マージン", name_size );
1960|      else
1961|        strncpy( name, "Horizontal Mergin", name_size );
1962|      sprintf( value, "%d", m_bTategaki ? m_BoxMarginY : m_BoxMarginX );
1963|      range[0] = 0;  range[1] = INT_MAX;
1964|      *option = range;
1965|      r = CadPrim_Int;
1966|      break;
1967|    case 18:
1968|      if ( bJapanese )
1969|        strncpy( name, "縦マージン", name_size );
1970|      else
1971|        strncpy( name, "Vertical Mergin", name_size );
1972|      sprintf( value, "%d", m_bTategaki ? m_BoxMarginX : m_BoxMarginY );
1973|      range[0] = 0;  range[1] = INT_MAX;
1974|      *option = range;
1975|      r = CadPrim_Int;
1976|      break;
1977|    case 19:
1978|      if ( bJapanese )
1979|        strncpy( name, "塗りつぶし色", name_size );
1980|      else
1981|        strncpy( name, "Fill Color", name_size );
1982|      StrX_getColorStr( value, m_FillColor );
1983|      r = CadPrim_Color;
1984|      break;
1985|    case 20:
1986|      if ( bJapanese )
1987|        strncpy( name, "濃さ(非透過%)", name_size );
1988|      else
1989|        strncpy( name, "Transparent %", name_size );
1990|      sprintf( value, "%d", m_FillNTrans );
1991|      range[0] = 0;  range[1] = 100;
1992|      *option = range;
1993|      r = CadPrim_Int;
1994|      break;
1995|    case 21:
1996|      if ( bJapanese )
1997|        strncpy( name, "枠の色", name_size );
1998|      else
1999|        strncpy( name, "Frame Color", name_size );
2000|      StrX_getColorStr( value, m_BorderColor );
2001|      r = CadPrim_Color;
2002|      break;
2003|    case 22:
2004|      if ( bJapanese )
2005|        strncpy( name, "枠の幅", name_size );
2006|      else
2007|        strncpy( name, "Frame Width", name_size );
2008|      sprintf( value, "%d", m_BorderWidth );
2009|      range[0] = 0;  range[1] = INT_MAX;
2010|      *option = range;
2011|      r = CadPrim_Int;
2012|      break;
2013|   #ifndef NDEBUG
2014|    case 23:
2015|      strncpy( name, "id", name_size );
2016|      sprintf( value, "%d", m_id );
2017|      break;
2018|    case 24:
2019|      strncpy( name, "m_Controler_id", name_size );
2020|      sprintf( value, "%d", m_Controler_id );
2021|      break;
2022|    case 25: {
2023|      CadPrim_Link*  link = ListX_getFirst( &m_Links, CadPrim_Link );
2024|      strncpy( name, "m_Links(0)", name_size );
2025|      if ( link == NULL )  strcpy( value, "NULL" );
2026|      else  sprintf( value, "%d", link->prim_id );
2027|      break;
2028|    }
2029|   #endif
2030|  }
2031|
2032|  return  r;
2033|}
2034|
2035|/***********************************************************************
2036|  2-39. <<< [Text_Box::SetProp] プロパティの値を設定する >>>
2037|************************************************************************/
2038|void  Text_Box::SetProp( int iProp, const char* value, const char* path )
2039|{
2040|  char  s[256];
2041|  int   i;
2042|
2043|  switch ( iProp ) {
2044|    case 0:
2045|      m_Text = value;
2046|      break;
2047|    case 1:
2048|      m_IdLabel = value;
2049|      break;
2050|    case 2:
2051|      m_URL = value;
2052|      break;
2053|    case 3:
2054|      m_Target = value;
2055|      break;
2056|    case 4:
2057|      ChangeShape( atoi( value ) );
2058|      break;
2059|    case 5:
2060|      m_CenterX = atoi( value );
2061|      break;
2062|    case 6:
2063|      m_Y = atoi( value );
2064|      break;
2065|    case 7:
2066|      m_DiffW = atoi( value );
2067|      break;
2068|    case 8:
2069|      m_BetweenOfLine = atoi( value );
2070|      break;
2071|    case 9:
2072|      ChangeAlign( atoi( value ) );
2073|      break;
2074|    case 10:
2075|      m_RotateDegree = atoi( value );
2076|      break;
2077|    case 11:
2078|      m_Color = StrX_getColorValue( value );
2079|      break;
2080|    case 12:
2081|      i = m_Size;
2082|      StrX_getFontValue( value, s, &m_Size, &m_bBold, &m_bItalic );
2083|      m_Size /= 10;
2084|      m_BetweenOfLine += m_Size - i;
2085|      m_Font = s;
2086|      break;
2087|    case 13:
2088|      i = m_Size;
2089|      m_Size = atoi( value );
2090|      m_BetweenOfLine += m_Size - i;
2091|      break;
2092|    case 14:
2093|      m_bBold = atoi( value ) != 0;
2094|      break;
2095|    case 15:
2096|      m_bItalic = atoi( value ) != 0;
2097|      break;
2098|    case 16:
2099|      m_bTategaki = atoi( value ) != 0;
2100|      break;
2101|    case 17:
2102|      if ( m_bTategaki )  m_BoxMarginY = atoi( value );
2103|      else  m_BoxMarginX = atoi( value );
2104|      break;
2105|    case 18:
2106|      if ( m_bTategaki )  m_BoxMarginX = atoi( value );
2107|      else  m_BoxMarginY = atoi( value );
2108|      break;
2109|    case 19:
2110|      m_FillColor = StrX_getColorValue( value );
2111|      break;
2112|    case 20:
2113|      m_FillNTrans = atoi( value );
2114|      break;
2115|    case 21:
2116|      m_BorderColor = StrX_getColorValue( value );
2117|      break;
2118|    case 22: {
2119|      int  w = atoi( value );
2120|
2121|      if ( w == 0 ) {
2122|        int  shape = m_BoxShape;
2123|
2124|        ChangeShape( Text_Box_NoFrame );  // マージンを枠なし用に小さくする
2125|        m_BoxShape = shape;
2126|      }
2127|      m_BorderWidth = w;
2128|      break;
2129|    }
2130|  }
2131|}
2132|
2133|
2134|
2135| 
2136|/***********************************************************************
2137|  2-40. <<< [Text_Box::IsNeedUnicode] CadPrim::IsNeedUnicode の実装部 >>> 
2138|************************************************************************/
2139|bool  Text_Box::IsNeedUnicode()
2140|{
2141|  return  ( StrX_isExist2byte( m_Text ) || StrX_isExist2byte( m_URL ) )!= 0;
2142|}
2143|
2144| 
2145|/***********************************************************************
2146|  2-41. <<< [Text_Box::OnCreated] CadPrim::OnCreated の実装部 >>> 
2147|************************************************************************/
2148|void  Text_Box::OnCreated()
2149|{
2150|}
2151|
2152| 
2153|/***********************************************************************
2154|  2-42. <<< [Text_Box::GetBox] 枠の座標を取得する >>> 
2155|【補足】
2156|・Draw 実行後に使えます。
2157|************************************************************************/
2158|void  Text_Box::GetBox( RECT* rc )
2159|{
2160|  int  n;
2161|
2162|  if ( IsNotSetDrawParam() )
2163|    error2_0( SVGCat_Err_NotSetDrawParam, "" );
2164|
2165|  switch ( m_BasePos ) {
2166|
2167|   case  Text_Box_LeftAlign:
2168|    rc->left = m_CenterX - m_BoxMarginX;
2169|    rc->right = m_CenterX + m_W + m_DiffW + m_BoxMarginX;
2170|    break;
2171|
2172|   case  Text_Box_CenterAlign:
2173|    rc->left = m_CenterX - ( m_W + m_DiffW ) / 2 - m_BoxMarginX;
2174|    rc->right =  rc->left + m_W + m_DiffW + 2 * m_BoxMarginX;
2175|    break;
2176|
2177|   case  Text_Box_RightAlign:
2178|    rc->left = m_CenterX - m_W - m_DiffW - m_BoxMarginX;
2179|    rc->right =  m_CenterX + m_BoxMarginX;
2180|    break;
2181|  }
2182|
2183|  n = StrX_getNLine( m_Text );
2184|  rc->top =  m_Top - m_BoxMarginY;
2185|  rc->bottom = m_Top + m_10H/10 + m_BoxMarginY + 1;
2186|
2187|
2188|  if ( m_bTategaki ) {
2189|    POINT  pts[2];
2190|    TwoD_XY  center, xy;
2191|    int   i;
2192|
2193|    pts[0].x = rc->left;   pts[0].y = rc->top;
2194|    pts[1].x = rc->right;  pts[1].y = rc->bottom;
2195|    TwoD_XY_init( &center, m_CenterX - 1, m_Y );
2196|    for ( i = 0; i < 2; i++ ) {
2197|      TwoD_XY_init( &xy, pts[i].x, pts[i].y );
2198|      TwoD_XY_rot( &xy, &center, 90 * (2 * 3.141592) / 360 );
2199|      pts[i].x = (long)(xy.x + 0.5);
2200|      pts[i].y = (long)(xy.y + 0.5);
2201|    }
2202|    rc->left = pts[1].x;  rc->right = pts[0].x;
2203|    rc->top = pts[0].y - 1;  rc->bottom = pts[1].y;
2204|
2205|    i = ( m_10H/10 - (StrX_getNLine( m_Text ) - 1) * m_BetweenOfLine ) / 2 - m_10Descent/10;
2206|    rc->left -= i;
2207|    rc->right -= i;
2208|  }
2209|}
2210|
2211| 
2212|/***********************************************************************
2213|  2-43. <<< [Text_Box::GetTXYByIndex] 位置番号から位置座標(カラム&行)を得る >>> 
2214|【引数】
2215|  ・int  index;   位置番号(テキストの先頭=0、改行は+2)
2216|  ・int*  cx,cy;  (出力)位置座標(カラム&行、先頭は 0,0)
2217|  ・char*  返り値;  行頭(m_Textの内部)
2218|************************************************************************/
2219|char*  Text_Box::GetTXYByIndex( int index, int* cx, int* cy )
2220|{
2221|  char*   p;
2222|
2223|  *cy = StrX_getILine( m_Text, (const char*)m_Text + index ) - 1;
2224|  p = StrX_refTopOfLine( m_Text, *cy+1 );
2225|  *cx = (const char*)m_Text + index - p;
2226|
2227|  return  p;
2228|}
2229|
2230|
2231|
2232|
2233| 
2234|/***********************************************************************
2235|  2-44. <<< [Text_Box::GetGXYByIndex] 位置番号から位置座標を得る >>> 
2236|【引数】
2237|  ・int  index;   位置番号(テキストの先頭=0、改行は+2)
2238|  ・int*  dx,dy;  (出力)テキストのベースライン左端の座標(原点は m_CenterX, m_Y)
2239|【補足】
2240|・現在、左詰しか対応していません。
2241|************************************************************************/
2242|void  Text_Box::GetGXYByIndex( CDC* dc, int index, int* dx, int* dy )
2243|{
2244|    CFont   font;
2245|    CFont   font2;
2246|    CFont*  oldFont;
2247|    LOGFONT  logFont;
2248|    CSize   size;
2249|    int     cx, cy;
2250|    char*   p;
2251|    char    s[1024];
2252|
2253|    font.CreatePointFont( m_Size*100, (m_bTategaki ? CString('@')+m_Font : m_Font), dc );
2254|    font.GetLogFont( &logFont );
2255|    logFont.lfWidth = 0;
2256|    logFont.lfHeight = m_Size * 100;
2257|    logFont.lfWeight = m_bBold ? FW_BOLD : FW_NORMAL;
2258|    logFont.lfItalic = m_bItalic;
2259|    logFont.lfEscapement = - m_RotateDegree * 10 + (m_bTategaki ? 2700 :0);
2260|    font2.CreatePointFontIndirect( &logFont, dc );
2261|    oldFont = dc->SelectObject( &font2 );
2262|
2263|    p = GetTXYByIndex( index, &cx, &cy );
2264|
2265|    StrX_cpy( s, p, cx < sizeof(s) ? cx+1 : sizeof(s) );
2266|
2267|    size = dc->GetOutputTextExtent( s );
2268|    *dx = size.cx / 10;
2269|    if ( cy == 0 )  *dy = 0;  else  *dy = m_BetweenOfLine * cy;
2270|
2271|    dc->SelectObject( oldFont );
2272|}
2273|
2274|
2275|
2276|
2277| 
2278|/***********************************************************************
2279|  2-45. <<< [Text_Box::GetGXYByTXY] カラム&行から位置座標を得る >>> 
2280|【引数】
2281|  ・int*  cx,cy;  位置座標(カラム&行、先頭は 0,0)
2282|  ・int*  dx,dy;  (出力)テキストのベースライン左端の座標(原点は m_CenterX, m_Y)
2283|【補足】
2284|・現在、左詰しか対応していません。
2285|************************************************************************/
2286|void  Text_Box::GetGXYByTXY( CDC* dc, int cx, int cy, int* dx, int* dy )
2287|{
2288|    CFont   font;
2289|    CFont   font2;
2290|    CFont*  oldFont;
2291|    LOGFONT  logFont;
2292|    CSize   size;
2293|    char*   p;
2294|    char    s[1024];
2295|
2296|    font.CreatePointFont( m_Size*100, (m_bTategaki ? CString('@')+m_Font : m_Font), dc );
2297|    font.GetLogFont( &logFont );
2298|    logFont.lfWidth = 0;
2299|    logFont.lfHeight = m_Size * 100;
2300|    logFont.lfWeight = m_bBold ? FW_BOLD : FW_NORMAL;
2301|    logFont.lfItalic = m_bItalic;
2302|    logFont.lfEscapement = - m_RotateDegree * 10 + (m_bTategaki ? 2700 :0);
2303|    font2.CreatePointFontIndirect( &logFont, dc );
2304|    oldFont = dc->SelectObject( &font2 );
2305|
2306|    p = StrX_refTopOfLine( m_Text, cy+1 );
2307|
2308|    StrX_cpy( s, p, cx < sizeof(s) ? cx+1 : sizeof(s) );
2309|
2310|    size = dc->GetOutputTextExtent( s );
2311|    *dx = size.cx / 10;
2312|    if ( cy == 0 )  *dy = 0;  else  *dy = m_BetweenOfLine * cy;
2313|
2314|    dc->SelectObject( oldFont );
2315|}
2316|
2317| 
2318|/***********************************************************************
2319|  2-46. <<< [Text_Box::GetLinkToHandle] CadPrim::GetLinkToHandle の実装部 >>> 
2320|************************************************************************/
2321|CadPrim_Link*  Text_Box::GetLinkToHandle( int iHandle )
2322|{
2323|  ASSERT( iHandle >= 1 && iHandle <= GetNumOfLinkToHandle() );
2324|  return  ListX_get( &m_Links, iHandle - 1, CadPrim_Link );
2325|}
2326|
2327|int  Text_Box::GetNumOfLinkToHandle()
2328|{
2329|  return  ListX_getN( &m_Links, CadPrim_Link );
2330|}
2331|
2332|
2333|/***********************************************************************
2334|  2-47. <<< [Text_Box::GetLinkOnReadHandleNum] CadPrim::GetLinkOnReadHandleNum の実装部 >>>
2335|************************************************************************/
2336|int  Text_Box::GetLinkOnReadHandleNum( int x, int y, int diff )
2337|{
2338|  RECT  rc;
2339|  int  cx, cy;
2340|
2341|  GetBox( &rc );
2342|  cx = (rc.left + rc.right) / 2;
2343|  cy = (rc.top + rc.bottom) / 2;
2344|  return ( cx-diff <= x && x <= cx+diff &&  cy-diff <= y && y <= cy+diff );
2345|}
2346|
2347|/***********************************************************************
2348|  2-48. <<< [Text_Box::GetLinkableHandleNum] CadPrim::GetLinkableHandleNum の実装部 >>>
2349|************************************************************************/
2350|int  Text_Box::GetLinkableHandleNum( int x, int y )
2351|{
2352|  RECT  rc;
2353|
2354|  GetBox( &rc );
2355|  return ( rc.left <= x && x <= rc.right && rc.top <= y && y <= rc.bottom );
2356|}
2357|
2358|
2359|/***********************************************************************
2360|  2-49. <<< [Text_Box::LinkToHandle] CadPrim::LinkToHandle の実装部 >>>
2361|************************************************************************/
2362|void  Text_Box::LinkToHandle( int iHandleOfThis, CadPrim* prim, int iHandleOfPrim )
2363|{
2364|  CadPrim_Link*  link;
2365|  RECT  rc;
2366|
2367|  #ifndef  NDEBUG
2368|  for ( ListX_forEach( &m_Links, &link, CadPrim_Link ) ) {
2369|    if ( link->prim == prim && link->iHandle != iHandleOfPrim )
2370|      error();  /* 重複リンク */
2371|  }
2372|  #endif
2373|
2374|  for ( ListX_forEach( &m_Links, &link, CadPrim_Link ) ) {
2375|    if ( link->prim == prim && link->iHandle == iHandleOfPrim )
2376|      return;
2377|  }
2378|
2379|  GetBox( &rc );
2380|
2381|  link = ListX_addLastMalloc( &m_Links, CadPrim_Link );
2382|  link->iHandle = iHandleOfPrim;
2383|  link->prim = prim;
2384|  link->prim_id = prim->GetID();
2385|  link->x = (rc.left + rc.right) / 2;
2386|  link->y = (rc.top + rc.bottom) / 2;
2387|
2388|  prim->LinkToControler( iHandleOfPrim, this );
2389|  prim->MoveByHandle( iHandleOfPrim, link->x, link->y, false, false );
2390|}
2391|
2392|
2393|/***********************************************************************
2394|  2-50. <<< [Text_Box::UnlinkToHandle] CadPrim::UnlinkToHandle の実装部 >>>
2395|************************************************************************/
2396|void  Text_Box::UnlinkToHandle( CadPrim* prim, int iHandleOfPrim, bool mutual )
2397|{
2398|  CadPrim_Link*  link;
2399|
2400|
2401|  for ( ListX_forEach( &m_Links, &link, CadPrim_Link ) ) {
2402|    if ( link->prim == prim && link->iHandle == iHandleOfPrim ) {
2403|      if ( mutual )
2404|        prim->UnlinkToControler( link->iHandle, this );
2405|      ListX_removeDelete( &m_Links, link, NULL );
2406|      break;
2407|    }
2408|  }
2409|}
2410|
2411|
2412|/***********************************************************************
2413|  2-51. <<< [Text_Box::UnlinkAll] CadPrim::UnlinkAll の実装部 >>>
2414|************************************************************************/
2415|void  Text_Box::UnlinkAll()
2416|{
2417|  CadPrim_Link*  link;
2418|  CadPrim_Link*  link2;
2419|
2420|  for ( link = (CadPrim_Link*)m_Links.first; link != NULL; ) {
2421|    link2 = ListX_Elem_getNextT( link, CadPrim_Link );
2422|    UnlinkToHandle( link->prim, link->iHandle );
2423|    link = link2;
2424|  }
2425|  if ( m_Controler != NULL )
2426|    m_Controler->UnlinkToHandle( this, 1 );
2427|}
2428|
2429|
2430|/***********************************************************************
2431|  2-52. <<< [Text_Box::LinkToControler] CadPrim::LinkToControler の実装部 >>>
2432|************************************************************************/
2433|void  Text_Box::LinkToControler( int iHandle, CadPrim* ctrl )
2434|{
2435|  m_Controler = ctrl;
2436|  m_Controler_id = ctrl->GetID();
2437|}
2438|
2439|
2440|/***********************************************************************
2441|  2-53. <<< [Text_Box::UnlinkToControler] CadPrim::UnlinkToControler の実装部 >>>
2442|************************************************************************/
2443|void  Text_Box::UnlinkToControler( int iHandle, CadPrim* ctrl )
2444|{
2445|  m_Controler = NULL;
2446|}
2447|
2448|
2449|/***********************************************************************
2450|  2-54. <<< [Text_Box::AdjustLinks] CadPrim::AdjustLinks の実装部 >>>
2451|【補足】
2452|・ファイルを開きなおしたときにリンク状態を維持するために、Text_Box::MoveLinks
2453|  を別に呼ぶ必要があります。
2454|************************************************************************/
2455|void  Text_Box::AdjustLinks( ListX* prims )
2456|{
2457|  CadPrim_Link*  link;
2458|
2459|  m_Controler = Undo_Uty_getPrimPtr( prims, m_Controler_id );
2460|
2461|  for ( link = ListX_getFirst( &m_Links, CadPrim_Link );  link != NULL; ) {
2462|    link->prim = Undo_Uty_getPrimPtr( prims, link->prim_id );
2463|
2464|    if ( link->prim == NULL ) {
2465|      CadPrim_Link*  nextLink = ListX_Elem_getNextT( link, CadPrim_Link );
2466|      ListX_removeFree( &m_Links, link );
2467|      link = nextLink;
2468|    }
2469|    else {
2470|      link = ListX_Elem_getNextT( link, CadPrim_Link );
2471|    }
2472|  }
2473|
2474|  for ( ListX_forEach( &m_Links, &link, CadPrim_Link ) ) {
2475|    link->prim->AdjustLinks( prims );
2476|  }
2477|}
2478|
2479| 
2480|/***********************************************************************
2481|  2-55. <<< [Text_Box::GetArrowPoint] 枠と、リンクしているラインとの交点を取得する >>> 
2482|【引数】
2483|  ・int  i;       リンクしているラインが this とリンクしている頂点の番号 (1 or 2)
2484|  ・int  x1, y1;  ラインの先端の座標(Text_Box の中)
2485|  ・int  x2, y2;  ラインの尾の座標(Text_Box の外)
2486|  ・int*  x, y;   (出力)交点の座標
2487|************************************************************************/
2488|void  Text_Box::GetArrowPoint( int i, int x1, int y1, int x2, int y2, int* x, int* y )
2489|{
2490|  RECT  rc;
2491|
2492|  GetBox( &rc );
2493|
2494|  /* ボックスの上辺について */
2495|  if ( y1 > y2 ) {
2496|    *x = ( x1 * (rc.top - y2) + x2 * (y1 - rc.top) ) / (y1 - y2);
2497|    *y = rc.top;
2498|    if ( *x >= rc.left && *x <= rc.right )  return;
2499|  }
2500|
2501|  /* ボックスの左辺について */
2502|  if ( x1 > x2 ) {
2503|    *x = rc.left;
2504|    *y = ( y1 * (rc.left - x2) + y2 * (x1 - rc.left) ) / (x1 - x2);
2505|    if ( *y >= rc.top && *y <= rc.bottom ) {
2506|      if ( m_BoxShape == Text_Box_Parallelogram )
2507|        *x -= (*y - (rc.top + rc.bottom) / 2 ) / 2;
2508|      return;
2509|    }
2510|  }
2511|
2512|  /* ボックスの右辺について */
2513|  if ( x1 < x2 ) {
2514|    *x = rc.right;
2515|    *y = ( y1 * (x2 - rc.right) + y2 * (rc.right - x1) ) / (x2 - x1);
2516|    if ( *y >= rc.top && *y <= rc.bottom ) {
2517|      if ( m_BoxShape == Text_Box_Parallelogram )
2518|        *x -= (*y - (rc.top + rc.bottom) / 2 ) / 2;
2519|      return;
2520|    }
2521|  }
2522|
2523|  /* ボックスの下辺について */
2524|  if ( y1 < y2 ) {
2525|    *x = ( x1 * (y2 - rc.bottom) + x2 * (rc.bottom - y1) ) / (y2 - y1);
2526|    *y = rc.bottom;
2527|    if ( *x >= rc.left && *x <= rc.right )  return;
2528|  }
2529|
2530|  /* ボックスに交わらないとき */
2531|  if ( i == 1 )
2532|    { *x = x1;  *y = y1; }
2533|  else
2534|    { *x = x2;  *y = y2; }
2535|}
2536| 
2537|/***********************************************************************
2538|  2-56. <<< [Text_Box::GetClickedPos] クリックした位置のテキスト位置を返す >>> 
2539|【引数】
2540|  ・int  x, y;     クリック位置(クライアント座標)
2541|  ・int  返り値;   バイト位置
2542|************************************************************************/
2543|int  Text_Box::GetClickedPos( int x, int y, CadPrim_DrawParam* p )
2544|{
2545|  int  iLine;
2546|  char*  pTop;
2547|
2548|  if ( m_bTategaki ) {
2549|    return  0;
2550|  }
2551|  else {
2552|    if ( y <= m_Y + m_10Descent / 10 )  return  0;
2553|    iLine = ( y - m_Top ) / m_BetweenOfLine + 1;
2554|    pTop = StrX_refTopOfLine( m_Text, iLine );
2555|    if ( pTop == NULL )  return  strlen( m_Text );
2556|    else  return  (const char*)pTop - (const char*)m_Text;
2557|  }
2558|}
2559|
2560| 
2561|/***********************************************************************
2562|  2-57. <<< [Text_Box::ChangeAlign] 表示位置を変えずに align を変える >>> 
2563|************************************************************************/
2564|void  Text_Box::ChangeAlign( int align )
2565|{
2566|  int  diff = align - m_BasePos;
2567|
2568|  if ( m_bTategaki ) {
2569|    if ( diff == 1 || diff == -1 ) {
2570|      if ( align + m_BasePos == 1 )
2571|        m_Y += (m_W + 1) / 2 * diff;
2572|      else
2573|        m_Y += m_W / 2 * diff;
2574|    }
2575|    else
2576|      m_Y += m_W * ( diff / 2 );
2577|  }
2578|  else {
2579|    if ( diff == 1 || diff == -1 ) {
2580|      if ( align + m_BasePos == 1 )
2581|        m_CenterX += (m_W + 1) / 2 * diff;
2582|      else
2583|        m_CenterX += m_W / 2 * diff;
2584|    }
2585|    else
2586|      m_CenterX += m_W * ( diff / 2 );
2587|  }
2588|
2589|  m_BasePos = align;
2590|}
2591|
2592|
2593| 
2594|/***********************************************************************
2595|  2-58. <<< [Text_Box::ChangeShape] マージンを変わったように見えない程度に枠の形状を変える >>> 
2596|************************************************************************/
2597|void  Text_Box::ChangeShape( int shape )
2598|{
2599|  const  int  mx[] = { -6, 0, 0, 2, 20, 2 };
2600|  const  int  my[] = { -4, 0, 0, 2, 2, 0 };
2601|
2602|  if ( m_BorderWidth == 0 ) {
2603|    m_BoxMarginX += mx[shape] - mx[0];
2604|    m_BoxMarginY += my[shape] - my[0];
2605|  }
2606|  else {
2607|    m_BoxMarginX += mx[shape] - mx[m_BoxShape];
2608|    m_BoxMarginY += my[shape] - my[m_BoxShape];
2609|  }
2610|  if ( m_BoxMarginX < 0 )  m_BoxMarginX = 0;
2611|  if ( m_BoxMarginY < 0 )  m_BoxMarginY = 0;
2612|  m_BoxShape = shape;
2613|  if ( m_BorderWidth == 0 )  m_BorderWidth = 1;
2614|}
2615|
2616| 
2617|/***********************************************************************
2618|  2-59. <<< [Text_Box::IsNotSetDrawParam] 描画後に決まる属性がまだ決まっていないかどうか >>> 
2619|************************************************************************/
2620|bool  Text_Box::IsNotSetDrawParam()
2621|{
2622|  return  m_10H1 == -1;
2623|}
2624|
2625| 
2626|#endif 
2627| 
2628|/*-------------------------------------------------------------------------*/
2629|/* 3. <<<< ◆ (Text_Editor) インライン・テキストエディタ >>>>  */ 
2630|/*-------------------------------------------------------------------------*/
2631| 
2632|Text_Editor::Text_Editor() 
2633|{
2634|  m_bCaretDisp = true;
2635|}
2636|
2637| 
2638|/***********************************************************************
2639|  3-1. <<< [Text_Editor::Attach] 編集対象のテキストに合わせる >>> 
2640|************************************************************************/
2641|void  Text_Editor::Attach( Text_Box* text )
2642|{
2643|  m_Text = text->m_Text;
2644|  m_CenterX = text->m_CenterX + 1;
2645|  m_Y = text->m_Y + 1;
2646|  m_DiffW = text->m_DiffW;
2647|  m_W = text->m_W;
2648|  m_10H = text->m_10H;
2649|  m_10H1 = text->m_10H1;
2650|  m_10Descent = text->m_10Descent;
2651|  m_Top = text->m_Top;
2652|  m_BetweenOfLine = text->m_BetweenOfLine;
2653|  m_RotateDegree = text->m_RotateDegree;
2654|  m_Color = text->m_Color;
2655|  m_Font = text->m_Font;
2656|  m_Size = text->m_Size;
2657|  m_bBold = text->m_bBold;
2658|  m_bItalic = text->m_bItalic;
2659|  m_BasePos = text->m_BasePos;
2660|  m_bTategaki = text->m_bTategaki;
2661|
2662|  m_BoxShape = text->m_BoxShape;
2663|  m_BoxMarginX = text->m_BoxMarginX;
2664|  m_BoxMarginY = text->m_BoxMarginY;
2665|  m_BorderWidth = text->m_BorderWidth;
2666|  m_BorderColor = text->m_BorderColor;
2667|  m_FillColor = text->m_FillColor;
2668|  m_FillNTrans = text->m_FillNTrans;
2669|}
2670| 
2671|/***********************************************************************
2672|  3-2. <<< [Text_Editor::Draw] CadPrim::Draw の実装部 >>> 
2673|************************************************************************/
2674|void  Text_Editor::Draw( CDC* dc, CadPrim_DrawParam* p )
2675|{
2676|  /* テキストを描く */
2677|  {
2678|    int  i = m_BorderWidth;   m_BorderWidth = 0;
2679|    Text_Box::Draw( dc, p );
2680|    m_BorderWidth = i;
2681|  }
2682|
2683|
2684|  /* 編集中を示す外枠を描く */
2685|  {
2686|    CPen     whitePen( PS_SOLID, 1, RGB(0x80,0x80,0x80) );
2687|    CPen     blackPen( PS_SOLID, 1, RGB(0x20,0x20,0x20) );
2688|    CPen*    oldPen;
2689|    RECT     box;
2690|
2691|    GetBox( &box );
2692|
2693|
2694|    /* いちばん外の枠を描く */
2695|    dc->MoveTo( box.left, box.bottom - 2 );
2696|
2697|    oldPen = dc->SelectObject( &blackPen );
2698|    dc->LineTo( box.left, box.top );
2699|    dc->LineTo( box.right - 2, box.top );
2700|
2701|    dc->SelectObject( &whitePen );
2702|    dc->LineTo( box.right - 2, box.bottom - 2 );
2703|    dc->LineTo( box.left, box.bottom - 2 );
2704|
2705|
2706|    /* 1つ内の枠を描く */
2707|    dc->MoveTo( box.left + 1, box.bottom - 3 );
2708|
2709|    oldPen = dc->SelectObject( &blackPen );
2710|    dc->LineTo( box.left + 1, box.top + 1 );
2711|    dc->LineTo( box.right - 3, box.top + 1 );
2712|
2713|    dc->SelectObject( &whitePen );
2714|    dc->LineTo( box.right - 3, box.bottom - 3 );
2715|    dc->LineTo( box.left + 1, box.bottom - 3 );
2716|
2717|
2718|    /* 1つ外の枠を描く */
2719|    dc->MoveTo( box.left - 1, box.bottom - 1 );
2720|
2721|    oldPen = dc->SelectObject( &blackPen );
2722|    dc->LineTo( box.left - 1, box.top - 1 );
2723|    dc->LineTo( box.right - 1, box.top - 1 );
2724|
2725|    dc->SelectObject( &whitePen );
2726|    dc->LineTo( box.right - 1, box.bottom - 1 );
2727|    dc->LineTo( box.left - 1, box.bottom - 1 );
2728|
2729|    m_bCaretDisp = true;
2730|    DrawCaretXor( dc, p );
2731|
2732|    dc->SelectObject( oldPen );
2733|  }
2734|}
2735|
2736|
2737| 
2738|/***********************************************************************
2739|  3-3. <<< [Text_Editor::DrawCaretXor] キャレット(テキスト入力位置)を反転描画する >>> 
2740|************************************************************************/
2741|void  Text_Editor::DrawCaretXor( CDC* dc, CadPrim_DrawParam* p )
2742|{
2743|  int     gx1, gy1, gx2, gy2;
2744|
2745|  GetGXYByIndex( dc, m_CaretStart, &gx1, &gy1 );
2746|  GetGXYByIndex( dc, m_CaretEnd, &gx2, &gy2 );
2747|
2748|  /* キャレットを反転する */
2749|  {
2750|    CPen  whitePen( PS_SOLID, 1, RGB(0xFF,0xFF,0xFF) );
2751|    int   height;
2752|    int   x, y;
2753|    int   y_over;
2754|
2755|    x = m_CenterX + gx2;
2756|    height = m_Y - m_Top + m_10Descent / 10 + 2;
2757|    y_over = m_Top - 1 + gy2 + height;
2758|
2759|    for ( y = m_Top - 1 + gy2;  y < y_over;  y ++ ) {
2760|      dc->SetPixel( x, y, dc->GetPixel( x, y ) ^ 0x00C0C0C0 );
2761|      dc->SetPixel( x+1, y, dc->GetPixel( x+1, y ) ^ 0x00C0C0C0 );
2762|    }
2763|  }
2764|}
2765|
2766|
2767| 
2768|/***********************************************************************
2769|  3-4. <<< [Text_Editor::OnBlinkTiming] 点滅するタイミングで行う処理 >>> 
2770|【補足】
2771|・CreateThread で、次のスレッド関数を実行します。
2772|  blinkThread()
2773|  {
2774|    for (;;) {
2775|      Sleep( GetCaretBlinkTime() );  // 点滅する時間だけ待つ API
2776|      editor->OnBlinkTiming();  // 本関数
2777|    }
2778|  }
2779|************************************************************************/
2780|void  Text_Editor::OnBlinkTiming( CDC* dc, CadPrim_DrawParam* p )
2781|{
2782|  m_bCaretDisp = ! m_bCaretDisp;
2783|
2784|  if ( m_bCaretDisp ) {
2785|    static  int  i = 0;
2786|    static  int  j = 0;
2787|
2788|    i++;  if ( i == m_Text.GetLength()+1 ) { i = 0;
2789|      j++;  if ( j == m_Text.GetLength()+1 ) j = 0;
2790|    }
2791|
2792|    m_CaretEnd = i;
2793|    m_CaretStart = j;
2794|    Draw( dc, p );
2795|  }
2796|
2797|  DrawCaretXor( dc, p );
2798|}
2799|
2800|
2801| 
2802|