001 #include "Utils.HC"; 002 #include "RuleSet.HC"; 003 #include "FileBMP.HC"; 004 U0 CalcBezier(CD3I32 *point,CD3I32 *l,CD3I32 *cent,CD3I32 *r) { 005 point->x=2.*cent->x-l->x/2.-r->x/2.; 006 point->y=2.*cent->y-l->y/2.-r->y/2.; 007 } 008 //Returns maximum y 009 F64 GrPreciseBezier(CDC *dc,CD3I32 *ctrls,F64 *highest_x_pos=NULL) { 010 F64 x=ctrls[2].x,y=ctrls[2].y,x2,y2,step; 011 F64 max_y=y; 012 F64 max_x=x; 013 for(step=1/100.;step<=1;step+=1./100.) { 014 x2=ctrls[0].x*step`2+ctrls[1].x*2*step*(1-step)+ctrls[2].x*(1-step)`2; 015 y2=ctrls[0].y*step`2+ctrls[1].y*2*step*(1-step)+ctrls[2].y*(1-step)`2; 016 GrLine3(dc,x,y,0,x2,y2,0); 017 x=x2,y=y2; 018 if(y>=max_y) { 019 max_y=y; 020 max_x=x; 021 } 022 } 023 if(highest_x_pos) *highest_x_pos=max_x; 024 return max_y; 025 } 026 U0 QuessCenter(CD3I32 *middle,CD3I32 *l,CD3I32 *r, 027 F64 desired_x,F64 desired_y,F64 l_min_deriv=0., 028 F64 r_min_deriv=0.) { 029 F64 at,closest_at,closest; 030 Bool tried_up=FALSE,tried_down=FALSE; 031 I64 sign=1,quessed_x,quessed_y; 032 F64 deriv,step; 033 //Quess y vertex cordnate 034 closest_at=l->y;step=l->y; 035 closest=F64_MAX; 036 while(!tried_up||!tried_down) { 037 middle->y=step; 038 CalcBezier(middle,l,middle,r); 039 at=l->y*0.5`2+middle->y*2*.5*.5+r->y*.5`2; 040 //left deritive 041 if(2.*Abs(at-l->y)>=l_min_deriv) 042 if(2.*Abs(r->y-at)>=r_min_deriv) { 043 if(Abs(at-desired_y)<closest) { 044 closest_at=step; 045 closest=Abs(at-desired_y); 046 } 047 if(at>desired_y) { 048 sign=-1; 049 tried_up=TRUE; 050 } else if(at<desired_y) { 051 sign=1; 052 tried_down=TRUE; 053 } else 054 break; 055 } 056 step+=sign; 057 } 058 quessed_y=closest_at; 059 //Guess x cordnate 060 tried_down=FALSE,tried_up=FALSE; 061 closest_at=l->x; 062 step=l->x; 063 closest=F64_MAX; 064 while(!tried_up||!tried_down) { 065 middle->x=step; 066 CalcBezier(middle,l,middle,r); 067 at=l->x*0.5`2+middle->x*2*.5*.5+r->x*.5`2; 068 if(Abs(at-desired_x)<closest) { 069 closest_at=step; 070 closest=Abs(at-desired_y); 071 } 072 if(at>desired_x) { 073 sign=-1; 074 tried_up=TRUE; 075 } else if(at<desired_x) { 076 sign=1; 077 tried_down=TRUE; 078 } else 079 break; 080 step+=sign; 081 } 082 quessed_x=closest_at; 083 middle->x=quessed_x,middle->y=quessed_y; 084 } 085 class CDisplayNode { 086 AST *ast; 087 CD2 hover_node_pos; 088 F64 handle_x,handle_y; 089 F64 bound_l,bound_r; 090 F64 max_y; 091 F64 l_deriv,r_deriv; 092 I32 color,thick; 093 I64 level; 094 I64Set *connects; 095 }; 096 U0 DisplayNodeDel(CDisplayNode *n) { 097 I64 i; 098 if(n->connects) { 099 i=n->connects->cnt; 100 while(--i>=0) 101 DisplayNodeDel(n->connects->body[i]); 102 } 103 Free(n); 104 } 105 CTrie *DisplayNodeGetHoverWord(CDisplayNode *n,I64 ms_x,I64 ms_y) { 106 I64 i; 107 AST *ret; 108 if(n->ast&&Sqrt(Sqr(ms_x-n->hover_node_pos.x)+Sqr(ms_y-n->hover_node_pos.y))<16) { 109 return n->ast->word; 110 } 111 if(n->connects) { 112 i=n->connects->cnt; 113 while(--i>=0) 114 if(ret=DisplayNodeGetHoverWord(n->connects->body[i],ms_x,ms_y)) { 115 return ret; 116 } 117 } 118 return NULL; 119 } 120 121 #define WORD_MARGIN 20 122 #define CURVE_MARGIN 40 123 class CDisplayTmp { 124 I64 *word_offsets; 125 F64 xoff,yoff,max_y; 126 }; 127 F64 Center(F64 a,F64 b) { 128 return Min(a,b)+(Max(a,b)-Min(a,b))/2; 129 } 130 //Returns maximum 4 drawn 131 F64 DrawConnect(CDC *dc,I64 level=0,F64 x,F64 y,F64 x2,F64 y2,F64 mdl,F64 mdr,F64 *vx=NULL,F64 *vy=NULL,F64 *dl=NULL,F64 *dr=NULL,F64 *zenith_x) { 132 F64 highest; 133 CD3I32 ctrls[3]; 134 ctrls[0].x=x; 135 ctrls[0].y=y; 136 ctrls[2].x=x2; 137 ctrls[2].y=y2; 138 QuessCenter(&ctrls[1],&ctrls[0],&ctrls[1],Center(x2,x),Max(y2,y)+CURVE_MARGIN*level,mdl,mdr); 139 dc->thick=3; 140 highest=GrPreciseBezier(dc,ctrls,zenith_x); 141 if(vx) *vx=ctrls[0].x*.5`2+ctrls[1].x*2*.5*(1-.5)+ctrls[2].x*.5`2; 142 if(vy) *vy=ctrls[0].y*.5`2+ctrls[1].y*2*.5*(1-.5)+ctrls[2].y*.5`2; 143 if(dl) *dl=2.*(ctrls[1].y-ctrls[0].y); 144 if(dr) *dr=2.*(ctrls[2].y-ctrls[1].y); 145 return highest; 146 } 147 I64 SideSort(AST *a,AST *b) { 148 return a->word_idx-b->word_idx; 149 } 150 I64 SideSortRev(AST *a,AST *b) { 151 return b->word_idx-a->word_idx; 152 } 153 //Fs->user_data has the distance we are measuring from 154 I64 DistSort(AST *a,AST *b) { 155 return AbsI64(a->word_idx-Fs->user_data)-AbsI64(b->word_idx-Fs->user_data); 156 } 157 158 I64 DrawWordInfo(CDC *dc,I64 x,I64 y,CTrie *word,Bool dummy=FALSE) { 159 I64 ox=x; 160 if(dummy) dc=DCNew(1,1); 161 if(word->flags&(NOUN|PRONOUN|ADJECTIVE)) { 162 dc->color=GREEN; 163 if(word->flags&MASCULINE) { 164 GrPrint(dc,x,y,"M"); 165 x+=8; 166 } else if(word->flags&FEMININE) { 167 GrPrint(dc,x,y,"F"); 168 x+=8; 169 } else if(word->flags&NEUTER) { 170 GrPrint(dc,x,y,"N"); 171 x+=8; 172 } 173 174 dc->color=PURPLE; 175 if(word->flags&COMPARATIVE) { 176 GrPrint(dc,x,y,"Comp"); 177 x+=8*4; 178 } else if(word->flags&COMPARATIVE) { 179 GrPrint(dc,x,y,"Sup"); 180 x+=8*3; 181 } 182 if(word->flags&NOMITIVE) { 183 dc->color=LTGREEN; 184 GrPrint(dc,x,y,"N"); 185 x+=8; 186 } else if(word->flags&ACCUSATIVE) { 187 dc->color=LTRED; 188 GrPrint(dc,x,y,"A"); 189 x+=8; 190 } else if(word->flags&GENITIVE) { 191 dc->color=LTCYAN; 192 GrPrint(dc,x,y,"G"); 193 x+=8; 194 } else if(word->flags&ABLATIVE) { 195 dc->color=LTBLUE; 196 GrPrint(dc,x,y,"Ab"); 197 x+=8*2; 198 } 199 200 _p_cnt: 201 dc->color=RED; 202 if(word->flags&_3P) { 203 GrPrint(dc,x,y,"3"); 204 x+=8; 205 } else if(word->flags&_2P) { 206 GrPrint(dc,x,y,"2"); 207 x+=8; 208 } else if(word->flags&_1P) { 209 GrPrint(dc,x,y,"1"); 210 x+=8; 211 } 212 213 dc->color=BLACK; 214 if(word->flags&PLURAL) { 215 GrPrint(dc,x,y,"P"); 216 x+=8; 217 } else { 218 GrPrint(dc,x,y,"S"); 219 x+=8; 220 } 221 } else if(word->flags&VERB) { 222 dc->color=BLUE; 223 if(word->flags&IMPERFECT) { 224 GrPrint(dc,x,y,"Imp"); 225 x+=8*3; 226 } else if(word->flags&FUTURE) { 227 GrPrint(dc,x,y,"Fut"); 228 x+=8*3; 229 } else if(word->flags&PERFECT) { 230 GrPrint(dc,x,y,"Per"); 231 x+=8*3; 232 } else if(word->flags&PLUPERFECT) { 233 GrPrint(dc,x,y,"Plu"); 234 x+=8*3; 235 } 236 goto _p_cnt; 237 } 238 if(dummy) DCDel(dc); 239 return (x-ox)/8; 240 } 241 242 243 CDisplayNode *DisplayNode(CDisplayTmp *world,CDC *dc,AST *ast,I64 level=0,I64 *max_h=NULL) { 244 CDisplayNode *ret=CAlloc(sizeof CDisplayNode),*tmp; 245 ret->ast=ast; 246 ret->level=level; 247 ASTSet *set; 248 F64 x,y,ww=0,x2,y2,handle_x,handle_y; 249 F64 bound_y=F64_MIN; 250 I64 color=LTGRAY,idx,run,run2,idx2,old_color,old_color2; 251 I64Set *left_sides=NULL,*right_sides=NULL,*set2=NULL; 252 U8 *optr,*base_word; 253 I64 level2,max_level=0; 254 AST *ast2; 255 CD3I32 ctrls[3]; 256 Bool is_left_side; 257 F64 max_l_deriv=0.,max_r_deriv=0.; 258 switch(ast->act_as_type) { 259 break;case AST_NOUN: color=GREEN; 260 break;case AST_CONJUNCTION: color=RED; 261 break;case AST_VERB: color=BLUE; 262 break;case AST_OF: color=BROWN; 263 break;case AST_WHERE: color=PURPLE; 264 break;case AST_ADJECTIVE: color=CYAN; 265 break;case AST_INFINITIVE: color=LTPURPLE; 266 break;case AST_MEASURE: color=LTGREEN; 267 break;case AST_ADVERB: color=LTCYAN; 268 break;case AST_QUESTION: color=LTGRAY; 269 } 270 old_color2=dc->color; 271 ret->color=color; 272 if(ast->word) { 273 y=8; 274 x=world->word_offsets[ast->word_idx]; 275 dc->color=color; 276 if(ast->word->translation) 277 ww=FONT_WIDTH*MaxI64(StrLen(ast->word->str),StrLen(ast->word->translation)); 278 else 279 ww=FONT_WIDTH*StrLen(ast->word->str); 280 x+=ww/2; 281 if(ast->word->front_declension||ast->word->back_declension) { 282 base_word=optr=StrNew(ast->word->str); 283 if(ast->word->back_declension) 284 base_word+=StrLen(ast->word->back_declension); 285 if(ast->word->front_declension) 286 base_word[StrLen(base_word)-StrLen(ast->word->front_declension)]=0; 287 x2=x-StrLen(ast->word->str)*8/2; 288 idx2=0; 289 if(ast->word->back_declension) { 290 dc->color=color^0x7; 291 GrPrint(dc,x2,y,"%s",ast->word->back_declension); 292 idx2+=StrLen(ast->word->back_declension); 293 } 294 dc->color=color; 295 GrPrint(dc,x2+8*idx2,y,"%s",base_word); 296 idx2+=StrLen(base_word); 297 if(ast->word->front_declension) { 298 dc->color=color^0x7; 299 GrPrint(dc,x2+8*idx2,y,"%s",ast->word->front_declension); 300 idx2+=StrLen(ast->word->front_declension); 301 } 302 dc->color=color; 303 Free(optr); 304 } else { 305 x2=x-StrLen(ast->word->str)*8/2; 306 GrPrint(dc,x2,y,"%s",ast->word->str); 307 } 308 x2=DrawWordInfo(NULL,x,y,ast->word,TRUE);//number of chars 309 x2=x-x2*8/2; 310 DrawWordInfo(dc,x2,y+1+FONT_HEIGHT,ast->word); 311 if(ast->word->translation) { 312 x2=x-StrLen(ast->word->translation)*8/2; 313 GrPrint(dc,x2,y+2+FONT_HEIGHT*2,"%s",ast->word->translation); 314 } 315 ret->hover_node_pos.x=x; 316 ret->hover_node_pos.y=y+3+FONT_HEIGHT*3+2.5; 317 GrFillCircle(dc,x,y+3+FONT_HEIGHT*3+2.5,0,5); 318 x2=x; 319 y2=y+3+FONT_HEIGHT*3+7; 320 ret->handle_x=x2; 321 ret->handle_y=y2; 322 ret->bound_l=x2; 323 ret->bound_r=x2; 324 ret->max_y=y2; 325 bound_y=y2; 326 } else 327 throw('Visual'); 328 //I will sort the left and right sides by distance 329 for(run=0;run<=10;run++) { 330 if((set=ast->nomitive)&&run==0) { 331 ent: 332 for(idx=0;idx!=set->cnt;idx++) { 333 set2=I64SetAdd(set2,set->body[idx]); 334 if(set->body[idx](AST*)->word_idx<ast->word_idx) 335 left_sides=I64SetAdd(left_sides,set->body[idx]); 336 else 337 right_sides=I64SetAdd(right_sides,set->body[idx]); 338 } 339 } else if((set=ast->accusative)&&run==1) { 340 goto ent; 341 } else if((set=ast->dative)&&run==2) { 342 goto ent; 343 } else if((set=ast->genitive)&&run==3) { 344 goto ent; 345 } else if((set=ast->adjective)&&run==4) { 346 goto ent; 347 } else if((set=ast->preposition)&&run==5) { 348 goto ent; 349 } else if((set=ast->conjunction)&&run==6) { 350 goto ent; 351 } else if((set=ast->measurement)&&run==7) { 352 goto ent; 353 } else if((set=ast->adverb)&&run==8) { 354 goto ent; 355 } else if((set=ast->ablative)&&run==9) { 356 goto ent; 357 }else if((set=ast->question)&&run==10) { 358 goto ent; 359 } 360 } 361 //Sort the left and right sides 362 if(left_sides) 363 QSortI64(left_sides->body,left_sides->cnt,&SideSortRev); 364 if(right_sides) 365 QSortI64(right_sides->body,right_sides->cnt,&SideSort); 366 if(set2) { 367 Fs->user_data=ast->word_idx; 368 QSortI64(set2->body,set2->cnt,&DistSort); 369 } 370 set=set2; 371 if(set) 372 for(idx=0;idx!=set->cnt;idx++) { 373 if(I64SetHasItem(ast->nomitive,set->body[idx])) 374 dc->color=LTGREEN; 375 else if(I64SetHasItem(ast->accusative,set->body[idx])) 376 dc->color=LTRED; 377 else if(I64SetHasItem(ast->dative,set->body[idx])) 378 dc->color=LTCYAN; 379 else if(I64SetHasItem(ast->genitive,set->body[idx])) 380 dc->color=BROWN; 381 else if(I64SetHasItem(ast->adjective,set->body[idx])) 382 dc->color=BLUE; 383 else if(I64SetHasItem(ast->preposition,set->body[idx])) 384 dc->color=LTGRAY; 385 else if(I64SetHasItem(ast->conjunction,set->body[idx])) 386 dc->color=RED; 387 else if(I64SetHasItem(ast->measurement,set->body[idx])) 388 dc->color=PURPLE; 389 else if(I64SetHasItem(ast->adverb,set->body[idx])) 390 dc->color=CYAN; 391 else if(I64SetHasItem(ast->ablative,set->body[idx])) 392 dc->color=BLACK; 393 else if(I64SetHasItem(ast->question,set->body[idx])) 394 dc->color=DKGRAY; 395 if(I64SetHasItem(left_sides,set->body[idx])) { 396 is_left_side=TRUE; 397 level2=0; 398 for(idx2=0;idx2!=left_sides->cnt;idx2++) { 399 ast2=left_sides->body[idx2]; 400 if(ast2->disp_node) 401 level2=MaxI64(ast2->disp_node->level,level2); 402 if(ast2==set->body[idx]) 403 break; 404 } 405 } 406 if(I64SetHasItem(right_sides,set->body[idx])) { 407 is_left_side=FALSE; 408 level2=0; 409 for(idx2=0;idx2!=right_sides->cnt;idx2++) { 410 ast2=right_sides->body[idx2]; 411 if(ast2->disp_node) 412 level2=MaxI64(ast2->disp_node->level,level2); 413 if(ast2==set->body[idx]) 414 break; 415 } 416 } 417 max_level=MaxI64(max_level,level2); 418 tmp=DisplayNode(world,dc,set->body[idx],level2+1); 419 set->body[idx](AST*)->disp_node=tmp; 420 ret->connects=I64SetAdd(ret->connects,tmp); 421 //ret->handle_y set here 422 if(is_left_side) { 423 world->max_y=Max(world->max_y,ret->handle_y=DrawConnect(dc,level2+1,tmp->handle_x,tmp->handle_y,x2,y2,0,max_l_deriv,&handle_x,&handle_y,&ret->l_deriv,&ret->r_deriv,&ret->handle_x)); 424 max_l_deriv=Max(Abs(ret->r_deriv*.55),max_l_deriv); //our target node is on the left side,our current node is on the rgiht side 425 } else { 426 world->max_y=Max(world->max_y,ret->handle_y=DrawConnect(dc,level2+1,tmp->handle_x,tmp->handle_y,x2,y2,max_r_deriv,0,&handle_x,&handle_y,&ret->l_deriv,&ret->r_deriv,&ret->handle_x)); 427 max_r_deriv=Max(Abs(ret->l_deriv*.55),max_r_deriv); //our target node is on the right side,our current node is on the left side 428 } 429 ret->max_y=Max(ret->max_y,handle_y); 430 ret->bound_l=Min(ret->bound_l,tmp->bound_l); 431 ret->bound_r=Max(ret->bound_r,tmp->bound_r); 432 old_color=dc->color; 433 dc->color=BLACK; 434 GrFillCircle(dc,tmp->handle_x,tmp->handle_y,0,10); 435 dc->color=old_color; 436 } 437 //If we have connects of each side,make our connect in the "center" 438 if(left_sides&&left_sides->cnt&&right_sides&&right_sides->cnt) { 439 ret->handle_x=(ret->bound_r-ret->bound_l)/2.+ret->bound_l; 440 ret->handle_y=ret->max_y+8; 441 } 442 Free(left_sides),Free(right_sides); 443 dc->color=old_color2; 444 ret->level=level; 445 return ret; 446 } 447 448 U0 CopyRegion(CDC *dst,CDC *img,I64 dx,I64 dy,I64 x,I64 y,I64 w,I64 h) { 449 I64 x2,y2; 450 for(x2=x;x2!=x+w;x2++) { 451 for(y2=y;y2!=y+h;y2++) { 452 dst->color=GrPeek(img,x2,y2); 453 if(dst->color==-1) dst->color=TRANSPARENT; 454 GrPlot(dst,dx+x2-x,dy+y2-y); 455 } 456 } 457 } 458 //Like "word-wrap" for images 459 CDC *SplitImageIntoColumn(CDC *img,I64 width=GR_WIDTH) { 460 I64 clip_cnt=img->width/width; 461 if(img->width%width) 462 clip_cnt++; 463 CDC *ret=DCNew(width,img->height*clip_cnt); 464 while(--clip_cnt>=0) { 465 CopyRegion(ret,img,0,clip_cnt*img->height,clip_cnt*width,0,width,img->height); 466 } 467 return ret; 468 } 469 470 CDC *DrawSentence(AST *sentence,I64 word_cnt,U8 **words,I64 dwidth=I64_MAX,I64 *w=NULL,I64 *h=NULL,I64 ms_x=0,I64 ms_y=0,CTrie **hover_over=NULL) { 471 I64 off,idx,inf_d,wc,cw; 472 CDC *dc,*wrapped; 473 I64 last_wrap=0,diff; 474 U8 *closest; 475 CDisplayTmp t; 476 CTrie **forms; 477 AST *untainted=ASTClone(sentence); 478 wc=ASTGetTrieWords(sentence,NULL); 479 forms=CAlloc(word_cnt*8); 480 ASTGetTrieWords(sentence,forms); 481 t.xoff=0,t.yoff=0; 482 t.word_offsets=MAlloc(word_cnt*8); 483 t.max_y=0.; 484 for(off=WORD_MARGIN,idx=0;idx!=word_cnt;idx++) { 485 cw=0; 486 if(forms[idx]) { 487 cw=StrLen(forms[idx]->str); 488 if(forms[idx]->translation) 489 cw=MaxI64(StrLen(forms[idx]->translation),cw); 490 } 491 t.word_offsets[idx]=off; 492 off+=FONT_WIDTH*cw; 493 off+=WORD_MARGIN; 494 //Make "image-wrap" points 495 if(idx) { 496 if(t.word_offsets[idx]-last_wrap+WORD_MARGIN>=dwidth) { 497 diff=t.word_offsets[idx]-t.word_offsets[idx-1]; 498 t.word_offsets[idx-1]=(last_wrap=CeilI64(t.word_offsets[idx-1],dwidth))+WORD_MARGIN; 499 off=t.word_offsets[idx]=diff+t.word_offsets[idx-1]; 500 off+=FONT_WIDTH*cw; 501 off+=WORD_MARGIN; 502 } 503 } 504 } 505 dc=DCNew(1,1); 506 DisplayNodeDel(DisplayNode(&t,dc,sentence)); 507 DCDel(dc); 508 dc=DCNew(off+WORD_MARGIN,t.max_y+8+10+FONT_HEIGHT*4); //See DisplayNode 509 DCFill(dc,TRANSPARENT); 510 //DisplayNode will set ->display_node of the ast,so use the one without the ->display_node's 511 CDisplayNode *dn=DisplayNode(&t,dc,untainted); 512 if(hover_over) { 513 hover_over[0]=DisplayNodeGetHoverWord(dn,ms_x,ms_y); 514 } 515 DisplayNodeDel(dn); 516 if(dwidth!=I64_MAX&&off+8>dwidth) { 517 wrapped=SplitImageIntoColumn(dc,dwidth); 518 DCDel(dc); 519 } else 520 wrapped=dc; 521 if(w) *w=dc->width; 522 if(h) *h=dc->height; 523 Free(t.word_offsets); 524 Free(forms); 525 ASTDel(untainted); 526 return wrapped; 527 } 528 WinMax; 529 U0 DumpSentence(...) { 530 try { 531 I64 *dummy_stk=MAlloc(8*(1+argc)); 532 I64 w,h; 533 CDC *dc; 534 dummy_stk[0]=argc; 535 MemCpy(dummy_stk+1,argv,argc*8); 536 AST *sent=ParseSentenceJoin(argc+1,dummy_stk); 537 if(sent) { 538 dc=DrawSentence(sent,argc,argv); 539 " 540 541 542 543 544 545 546 547 548 549 550 551 552 "; 553 DocSprite(DocPut,DC2Sprite(dc)); 554 " 555 556 557 558 559 560 561 562 563 564 565 566 567 "; 568 CFileBMP *bmp=BMPRLE4To(dc); 569 DCColorChg(dc,TRANSPARENT,WHITE); 570 FileWrite("sent.BMP",bmp,bmp->file_size); 571 Free(bmp); 572 DCDel(dc); 573 DumpAST(sent); 574 ASTDel(sent); 575 } 576 Free(dummy_stk); 577 } catch PutExcept(FALSE); 578 } 579 public Bool WordTextBox(CDC *dc=0,I64 x1,I64 y1,U8 *s,I64 bg_color=YELLOW) 580 {//3D. Transformation. DCF_SYMMETRY is silly. 581 U8 *ptr; 582 if(!dc) dc=gr.dc; 583 I64 ch,res,w,w_max,h; 584 I64 old=dc->color; 585 I64 border=2; 586 if (!s) return FALSE; 587 ptr=s; 588 w=0; w_max=0; h=FONT_HEIGHT; 589 590 while (ch=*ptr++) { 591 if (ch=='\t') 592 w=CeilU64(w+FONT_WIDTH,FONT_WIDTH*8); 593 else if (ch=='\n') { 594 if (w>w_max) w_max=w; 595 w=0; 596 h+=FONT_HEIGHT; 597 } else 598 w+=FONT_WIDTH; 599 } 600 if (w>w_max) w_max=w; 601 dc->color=bg_color; 602 GrRect(dc,x1-border,y1-border,w_max+border<<1,h+border<<1); 603 dc->color=old; 604 res=GrPrint(dc,x1,y1,"%s",s); 605 res|=GrLine(dc,x1-border ,y1-border ,x1+w_max+border,y1-border); 606 res|=GrLine(dc,x1-border ,y1+h+border,x1+w_max+border,y1+h+border); 607 res|=GrLine(dc,x1-border ,y1-border ,x1-border,y1+h+border); 608 res|=GrLine(dc,x1+w_max+border,y1-border ,x1+w_max+border,y1+h+border); 609 610 return !!(res); 611 } 612 613 614 615 U0 InteractViewDrawIt(CTask *t,CDC *dc) { 616 U8 *st; 617 U8 *tran; 618 U8 **toks; 619 I64 tcnt; 620 AST *ast; 621 CTrie *word=NULL; 622 CDC *dc2; 623 CDoc *d=DocNew; 624 I64 x,y; 625 if(ast=FramePtr("InteractAst",t)) { 626 if(st=FramePtr("InteractText",t)) { 627 toks=TokenizeSentence(st,&st); 628 tcnt=0; 629 while(toks[tcnt]) 630 tcnt++; 631 ast=ASTClone(ast); 632 dc2=DrawSentence(ast,tcnt,toks,,,,x=ms.pos.x-t->pix_left,y=ms.pos.y-t->pix_top,&word); 633 GrBlot(dc,0,0,dc2); 634 dc->color=RED; 635 if(word&&word->str) { 636 DocPrint(d,"Word %s:\n",word->str); 637 if(tran=GetTranslation(word->str,TRUE)) { 638 DocPrint(d,"Defs:\n%s\n",tran); 639 Free(tran); 640 } 641 642 //No declensions (like numbers that dont decline) 643 /*#define INDECLINABLE (1<<32) 644 #define PRESENT (1<<33) 645 #define PASSIVE (1<<34) 646 #define IMPERATIVE (1<<35) 647 #define PARTICIPLE (1<<36) 648 #define GERUND (1<<37) 649 #define COMPARATIVE (1<<38) 650 #define SUPERLATIVE (1<<39) 651 #define PARTICLE (1<<40) 652 #define CONJUNCTION2 (1<<41) //dixeque Words ending in -que 653 #define IS (1<<42) //Words like sum 654 #define DETIRMINER (1<<43) //things *that* are green */ 655 if(word->flags&NOMITIVE) 656 DocPrint(d,"Nom.\n"); 657 if(word->flags&GENITIVE) 658 DocPrint(d,"Gen.\n"); 659 if(word->flags&DATIVE) 660 DocPrint(d,"Dat.\n"); 661 if(word->flags&ACCUSATIVE) 662 DocPrint(d,"Acc.\n"); 663 if(word->flags&ABLATIVE) 664 DocPrint(d,"Abl.\n"); 665 if(word->flags&SINGULAR) 666 DocPrint(d,"Sing.\n"); 667 if(word->flags&PLURAL) 668 DocPrint(d,"Plrl.\n"); 669 if(word->flags&FEMININE) 670 DocPrint(d,"Fem.\n"); 671 if(word->flags&MASCULINE) 672 DocPrint(d,"Masc.\n"); 673 if(word->flags&INFINITIVE) 674 DocPrint(d,"Inf.\n"); 675 if(word->flags&_1P) 676 DocPrint(d,"1st.\n"); 677 if(word->flags&_2P) 678 DocPrint(d,"2nd.\n"); 679 if(word->flags&_3P) 680 DocPrint(d,"3rd.\n"); 681 if(word->flags&IMPERFECT) 682 DocPrint(d,"Imperfect.\n"); 683 if(word->flags&FUTURE) 684 DocPrint(d,"Fut.\n"); 685 if(word->flags&CONJUNCTION) 686 DocPrint(d,"Conj.\n"); 687 if(word->flags&VERB) 688 DocPrint(d,"V.\n"); 689 if(word->flags&NOUN) 690 DocPrint(d,"N.\n"); 691 if(word->flags&ADVERB) 692 DocPrint(d,"Adv.\n"); 693 if(word->flags&ADJECTIVE) 694 DocPrint(d,"Adj.\n"); 695 if(word->flags&PRONOUN) 696 DocPrint(d,"Pron.\n"); 697 if(word->flags&REFLEXIVE) 698 DocPrint(d,"Reflex.\n"); 699 if(word->flags&POSSESIVE) 700 DocPrint(d,"Poss.\n"); 701 if(word->flags&DEMONSTRATIVE) 702 DocPrint(d,"Demon.\n"); 703 if(word->flags&INTEROGITIVE) 704 DocPrint(d,"Inter.\n"); 705 if(word->flags&NEUTER) 706 DocPrint(d,"Neut.\n"); 707 if(word->flags&RELATIVE) 708 DocPrint(d,"Rel.\n"); 709 if(word->flags&PREPOSITION) 710 DocPrint(d,"Prep.\n"); 711 if(word->flags&PERFECT) 712 DocPrint(d,"Per.\n"); 713 if(word->flags&PLUPERFECT) 714 DocPrint(d,"Plu.\n"); 715 if(word->flags&SUBJUNCTIVE) 716 DocPrint(d,"Sub.\n"); 717 718 tran=DocSave(d); 719 WordTextBox(dc,x,y,StrUtil(tran,SUF_REM_CTRL_CHARS)); 720 Free(tran); 721 } 722 ASTDel(ast); 723 DCDel(dc2); 724 tcnt=0; 725 while(toks[tcnt]) 726 Free(toks[tcnt++]); 727 Free(toks); 728 } 729 } 730 DocDel(d); 731 } 732 U0 InteractView(U8 *st) { 733 U8 **toks; 734 I64 tcnt; 735 AST *ast; 736 SettingsPush; 737 DocClear; 738 FramePtrAdd("InteractText",st); 739 toks=TokenizeSentence(st,&st); 740 tcnt=0; 741 while(toks[tcnt]) 742 tcnt++; 743 ast=ParseSentenceJoin(tcnt,toks); 744 if(!ast) goto fin; 745 Fs->draw_it=&InteractViewDrawIt; 746 " 747 748 749 "; 750 DumpAST(ast); 751 FramePtrAdd("InteractAst",ast); 752 while(ast&&GetKey!=CH_ESC) 753 Refresh; 754 755 fin: 756 tcnt=0; 757 while(toks[tcnt]) 758 Free(toks[tcnt++]); 759 Free(toks); 760 ASTDel(ast); 761 SettingsPop; 762 } 763 U0 DumpSentences(U8 *st,U8 *translations=NULL) { 764 U8 **toks; 765 I64 tcnt; 766 I64 w=0,h=0; 767 AST *ast; 768 CDC *dc,*tmp_dc; 769 CDC *sents[0x800]; 770 I64 sent_cnt=0; 771 U8 *tmp; 772 CFileBMP *bmp; 773 while(*SkipWhitespace(st)) { 774 tcnt=0; 775 toks=TokenizeSentence(st,&st); 776 while(toks[tcnt]) { 777 tcnt++; 778 } 779 ast=ParseSentenceJoin(tcnt,toks); 780 if(ast) { 781 dc=DrawSentence(ast,tcnt,toks); 782 " 783 784 785 786 787 788 789 790 791 792 793 794 795 "; 796 DocSprite(DocPut,DC2Sprite(dc)); 797 " 798 799 800 801 802 803 804 805 806 807 808 809 810 "; 811 sents[sent_cnt++]=dc; 812 w=MaxI64(dc->width,w); 813 h+=dc->height;; 814 } 815 tcnt=0; 816 while(toks[tcnt]) 817 Free(toks[tcnt++]); 818 Free(toks); 819 } 820 if(translations) { 821 tcnt=0; 822 while(tmp=LstSub(tcnt,translations)) { 823 if(8*StrLen(tmp)>w) 824 w=8*StrLen(tmp); 825 tcnt++; 826 } 827 h+=tcnt*25; 828 } 829 dc=DCNew(w,h); 830 DCFill(dc,WHITE); 831 h=0; 832 for(tcnt=0;tcnt<sent_cnt;tcnt++) { 833 tmp_dc=sents[tcnt]; 834 w=dc->width/2.-tmp_dc->width/2.; 835 GrBlot(dc,w,h,tmp_dc); 836 h+=tmp_dc->height; 837 if(translations) { 838 if(tmp=LstSub(tcnt,translations)) { 839 w=dc->width/2.-8*StrLen(tmp)/2.; 840 dc->color=BLACK; 841 GrPrint(dc,w,h+(25-8)/2.,"%s",tmp); 842 h+=25; 843 } 844 } 845 DCDel(tmp_dc); 846 } 847 bmp=BMPRLE4To(dc); 848 FileWrite("sent.BMP",bmp,bmp->file_size); 849 Free(bmp); 850 DCDel(dc); 851 } 852 853 DocMax; 854 /* 855 856 DumpSentences( 857 "laicalis nisi hos quinque pericula et comminationes sunt dimittere sed nos perditus et nos cedere inferno." 858 "[ quid quinque ] es [ [ Mortificatio animales ] et surreptio et [ peccare sexualiter ] et mendacium et [ alcohol illa inportet neglegentiam]]." 859 "Nisi [ [ hos quinque pericula et comminationes ] sunt dimittere ] nisi [ nos sunt perditus ] et [ nos cedere inferno ]." 860 , 861 "Householder, unless these five dangers and threats are given up, one is said to be unethical, and one goes to hell\0" 862 "What five? Killing living creatures, stealing, committing sexual misconduct, lying, and using alcoholic drinks that cause negligence\0" 863 "Unless these five dangers and threats are given up, one is said to be unethical, and one goes to hell\0" 864 ); 865 */ 866 /*DumpSentences( 867 "Erema est symbolum pro [ siccitas et infelix ] de dormire animam." 868 "[uva catervae] est [[symbolum pro schola scholarium] quia [initiati surgere conjuncte in solum rami]] ." 869 "Tu non oportet [ interficere animales vel furari vel potare alcohol ]." 870 "Audio tibi et amo tibi." 871 "namque [ Grinch sum cupere [coleum huius]].", 872 "The desert is a symbol for the aridity and unproductivity of the unawakened consciousness.\0" 873 "The grape cluster is a symbol for the school of adepts, for the initiates grow together upon a single branch\0" 874 "You shouldn't kill living creatures, or steal,or lie, or drink alcohol.\0" 875 );*/ 876 877 /*DumpSentences( 878 "sancti entia in decem regiones es." 879 "numerosus sicut [harenae [fluminis ganges]] es." // ... 880 "insimul adlaudant [inopinabilissimus et [altissimam sanctus] dominum Amitaiyus]." 881 "[[Omne ens] qui [audiant id nomen]] et [laetant in fidem]." 882 "cogitent eius solus semel." 883 "eorum devoveant [[meritum renato] [in illum sanctum agrum]]." 884 "adfecto [[renato illum] et [potiri renatum] et [potiri salvationem]]." // 885 , 886 "All the Holy Ones in the ten directions,\0" 887 "as numerous as the sands of the Ganges River\0" 888 "together praise the inconceivable, supernal virtue of Lord Amitayus\0" 889 "All sentient beings who, having heard his Name, rejoice in faith,\0" 890 " think of him even once,\0" 891 "and sincerely devote the merit of virtuous practices to rebirth in that holy land,\0" 892 //aspiring to be reborn there, will attain rebirth and attain salvation. But excluded are those who have committed the five cardinal sins and violated the holy law." 893 );*/ 894 /* 895 DumpSentences( 896 " [in principio] creavit Deus caelum et terram." 897 "[terra erat [inanis et vacua]] et [[tenebrae super faciem ] et spiritus Dei ferebatur super aquas]." 898 "[dixitque Deus] quod [[fiat lux] et [facta est lux]]." 899 "et [[vidit Deus lucem] quod [esset bona]] et [divisit lucem ac tenebras]." 900 "[appellavitque quod [[lucem diem es] et [tenebras noctem es] ]]." 901 , 902 "In the beginning God created heaven, and earth.\0" 903 "And the earth was void and empty, and darkness was upon the face of the deep; and the spirit of God moved over the waters.\0" 904 "And God said: Be light made. And light was made.\0" 905 "And God saw the light that it was good; and he divided the light from the darkness.\0" 906 "And he called the light Day, and the darkness Night; and there was evening and morning one day. \0" 907 ); 908 */ 909 //DumpSentences("Es [optumus situs] [interretialis finctus].","Is the best site of the false internet!"); 910 911 912 //DumpSentences("Benedicere te. Spero potioris pacem aeternam et laetitiam."); 913 /*DumpSentences( 914 "namque [ Grinch sum cupere [coleum huius]].", 915 "Truly,The Grinch's sack Is what I want" 916 );*/ 917 /*DumpSentences( 918 "*[ omnis sancti entia in decem regiones] es.", 919 "Poop\0" 920 );*/ 921 // 922 //DumpSentence("quomondo","es","tuum","sapor","[","camelus","lotii","]");; 923 //DumpSentence("[","tu","ne","cede","malis","]","sed","contra","audentior","ito"); 924 //DumpSentence("Spero","potioris","pacem","aeternam","et","laetitiam"); 925 //DumpSentence("nisi","[","canto","]","sed","audio"); 926 //DumpSentence("laicalis","nisi","hos","quinque","pericula","et","comminationes","sunt","dimittere","sed","nos","perditus","et","nos","cedere","inferno"); 927 //DumpSentence("[","quid","quinque","]","es","[","[","Mortificatio","animales","]","et","surreptio","et","[","peccare","sexualiter","]","et","mendacium","et","[","alcohol","illa","inportet","neglegentiam","]","]"); 928 //DumpSentence("Nisi","[","[","hos","quinque","pericula","et","comminationes","]","sunt","dimittere","]","nisi","[","nos","sunt","perditus","]","et","[","nos","cedere","inferno","]"); 929 // 930 /*DumpSentence("portat"); 931 DumpSentence("portat","saxa","puella","in","aqua"); 932 DumpSentence("cibum","et","aquam","portabo","ad","triclinium"); 933 DumpSentence("cibum","portatis","et","aquam","gustant","sed","vinum","amamus"); 934 DumpSentence("agricolae","saxa","invenient"); 935 DumpSentence("servi","et","puellae","reginam","audiebant"); 936 DumpSentence("in","triclinio","cibum","paramus"); 937 DumpSentence("quomondo","aquam","portabis"); 938 DumpSentence("quis","est"); 939 DumpSentence("cum","amico","in","silva","ambulo"); 940 DumpSentence("ex","silva","ad","villam","festinabo","et","cum","amico","in","cameram","ambulabo"); 941 DumpSentence("nepos","noster","uxorem","cupit"); 942 DumpSentence("non","edam","vivo","sed","ut","vivam","edo");*/ 943 //Genesis 1 944 //DumpSentences("creavit terram et terram"); 945 //InteractView("edimus ut vivamus"); 946 //InteractView("philosophia est vitae magistra"); 947 //DumpSentences("assentatio es [malus vitium]"); 948 //DumpSentences("video hominem abire"); 949 //DumpSentence("terra","erat","inanis","et","vacua","et","tenebrae","super","faciem","abyssi","et","spiritus","Dei","ferebatur","super","aquas"); 950 //"si", 951 //DumpSentences("Omne qui ens audiant nomen."); 952 //DumpSentences("puella nominis nominis es"); 953 954 // Nroot's Doctrine 1 955 DumpSentences("Res finitus sunt." 956 "Formamentum sunt haut." 957 "Res creat e [formamentis abditis]." 958 "Animi est abditi." 959 "animos sunt mutationes formamentorum." 960 "Mutatio formamentorum sunt discursum." 961 "tela tenet unus fila ilico. [duo fila existit haut] ubi [unus existat]." 962 "sed fila existat juxta alius fila." 963 "[[unus corpus] teneat haut [alius positum]]." 964 "[corpus tenet diversum animos] quando [diversum positum existit]." 965 "[animus est juxta [diversum animos]] hac [tela tenet [diversum fila]." 966 "[idem animi ] sunt [[omnia animos] in [diversum positum]]."); 967 //InteractView("decorum est pro patria mori"); 968 // 969 //InteractView("in principio creavit Deus [caelum et terram]"); 970 //InteractView("Notitia est peior quam melior"); 971 //DumpSentences("Notitia est peior quam melior"); 972 //TrieAdd("Herodes",NOUN|NOMITIVE,"Herod"); 973 //InteractView("tunc Herodes videns"); 974 //DumpSentences("[[tunc Herodes videns] quoniam [inlusus esset a magis]] et [iratus est valde]"); 975 // et mittens occidit omnes pueros qui erant in Bethleem et in omnibus finibus eius a bimatu et infra secundum tempus quod exquisierat a magis");