Пример #1
0
UcciCommEnum BusyLine(UcciCommStruct &UcciComm, bool bDebug) {
  char szLineStr[SE_LINE_INPUT_MAX_CHAR];
  char *lp;
  if (pipeInputReadLine(szLineStr)) {
    if (bDebug) {
		//printf("info busyline [%s]\n", szLineStr);
		//fflush(stdout);
		pipeOutputWrite("info busyline [%s]\n", szLineStr);
    }
    // "BusyLine"只能接收"isready"、"ponderhit"和"stop"这三条指令
    if (false) {
    } else if (StrEqv(szLineStr, "isready")) {
      return UCCI_COMM_ISREADY;
    } else if (StrEqv(szLineStr, "ponderhit draw")) {
      return UCCI_COMM_PONDERHIT_DRAW;
    // 注意:必须首先判断"ponderhit draw",再判断"ponderhit"
    } else if (StrEqv(szLineStr, "ponderhit")) {
      return UCCI_COMM_PONDERHIT;
    } else if (StrEqv(szLineStr, "stop")) {
      return UCCI_COMM_STOP;
    } else if (StrEqv(szLineStr, "quit")) {
      return UCCI_COMM_QUIT;
    } else {
      lp = szLineStr;
      if (StrEqvSkip(lp, "probe ")) {
        return ParsePos(UcciComm, lp) ? UCCI_COMM_PROBE : UCCI_COMM_UNKNOWN;
      } else {
        return UCCI_COMM_UNKNOWN;
      }
    }
  } else {
    return UCCI_COMM_UNKNOWN;
  }
}
Пример #2
0
UcciCommEnum IdleLine(UcciCommStruct &UcciComm, bool bDebug) {
  char szLineStr[SE_LINE_INPUT_MAX_CHAR];
  char *lp;
  int i;
  bool bGoTime;

  while (!pipeInputReadLine(szLineStr)) {
    Idle();
  }
  lp = szLineStr;
  if (bDebug) {
	  //printf("info idleline [%s]\n", lp);
	  //fflush(stdout);
	  pipeOutputWrite("info idleline [%s]\n", lp);
  }
  if (false) {
  // "IdleLine()"是最复杂的UCCI指令解释器,大多数的UCCI指令都由它来解释,包括:

  // 1. "isready"指令
  } else if (StrEqv(lp, "isready")) {
    return UCCI_COMM_ISREADY;

  // 2. "setoption <option> [<arguments>]"指令
  } else if (StrEqvSkip(lp, "setoption ")) {
    if (false) {

    // (1) "batch"选项
    } else if (StrEqvSkip(lp, "batch ")) {
      UcciComm.Option = UCCI_OPTION_BATCH;
      if (StrEqv(lp, "on")) {
        UcciComm.bCheck = true;
      } else if (StrEqv(lp, "true")) {
        UcciComm.bCheck = true;
      } else {
        UcciComm.bCheck = false;
      } // 由于"batch"选项默认是关闭的,所以只有设定"on"或"true"时才打开,下同

    // (2) "debug"选项
    } else if (StrEqvSkip(lp, "debug ")) {
      UcciComm.Option = UCCI_OPTION_DEBUG;
      if (StrEqv(lp, "on")) {
        UcciComm.bCheck = true;
      } else if (StrEqv(lp, "true")) {
        UcciComm.bCheck = true;
      } else {
        UcciComm.bCheck = false;
      }

    // (3) "ponder"选项
    } else if (StrEqvSkip(lp, "ponder ")) {
      UcciComm.Option = UCCI_OPTION_PONDER;
      if (StrEqv(lp, "on")) {
        UcciComm.bCheck = true;
      } else if (StrEqv(lp, "true")) {
        UcciComm.bCheck = true;
      } else {
        UcciComm.bCheck = false;
      }

    // (4-1) "alwayscheck"选项
    } else if (StrEqvSkip(lp, "alwayscheck ")) {
      UcciComm.Option = UCCI_OPTION_ALWAYSCHECK;
      if (StrEqv(lp, "on")) {
        UcciComm.bCheck = true;
      } else if (StrEqv(lp, "true")) {
        UcciComm.bCheck = true;
      } else {
        UcciComm.bCheck = false;
      }

    // (4-2) "usehash"选项
    } else if (StrEqvSkip(lp, "usehash ")) {
      UcciComm.Option = UCCI_OPTION_USEHASH;
      if (StrEqv(lp, "off")) {
        UcciComm.bCheck = false;
      } else if (StrEqv(lp, "false")) {
        UcciComm.bCheck = false;
      } else {
        UcciComm.bCheck = true;
      }

    // (5) "usebook"选项
    } else if (StrEqvSkip(lp, "usebook ")) {
      UcciComm.Option = UCCI_OPTION_USEBOOK;
      if (StrEqv(lp, "off")) {
        UcciComm.bCheck = false;
      } else if (StrEqv(lp, "false")) {
        UcciComm.bCheck = false;
      } else {
        UcciComm.bCheck = true;
      }

    // (6) "useegtb"选项
    } else if (StrEqvSkip(lp, "useegtb ")) {
      UcciComm.Option = UCCI_OPTION_USEEGTB;
      if (StrEqv(lp, "off")) {
        UcciComm.bCheck = false;
      } else if (StrEqv(lp, "false")) {
        UcciComm.bCheck = false;
      } else {
        UcciComm.bCheck = true;
      }

    // (7) "bookfiles"选项
    } else if (StrEqvSkip(lp, "bookfiles ")) {
      UcciComm.Option = UCCI_OPTION_BOOKFILES;
      UcciComm.szOption = lp;

    // (8) "egtbpaths"选项
    } else if (StrEqvSkip(lp, "egtbpaths ")) {
      UcciComm.Option = UCCI_OPTION_EGTBPATHS;
      UcciComm.szOption = lp;

    // (9) "evalapi"选项
    } else if (StrEqvSkip(lp, "evalapi ")) {
      UcciComm.Option = UCCI_OPTION_EVALAPI;
      UcciComm.szOption = lp;

    // (10) "hashsize"选项
    } else if (StrEqvSkip(lp, "hashsize ")) {
      UcciComm.Option = UCCI_OPTION_HASHSIZE;
      UcciComm.nSpin = Str2Digit(lp, 0, 1024);

    // (11) "threads"选项
    } else if (StrEqvSkip(lp, "threads ")) {
      UcciComm.Option = UCCI_OPTION_THREADS;
      UcciComm.nSpin = Str2Digit(lp, 0, 32);

    // (12) "promotion"选项
    } else if (StrEqvSkip(lp, "promotion ")) {
      UcciComm.Option = UCCI_OPTION_PROMOTION;
      if (StrEqv(lp, "on")) {
        UcciComm.bCheck = true;
      } else if (StrEqv(lp, "true")) {
        UcciComm.bCheck = true;
      } else {
        UcciComm.bCheck = false;
      }

    // (13) "idle"选项
    } else if (StrEqvSkip(lp, "idle ")) {
      UcciComm.Option = UCCI_OPTION_IDLE;
      if (false) {
      } else if (StrEqv(lp, "none")) {
        UcciComm.Grade = UCCI_GRADE_NONE;
      } else if (StrEqv(lp, "small")) {
        UcciComm.Grade = UCCI_GRADE_SMALL;
      } else if (StrEqv(lp, "medium")) {
        UcciComm.Grade = UCCI_GRADE_MEDIUM;
      } else if (StrEqv(lp, "large")) {
        UcciComm.Grade = UCCI_GRADE_LARGE;
      } else {
        UcciComm.Grade = UCCI_GRADE_NONE;
      }

    // (14) "pruning"选项
    } else if (StrEqvSkip(lp, "pruning ")) {
      UcciComm.Option = UCCI_OPTION_PRUNING;
      if (false) {
      } else if (StrEqv(lp, "none")) {
        UcciComm.Grade = UCCI_GRADE_NONE;
      } else if (StrEqv(lp, "small")) {
        UcciComm.Grade = UCCI_GRADE_SMALL;
      } else if (StrEqv(lp, "medium")) {
        UcciComm.Grade = UCCI_GRADE_MEDIUM;
      } else if (StrEqv(lp, "large")) {
        UcciComm.Grade = UCCI_GRADE_LARGE;
      } else {
        UcciComm.Grade = UCCI_GRADE_LARGE;
      }

    // (15) "knowledge"选项
    } else if (StrEqvSkip(lp, "knowledge ")) {
      UcciComm.Option = UCCI_OPTION_KNOWLEDGE;
      if (false) {
      } else if (StrEqv(lp, "none")) {
        UcciComm.Grade = UCCI_GRADE_NONE;
      } else if (StrEqv(lp, "small")) {
        UcciComm.Grade = UCCI_GRADE_SMALL;
      } else if (StrEqv(lp, "medium")) {
        UcciComm.Grade = UCCI_GRADE_MEDIUM;
      } else if (StrEqv(lp, "large")) {
        UcciComm.Grade = UCCI_GRADE_LARGE;
      } else {
        UcciComm.Grade = UCCI_GRADE_LARGE;
      }

    // (16) "randomness"选项
    } else if (StrEqvSkip(lp, "randomness ")) {
      UcciComm.Option = UCCI_OPTION_RANDOMNESS;
      if (false) {
      } else if (StrEqv(lp, "none")) {
        UcciComm.Grade = UCCI_GRADE_NONE;
      } else if (StrEqv(lp, "small")) {
        UcciComm.Grade = UCCI_GRADE_SMALL;
      } else if (StrEqv(lp, "medium")) {
        UcciComm.Grade = UCCI_GRADE_MEDIUM;
      } else if (StrEqv(lp, "large")) {
        UcciComm.Grade = UCCI_GRADE_LARGE;
      } else {
        UcciComm.Grade = UCCI_GRADE_NONE;
      }

    // (17) "style"选项
    } else if (StrEqvSkip(lp, "style ")) {
      UcciComm.Option = UCCI_OPTION_STYLE;
      if (false) {
      } else if (StrEqv(lp, "solid")) {
        UcciComm.Style = UCCI_STYLE_SOLID;
      } else if (StrEqv(lp, "normal")) {
        UcciComm.Style = UCCI_STYLE_NORMAL;
      } else if (StrEqv(lp, "risky")) {
        UcciComm.Style = UCCI_STYLE_RISKY;
      } else {
        UcciComm.Style = UCCI_STYLE_NORMAL;
      }

    // (18) "newgame"选项
    } else if (StrEqv(lp, "newgame")) {
      UcciComm.Option = UCCI_OPTION_NEWGAME;

    // (19) 无法识别的选项,有扩充的余地
    } else {
      UcciComm.Option = UCCI_OPTION_UNKNOWN;
    }
    return UCCI_COMM_SETOPTION;

  // 3. "position {<special_position> | fen <fen_string>} [moves <move_list>]"指令
  } else if (StrEqvSkip(lp, "position ")) {
    return ParsePos(UcciComm, lp) ? UCCI_COMM_POSITION : UCCI_COMM_UNKNOWN;

  // 4. "banmoves <move_list>"指令,处理起来和"position ... moves ..."是一样的
  } else if (StrEqvSkip(lp, "banmoves ")) {
    UcciComm.nBanMoveNum = MIN((int) (strlen(lp) + 1) / 5, MAX_MOVE_NUM);
    for (i = 0; i < UcciComm.nBanMoveNum; i ++) {
      dwCoordList[i] = *(uint32_t *) lp;
      lp += sizeof(uint32_t) + 1;
    }
    UcciComm.lpdwBanMovesCoord = dwCoordList;
    return UCCI_COMM_BANMOVES;

  // 5. "go [ponder | draw] <mode>"指令
  } else if (StrEqvSkip(lp, "go ")) {
    UcciComm.bPonder = UcciComm.bDraw = false;
    // 首先判断到底是"go"、"go ponder"还是"go draw"
    if (StrEqvSkip(lp, "ponder ")) {
      UcciComm.bPonder = true;
    } else if (StrEqvSkip(lp, "draw ")) {
      UcciComm.bDraw = true;
    }
    // 然后判断思考模式
    bGoTime = false;
    if (false) {
    } else if (StrEqvSkip(lp, "depth ")) {
      UcciComm.Go = UCCI_GO_DEPTH;
      UcciComm.nDepth = Str2Digit(lp, 0, UCCI_MAX_DEPTH);
    } else if (StrEqvSkip(lp, "nodes ")) {
      UcciComm.Go = UCCI_GO_NODES;
      UcciComm.nDepth = Str2Digit(lp, 0, 2000000000);
    } else if (StrEqvSkip(lp, "time ")) {
      UcciComm.nTime = Str2Digit(lp, 0, 2000000000);
      bGoTime = true;
    // 如果没有说明是固定深度还是设定时限,就固定深度为"UCCI_MAX_DEPTH"
    } else {
      UcciComm.Go = UCCI_GO_DEPTH;
      UcciComm.nDepth = UCCI_MAX_DEPTH;
    }
    // 如果是设定时限,就要判断是时段制还是加时制
    if (bGoTime) {
      if (false) {
      } else if (StrScanSkip(lp, " movestogo ")) {
        UcciComm.Go = UCCI_GO_TIME_MOVESTOGO;
        UcciComm.nMovesToGo = Str2Digit(lp, 1, 999);
      } else if (StrScanSkip(lp, " increment ")) {
        UcciComm.Go = UCCI_GO_TIME_INCREMENT;
        UcciComm.nIncrement = Str2Digit(lp, 0, 999999);
      // 如果没有说明是时段制还是加时制,就设定为步数是1的时段制
      } else {
        UcciComm.Go = UCCI_GO_TIME_MOVESTOGO;
        UcciComm.nMovesToGo = 1;
      }
    }
    return UCCI_COMM_GO;

  // 6. "stop"指令
  } else if (StrEqv(lp, "stop")) {
    return UCCI_COMM_STOP;

  // 7. "probe {<special_position> | fen <fen_string>} [moves <move_list>]"指令
  } else if (StrEqvSkip(lp, "probe ")) {
    return ParsePos(UcciComm, lp) ? UCCI_COMM_PROBE : UCCI_COMM_UNKNOWN;

  // 8. "quit"指令
  } else if (StrEqv(lp, "quit")) {
    return UCCI_COMM_QUIT;

  // 9. 无法识别的指令
  } else {
    return UCCI_COMM_UNKNOWN;
  }
}
Пример #3
0
int RazdsParser::ParseSYMB( FILE *fp, RuleHash *pHash )
{
    int ret;

    int bitmap_width;
    char pbm_line[200]; // max bitmap width...
    bool inserted = FALSE;
    Rule *symb = (Rule*) calloc( 1, sizeof(Rule) );
    plib->pAlloc->Add( symb );
    Rule *symbtmp = NULL;

    symb->exposition.SXPO = new wxString;
    symb->bitmap.SBTM = new wxString;
    wxString SVCT;
    wxString SCRF;

    sscanf( pBuf + 11, "%d", &symb->RCID );

    ret = ReadS52Line( pBuf, NEWLN, 0, fp );

    do {
        MOD_REC ( SYMD ) {
            strncpy( symb->name.SYNM, pBuf + 9, 8 );
            symb->definition.SYDF = pBuf[17];
            ParsePos( &symb->pos.symb, pBuf + 18, FALSE );
        }

        MOD_REC ( SXPO ) symb->exposition.SXPO->Append( wxString( pBuf + 9, wxConvUTF8 ) );

        MOD_REC ( SBTM ) {
            bitmap_width = symb->pos.symb.bnbox_w.SYHL;
            if( bitmap_width > 200 ) wxLogMessage( _T ( "ParseSymb....bitmap too wide." ) );
#ifdef __WXOSX__  //  bitmap_width > pbm_line ???
            // buffer overflow attack possible so changed to strlcpy()
            strlcpy( pbm_line, pBuf + 9, bitmap_width );
#else
            strncpy( pbm_line, pBuf + 9, bitmap_width );
#endif
            pbm_line[bitmap_width] = 0;
            symb->bitmap.SBTM->Append( wxString( pbm_line, wxConvUTF8 ) );
        }

        MOD_REC ( SCRF ) SCRF.Append( wxString( pBuf + 9, wxConvUTF8 ) ); // CIDX+CTOK

        MOD_REC ( SVCT ) SVCT.Append( wxString( pBuf + 9, wxConvUTF8 ) );

        if( ( 0 == strncmp( "****", pBuf, 4 ) ) || ( ret == -1 ) ) {
            symb->vector.SVCT = (char *) calloc( SVCT.Len() + 1, 1 );
            strncpy( symb->vector.SVCT, SVCT.mb_str(), SVCT.Len() );

            symb->colRef.SCRF = (char *) calloc( SCRF.Len() + 1, 1 );
            strncpy( symb->colRef.SCRF, SCRF.mb_str(), SCRF.Len() );

            // Create a key
            char keyt[20];
            strncpy( keyt, symb->name.SYNM, 8 );
            keyt[8] = 0;
            wxString key( keyt, wxConvUTF8 );

            symbtmp = ( *pHash )[key];

            if( NULL == symbtmp ) // not there, so....
            ( *pHash )[key] = symb; // insert in hash table

            else // already something here with same key...
            {
                if( symb->name.SYNM != symbtmp->name.SYNM ) // if the pattern names are not identical
                        {
                    ( *pHash )[key] = symb; // replace the pattern
                    plib->DestroyRuleNode( symbtmp ); // remember to free to replaced node
                    // the node itself is destroyed as part of pAlloc
                }
            }
            inserted = TRUE;
        }
        ret = ReadS52Line( pBuf, NEWLN, 0, fp );
        ChopS52Line( pBuf, '\0' );

    } while( inserted == FALSE );

    return ret;
}
Пример #4
0
int RazdsParser::ParsePATT( FILE *fp )
{
    int ret;

    int bitmap_width;
    char pbm_line[200]; // max bitmap width...
    char strk[20];

    bool inserted = FALSE;
    Rule *pattmp = NULL;
    Rule *patt = (Rule*) calloc( 1, sizeof(Rule) );
    plib->pAlloc->Add( patt );

    patt->exposition.PXPO = new wxString;
    patt->bitmap.PBTM = new wxString;
    wxString PVCT;
    wxString PCRF;

    sscanf( pBuf + 11, "%d", &patt->RCID );
#ifdef __WXOSX__
    ReadS52Line( pBuf, NEWLN, 0, fp );
#else
    ret = ReadS52Line( pBuf, NEWLN, 0, fp );
#endif
    do {
        MOD_REC ( PATD ) {
            strncpy( patt->name.PANM, pBuf + 9, 8 );
            patt->definition.PADF = pBuf[17];
            patt->fillType.PATP = pBuf[18]; // first character 'S' or 'L', for staggered or linear
            patt->spacing.PASP = pBuf[21];
            ParsePos( &patt->pos.patt, pBuf + 24, TRUE );
        }

        MOD_REC ( PXPO ) patt->exposition.PXPO->Append( wxString( pBuf + 9, wxConvUTF8 ) );
        MOD_REC ( PCRF ) PCRF.Append( wxString( pBuf + 9, wxConvUTF8 ) ); // CIDX+CTOK
        MOD_REC ( PVCT ) PVCT.Append( wxString( pBuf + 9, wxConvUTF8 ) );

        MOD_REC ( PBTM ) {
            bitmap_width = patt->pos.patt.bnbox_w.SYHL;
            strncpy( pbm_line, pBuf + 9, bitmap_width );
            pbm_line[bitmap_width] = 0;
            patt->bitmap.SBTM->Append( wxString( pbm_line, wxConvUTF8 ) );
        }

        MOD_REC ( **** ) {

            patt->vector.PVCT = (char *) calloc( PVCT.Len() + 1, 1 );
            strncpy( patt->vector.PVCT, PVCT.mb_str(), PVCT.Len() );

            patt->colRef.PCRF = (char *) calloc( PCRF.Len() + 1, 1 );
            strncpy( patt->colRef.PCRF, PCRF.mb_str(), PCRF.Len() );

            // check if key already there
            strncpy( strk, patt->name.PANM, 8 );
            strk[8] = 0;
            wxString key( strk, wxConvUTF8 );

            pattmp = ( *plib->_patt_sym )[key];

            if( NULL == pattmp ) // not there, so....
            ( *plib->_patt_sym )[key] = patt; // insert in hash table

            else // already something here with same key...
            {
                if( patt->name.PANM != pattmp->name.PANM ) // if the pattern names are not identical
                        {
                    ( *plib->_patt_sym )[key] = patt; // replace the pattern
                    plib->DestroyPatternRuleNode( pattmp ); // remember to free to replaced node
                    // the node itself is destroyed as part of pAlloc
                }

            }

            inserted = TRUE;
        }
        ret = ReadS52Line( pBuf, NEWLN, 0, fp );
        ChopS52Line( pBuf, '\0' );

    } while( inserted == FALSE );

    return ret;
}
Пример #5
0
int RazdsParser::ParseLNST( FILE *fp )
{
    int ret;

    char strk[20];

    bool inserted = FALSE;
    Rule *lnstmp = NULL;
    Rule *lnst = (Rule*) calloc( 1, sizeof(Rule) );
    plib->pAlloc->Add( lnst );

    lnst->exposition.LXPO = new wxString;
    wxString LVCT;
    wxString LCRF;

    sscanf( pBuf + 11, "%d", &lnst->RCID );
#ifdef __WXOSX__
    ReadS52Line( pBuf, NEWLN, 0, fp );
#else
    ret = ReadS52Line( pBuf, NEWLN, 0, fp );
#endif
    do {
        MOD_REC ( LIND ) {
            strncpy( lnst->name.LINM, pBuf + 9, 8 ); // could be empty!
            ParsePos( &lnst->pos.line, pBuf + 17, FALSE );
        }

        MOD_REC ( LXPO ) lnst->exposition.LXPO->Append( wxString( pBuf + 9, wxConvUTF8 ) );
        MOD_REC ( LCRF ) LCRF.Append( wxString( pBuf + 9, wxConvUTF8 ) ); // CIDX + CTOK
        MOD_REC ( LVCT ) LVCT.Append( wxString( pBuf + 9, wxConvUTF8 ) );
        MOD_REC ( **** ) {

            lnst->vector.LVCT = (char *) calloc( LVCT.Len() + 1, 1 );
            strncpy( lnst->vector.LVCT, LVCT.mb_str(), LVCT.Len() );

            lnst->colRef.LCRF = (char *) calloc( LCRF.Len() + 1, 1 );
            strncpy( lnst->colRef.LCRF, LCRF.mb_str(), LCRF.Len() );

            // check if key already there
            strncpy( strk, lnst->name.LINM, 8 );
            strk[8] = 0;
            wxString key( strk, wxConvUTF8 );

            //wxString key((lnst->name.LINM), 8);
            lnstmp = ( *plib->_line_sym )[key];

            // insert in Hash Table
            if( NULL == lnstmp ) ( *plib->_line_sym )[key] = lnst;
            else
                if( lnst->name.LINM != lnstmp->name.LINM ) ( *plib->_line_sym )[key] = lnst;
                else
                    assert( 0 );
            // key must be unique --should not reach this

            inserted = TRUE;
        }
        ret = ReadS52Line( pBuf, NEWLN, 0, fp );
        ChopS52Line( pBuf, '\0' );
    } while( inserted == FALSE );

    return ret;
}
Пример #6
0
void ReadCategoryXML(xmlNode * a_node)
{
	xmlNode *cur_node=NULL;

	for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
		if (cur_node->type==XML_ELEMENT_NODE){
			//<Page>
			if(!xmlStrcasecmp(cur_node->name,(xmlChar*)"Page")){
				if(numpage < MAX_ENC_PAGES-1){
					numpage++;
					numtext=0;
					numimage=0;
					x=2;
					y=2;
					ParsePage(cur_node->properties);
				} else {
					LOG_ERROR("Too many Enc Pages, limit of %d hit", MAX_ENC_PAGES);
					return;
				}
			}

			//<Size>
			if(!xmlStrcasecmp(cur_node->name,(xmlChar*)"Size"))
			{
				if (cur_node->children != NULL)
					size = (xmlStrcasecmp ((xmlChar*)"Big", cur_node->children->content) == 0) ? 1 : 0;
			}

			//<Color>
			if(!xmlStrcasecmp(cur_node->name,(xmlChar*)"Color")){
				ParseColor(cur_node->properties);
				if (cur_node->children != NULL)
					GetColorFromName (cur_node->children->content);
			}

			//<Text>
			if(!xmlStrcasecmp(cur_node->name,(xmlChar*)"Text")){
				_Text *T=(_Text*)malloc(sizeof(_Text));
				_Text *t=&Page[numpage].T;
				T->Next=NULL;
				ParseText(cur_node->properties);
				T->x=x;
				T->y=y;
				T->size=size;
				T->r=r; T->g=g; T->b=b;
				T->text=NULL;
				T->ref=NULL;
				lastextlen = 0;
				if (cur_node->children != NULL)
				{
					MY_XMLSTRCPY (&T->text, (char*)cur_node->children->content);
					lastextlen = strlen (T->text) * ((T->size) ? 11 : 8);
					x += lastextlen;
				}
				while (t->Next != NULL)
					t = t->Next;
				t->Next = T;
			}

			//<nl>
			if(!xmlStrcasecmp(cur_node->name,(xmlChar*)"nl")){
				x=2;
				y+=(size)?18:15;
			}
			
			//<nlkx>
			if(!xmlStrcasecmp(cur_node->name,(xmlChar*)"nlkx")){
				y+=(size)?18:15;
				x-=lastextlen;
			}

			//<Image>
			if(!xmlStrcasecmp(cur_node->name,(xmlChar*)"image")){
				_Image *I=(_Image*)malloc(sizeof(_Image));
				_Image *i=&Page[numpage].I;
				xposupdate=1; yposupdate=1;
				ParseImage(cur_node->properties);
				I->mouseover=mouseover;
				mouseover=0;
			
				while(i->Next!=NULL)i=i->Next;
				I->id=id;
				I->Next=NULL;
				if(!I->mouseover){
					I->x=x;
					I->y=y;
					I->xend=x+xend;
					I->yend=y+yend;
					if(xposupdate)
						x+=xend;
					if(yposupdate)
						y+=yend-((size)?18:15);
					
				}else{
					I->x=i->x;
					I->y=i->y;
					I->xend=i->xend;
					I->yend=i->yend;
				}
				I->u=u;
				I->v=v;
				I->uend=uend;
				I->vend=vend;
				i->Next=I;
				numimage++;
			}

			//<sImage>
			if(!xmlStrcasecmp(cur_node->name,(xmlChar*)"simage")){
				_Image *I=(_Image*)malloc(sizeof(_Image));
				_Image *i=&Page[numpage].I;
				int picsperrow,xtile,ytile;
				float ftsize;
				xposupdate=1; yposupdate=1;
				ParseSimage(cur_node->properties);

				picsperrow=isize/tsize;
				xtile=tid%picsperrow;
				ytile=tid/picsperrow;
				ftsize=(float)tsize/isize;
#ifdef	NEW_TEXTURES
				u = ftsize * xtile;
				v = ftsize * ytile;
				uend = u + ftsize;
				vend = v + ftsize;
#else	/* NEW_TEXTURES */
				u=ftsize*xtile;
				v=-ftsize*ytile;
				uend=u+ftsize;
				vend=v-ftsize;
#endif	/* NEW_TEXTURES */
				I->mouseover=mouseover;
				mouseover=0;
				
				while(i->Next!=NULL)i=i->Next;
				I->id=id;
				I->Next=NULL;
				if(!I->mouseover){
					I->x=x;
					I->y=y;
					I->xend=x+(tsize*((float)ssize/100));
					I->yend=y+(tsize*((float)ssize/100));
					if(xposupdate)
						x+=(tsize*((float)ssize/100));
					if(yposupdate)
						y+=(tsize*((float)ssize/100))-((size)?18:15);
				}else{
					I->x=i->x;
					I->y=i->y;
					I->xend=i->xend;
					I->yend=i->yend;
				}
				I->u=u;
				I->v=v;
				I->uend=uend;
				I->vend=vend;
				i->Next=I;
				
				numimage++;
			}

			//<ddsImage>
			if(!xmlStrcasecmp(cur_node->name,(xmlChar*)"ddsimage")){
				_Image *I=(_Image*)malloc(sizeof(_Image));
				_Image *i=&Page[numpage].I;
				int picsperrow,xtile,ytile;
				float ftsize;
				xposupdate=1; yposupdate=1;
				ParseSimage(cur_node->properties);
				if(size==99)
					size=99;

				picsperrow=isize/tsize;
				xtile=tid%picsperrow;
				ytile=tid/picsperrow;
				ftsize=(float)tsize/isize;
				u=ftsize*xtile;
				v=ftsize*ytile;
				uend=u+ftsize;
				vend=v+ftsize;
				I->mouseover=mouseover;
				mouseover=0;

				while(i->Next!=NULL)i=i->Next;
					I->id=id;
				I->Next=NULL;
				if(!I->mouseover){
					I->x=x;
					I->y=y;
					I->xend=x+(tsize*((float)ssize/100));
					I->yend=y+(tsize*((float)ssize/100));
					if(xposupdate)
						x+=(tsize*((float)ssize/100));
					if(yposupdate)
						y+=(tsize*((float)ssize/100))-((size)?18:15);
				}else{
					I->x=i->x;
					I->y=i->y;
					I->xend=i->xend;
					I->yend=i->yend;
				}
				I->u=u;
				I->v=v;
				I->uend=uend;
				I->vend=vend;
				i->Next=I;

				numimage++;
			}

			//<Pos>
			if(!xmlStrcasecmp(cur_node->name,(xmlChar*)"pos")){
				ParsePos(cur_node->properties);
			}

			//<link>
			if(!xmlStrcasecmp(cur_node->name,(xmlChar*)"link")){
				_Text *T=(_Text*)malloc(sizeof(_Text));
				_Text *t=&Page[numpage].T;
				ParseLink(cur_node->properties);
				T->Next=NULL;
				T->x=x;
				T->y=y;
				T->size=size;
				T->r=r; T->g=g; T->b=b;
				T->text=NULL;
				T->ref=NULL;
				MY_XMLSTRCPY(&T->text, s);
				MY_XMLSTRCPY(&T->ref, ss);
				while(t->Next!=NULL)t=t->Next;
				t->Next=T;
				x+=strlen(T->text)*((T->size)?11:8);
				lastextlen=strlen(T->text)*((T->size)?11:8);
#ifdef ENCYCL_NAVIGATION
				save_raw_page_link(T->ref, T->text, numpage);
#endif
			}
			// See if this is the new maximum length.
			if(Page[numpage].max_y < y)
			{
				Page[numpage].max_y = y;
			}
		}

		ReadCategoryXML(cur_node->children);
	}
}