0001                                   Aiwnios.com
0002 
0003   Welcome to Aiwnios.com,the best server on earth. I will show you how  to do 
0004 cool stuff like write compilers and make games. I will write articles time to 
0005 time,but first let me tell you about myself.
0006 
0007   My name is Clayton and I like compilers alot.I wrote Aiwnios which is a  HolyC 
0008 compiler that runs on 64,bit arm and X86_64 and it's Travis Scott lit.I will 
0009 explain it in detail how it works,the first part is the lexer. I'm not a unix 
0010 pro but here are my notes Unix Notes or my Jain Notes.
0011 
0012   Here is a link to the User Guide if you want to know how to use aiwnios. Or 
0013 maybe you are here for the blog
0014 
0015   Checkout My FlashCards app and flash cards for the latest in nroots Greek 
0016 Quest(download the ISO and MountFile it in Aiwnios to use it).
0017 
0018   Irc Server
0019 
0020 aiwnios.com 6667
0021 Turn off SSL before connecting in your client
0022 Dont send anything important over the IRC server
0023 
0024 
0025 
0026                            Where did the Sh*tpit go?
0027 
0028   The Shitpit contained statements contrary to the the values of the 
0029 Tirhankaras. I will still write here(MY BLOG) but I cannot dig myself into a 
0030 deep hole.
0031 
0032 
0033                                     Clayton
0034 
0035  <nrootconauto@gmail.com>
0036 0037 0038 0039 0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 0070 0071 0072 0073 WIP DOOM port 0074 I am working on a port of Doom that runs on Aiwnios(TOOM). 0075
0076 0077 0078 0079 0080 0081 0082 0083 0084 0085 0086 0087 0088 0089 0090 0091 0092 0093 0094 0095 0096 0097 0098 0099 0100 0101 0102 0103 0104 0105 0106 0107 0108 0109 0110 0111 0112 0113 0114 0115 0116 0117 0118 0119 0120 0121 0122 0123 Compiler Part 1,The Lexer 0124 0125 The first part of the compiler is the lex. It turned the text from the source 0126 code into words(tokens) that the compiler understands. For example, 0127 "123" gets turned into a TK_I64. 0128 0129 In our lexer,we have CLexFile's which are blocks of text we read,this can we 0130 any piece of text,like a macro's definition or an #exe block or a file. We get 0131 the charactors out of the Lexer via LexGetChar,which will do things like free 0132 the old CLexFile if we reach the end of the stream. 0133 0134 Sometimes we want to put a charactor back into the stream. You can use CCF_USE 0135 _LAST_U16 to reuse the last charactor. For example,if we are looking for digits 0136 in the expression 123; and we hit the semicolon,we dont want to discard the 0137 semicolon that we just got,so we put it back into the lexer by setting CCF_USE_L 0138 AST_U16 0139 0140 0141 <3>
0142 0143 0144 0145 0146 0147 0148 0149 0150 0151 0152 0153 0154 0155 0156 0157 0158 0159 0160 0161 Compiler Part 2,The Parser 0162 0163 The second part of the compiler is the the parser. At the heart of this parser 0164 (in AIWNIOS_PrsExp.HC) is the shunting yard algorithm. This uses Reverse Polish 0165 Notation. This is a form of stack notation that looks like this: 0166 0167 0168 1 2 + 3 4 + * 0169 0170 The operators come is the order that they are used,lets see again with some 0171 parenthesis 0172 0173 ((1 2 +) (3 4 +) *) 0174 0175 Pretty epic isn't it. 0176 0177 To generate this,I use a stack called CCmpCtrl->ps with a class of CPrsStk. 0178 There are 3 stacks in a CPrsStk. The first is the precedence stack,the second is 0179 pointers to the generated CRPN's. The final is tree nodes. 0180 0181 The algorithm works by immediately pushing numbers to the stack first. 0182 Operators are pushed to the Shunting yard stack. It looks like this 0183 0184 <4>
0185 0186 0187 0188 0189 0190 0191 0192 0193 0194 0195 0196 0197 0198 0199 0200 0201 0202 0203 0204 The first thing to do here is put the '+' operator on the stack. 0205 0206 <5>
0207 0208 0209 0210 0211 0212 0213 0214 0215 0216 0217 0218 0219 0220 0221 0222 0223 0224 0225 0226 The next thing to do(after we push 2 to the output) is to check if + comes 0227 after *. + comes after the * so we push it to the output,then push * to the 0228 stack for later. We end up with something like this 0229 0230 <6>
0231 0232 0233 0234 0235 0236 0237 0238 0239 0240 0241 0242 0243 0244 0245 0246 0247 0248 0249 0250 0251 0252 Once we are at the end of input(after we add 3). We add all the operators to 0253 the output 0254 0255 <7>
0256 0257 0258 0259 0260 0261 0262 0263 0264 0265 0266 0267 0268 0269 0270 0271 0272 0273 0274 0275 Compiler Part 2,The Parser II 0276 0277 UNDER CONSTRUCTION 0278 0279 Compiler Part 3,The Code Generator 0280 0281 0282 The code generator in aiwnios is platform dependant and is written in C to 0283 make porting to new platforms easier(bootstrapping is done in C). There is an 0284 interface in AIWNIOS_CodeGen.HC to use the turn the Intermediate Codes from the 0285 HolyC parser into the C intermediate codes. 0286 0287 There are multiple phases to turning the intermeidate codes into machine code. 0288 The first phases are in optpass.c. This file is pretty simple and does things 0289 like constant folding(OptPassConstFold) and merging communitive operations(OptPa 0290 ssMergeCommunitives). This is boring stuff ,but the epic part is in x86_64_backe 0291 nd.c(or arm_backend.c for AARCH64). 0292 0293 The most important thing this file does is generate machine code,at the top of 0294 the file you will see functions that generate voluptuous X86 instructions for 0295 you. The second most important part is generating the temporary registers for 0296 the intermediate codes. 0297 0298 To do this,I imagine the CRPN's as a tree. Beacuse temporary registers are 0299 scare,we need to make good use of them. A good way to do this is to assign them 0300 to the leafs of the tree,and when we are done using them,we Pop them from our 0301 imaginary stack(computers loves stacks). 0302 0303 0304 <8>
0305 0306 0307 0308 0309 0310 0311 0312 0313 0314 0315 0316 0317 0318 0319 0320 0321 0322 The heavy lifting for this is done in PushTmpDepthFirst. This we recuse into 0323 the parse "Tree" and Push items once it's children are done. Items are popped 0324 when we are done with them. The PushTmp/PushTmpSpilled functions will 0325 automatically choose a temporary register based on how many temporary registers 0326 are used,or if none are availble a stack location will be choosed. 0327 0328 The fun part is at the __OptPassFinal function. This is basically a gaint 0329 switch statement that will generate the machine code from the intermediate 0330 codes. 0331 0332 This is done in 2 passes,the first pass is done to see how big the resulting 0333 source code is,and the second part is to actually generator the source code. In 0334 my code generator,I have code_misc's on some of the intermedaite codes like 0335 IC_GOTO. 0336 0337 Sometimes we want the address of a label,but we dont know it untill all the 0338 machine code is generated. You can have the compiler fill in the label at an 0339 offset in the machine code with CodeMiscAddRef(CCodeMisc*,I64 offset). At the 0340 end of our OptPassFinal function I fill in the holes with the label pointers. 0341 0342 0343 User-Guide 0344 0345 Runtime Part 1:Graphics I 0346 0347 Use the Fs->draw_it callback to draw something to the current window 0348 0349 0350 U0 DrawIt(CTask *,CDC *dc) { 0351 dc->color=BLUE; 0352 GrRect(dc,0,0,100,100); 0353 } 0354 Fs->draw_it=&DrawIt; 0355 0356 0357 0358 The first argument is a pointer to the CTask being drawn,and the second 0359 argument is a CDC drawing context,use some primitives to draw to the screen. 0360 0361 -] GrRect 0362 0363 GrRect(dc,200,200,100,100); 0364 0365 -] GrPlot(single pixel) 0366 0367 GrPlot(dc,200,200); 0368 0369 -] GrFillCircle 0370 0371 GrFillCircle(dc,100,100,50); 0372 0373 -] GrCircle 0374 0375 GrCircle(dc,100,100,50); 0376 0377 -] GrLine 0378 0379 GrLine(dc,100,100,0,0); 0380 0381 -] GrPrint 0382 0383 GrPrint(dc,100,100,"Hello World"); 0384 0385 -] GrBlot(copy dc to other dc) 0386 0387 GrBlot(dc,100,100,new); 0388 0389 -] DCClear 0390 0391 DCClear(dc); //Resets Z buffer 0392 0393 -] DCFill 0394 0395 DCFill(dc,COLOR); 0396 0397 0398 Runtime Part 1:Graphics Transformations and 3D graphics 0399 0400 TempleOS lets you do sexy stuff with the graphics like 3D graphics. At the 0401 heart of this is a transformation matrix. Im not a math genius but luckily for 0402 me there are functions for managing the math for me. Before we can use a 0403 transformation matrix,we need to set the DCF_TRANSFORMATION flag in CDC->flags. 0404 After wards you can use matrix functions to rotate your drawing things 0405 cordanates 0406 0407 0408 CDC *dc=DCNew(100,100); 0409 Mat4x4IdentEqu(dc->r); //Assign a identity matrix(No transformation) 0410 DCFill; 0411 dc->flags|=DCF_TRANSFORMATION; 0412 F64 rotx=0; 0413 for(;rotx<=2*pi;rotx+=(2*pi/100.)) { 0414 DCFill(dc); 0415 Mat4x4IdentEqu(dc->r); //Reset our transformation 0416 Mat4x4RotZ(dc->r,rotx); 0417 Mat4x4TranslationEqu(dc->r,50,50,0); 0418 dc->color=YELLOW; 0419 GrRect3(dc,0,0,0,50,50); 0420 DCFill; 0421 GrBlot(,100,100,dc); 0422 Sleep(33); 0423 } 0424 DCDel(dc); 0425 DCFill; 0426 0427 0428 Here are a list of (transformation) matrix goodies: 0429 -] Mat4x4RotX 0430 0431 //Rotates around the X axis,used for Y-flipping 0432 0433 -] Mat4x4RotY 0434 0435 //Rotates around the Y axis,used for X-flipping 0436 0437 -] Mat4x4RotZ 0438 0439 //Rotates around the Z axis,use general 2D rotations 0440 0441 -] Mat4x4Scale 0442 0443 //Zooms a matrix 0444 0445 -] Mat4x4TranslationEqu 0446 0447 Mat4x4TranslationEqu(mat,x,y,z); //Sets the cordantes of a matrix 0448 0449 -] Mat4x4TranslationAdd 0450 0451 Mat4x4TranslationAdd(mat,x,y,z); //Add to the cordantes of a matrix 0452 0453 -] Mat4x4MulXYZ 0454 0455 Mat4x4MulXYZ(mat,&x,&y,&z); //THIS WILL TRANSFORM THE CORDANTES BY THE MATRIX 0456 0457 0458 You may want to do general math on matricies too: 0459 -] Mat4x4IdentEqu 0460 0461 Mat4x4IdentEqu(mat); //This makes a normal matrix that doesnt do 0462 transofrmations 0463 0464 -] Mat4x4IdentNew 0465 0466 I64 *malloced=Mat4x4IdentNew; //This makes a normal matrix that doesnt do 0467 transofrmations 0468 0469 -] Mat4x4MulMat4x4Equ 0470 0471 Mat4x4MulMat4x4Equ(dst,a,b); //Multiplies a matrix to another matrix,ask a 0472 genius what this actually does 0473 0474 -] Mat4x4MulMat4x4New 0475 0476 I64 *malloced=Mat4x4MulMat4x4Nw(a,b); //Same as above but MAlloced 0477 0478 0479 Sometimes in your 3D adventures you may want to make sure you draw things in 0480 the distacne behind the things in the front. This is called Z-buffering. In 0481 TempleOS this is easy-peasy. Just call DCDepthBufAlloc(dc). This will handle 0482 your depths for you. 0483 0484 Here is a cube thing for you: 0485 0486 0487 CD3I32 poly[4]= 0488 {{-100,-100,-100},{100,-100,-100},{100,100,-100},{-100,100,-100}}; 0489 I64 colors[4]= {BLUE,YELLOW,GREEN,CYAN}; 0490 CDC *dc=DCNew(200,200); 0491 dc->r=Mat4x4IdentNew; 0492 DCDepthBufAlloc(dc); 0493 DCFill; 0494 dc->flags|=DCF_TRANSFORMATION; 0495 F64 rotx=0,roty; 0496 CD3I32 cube[6][6]; 0497 I64 i=0,i2=0; 0498 I64 *trans=Mat4x4IdentNew; 0499 for(rotx=0.; rotx<=(2.*pi)-1.; rotx+=2*pi/4.) { 0500 Mat4x4IdentEqu(trans); 0501 Mat4x4RotX(trans,rotx); 0502 Mat4x4RotY(trans,roty); 0503 for(i2=0; i2!=4; i2++) { 0504 MemCpy(&cube[i][i2],&poly[i2],sizeof(CD3I32)); 0505 Mat4x4MulXYZ(trans,&cube[i][i2].x,&cube[i][i2].y,&cube[i][i2].z); 0506 } 0507 i++; 0508 } 0509 for(rotx=0; rotx<=2*pi; rotx+=(2*pi/100.)) { 0510 DCFill(dc); 0511 DCDepthBufRst(dc); 0512 Mat4x4IdentEqu(dc->r); 0513 Mat4x4RotX(dc->r,rotx); 0514 Mat4x4RotY(dc->r,rotx); 0515 Mat4x4RotZ(dc->r,rotx); 0516 Mat4x4Scale(dc->r,.5); 0517 Mat4x4TranslationEqu(dc->r,0,0,3000); 0518 for(i2=0; i2!=6; i2++) { 0519 dc->color=colors[i2]; 0520 GrFillPoly3(dc,4,cube[i2]); 0521 } 0522 DCFill; 0523 GrBlot(,100,100,dc); 0524 Sleep(33); 0525 } 0526 DCDel(dc); 0527 DCFill; 0528 0529 0530 If you ran the above example,the cube looks flat,THIS IS BECUASE YOU NEED TO 0531 MAKE THINGS SHRINK IN THE DISTANCE 0532 0533 Let me introduce the CDC->transform callback: This callback will be called for 0534 every point that is rendered when DCF_TRANSFORMATION is enabled. To acheive the 0535 epic "shrinking effect",divide the X/Y coordinates by the Z coordanate times a 0536 scale distance Let's see an example: 0537 Heres an example: 0538 0539 0540 #define SCRN_SCALE 512 0541 U0 Transform(CDC *dc,I64 *x,I64 *y,I64 *z) 0542 { 0543 I64 zz; 0544 Mat4x4MulXYZ(dc->r,x,y,z); 0545 zz=SCRN_SCALE/3+*z; 0546 if (zz<1) zz=1; 0547 *x=SCRN_SCALE/2* *x/zz; 0548 *y=SCRN_SCALE/2* (*y)/zz; 0549 *x+=dc->x; 0550 *y+=dc->y; 0551 *z+=dc->z; 0552 } 0553 CDC *dc=DCAlias; 0554 dc->transform=&Transform; 0555 dc->flags|=DCF_TRANSFORMATION; 0556 I64 dist=0; 0557 dc->z=-60; 0558 for(dist=0;dist!=100;dist++) { 0559 Mat4x4TranslationEqu(dc->r,0,0,dist); 0560 dc->color=LTRED; 0561 GrRect3(dc,0,0,0,100,100); 0562 Refresh; 0563 DCFill; 0564 } 0565 0566 Runtime Part 1:Graphics Raster Operations 0567 0568 In TempleOS there are 16 colors,but you can mix them to make "new" colors. 0569 This is called dithering. To use dithering to use raster operations. This allows 0570 us to do things like make shading or invert the colors below what your drawing. 0571 Let's get started 0572 0573 0574 CDC *dc=DCAlias; 0575 I64 cnt; 0576 for(cnt=0;cnt!=100;cnt++) { 0577 dc->color=LTRED+YELLOW<<16+ROPF_DITHER; //Mix LTRED+YELLOW for Orange-ish 0578 color 0579 GrRect3(dc,0,0,0,100,100); 0580 Refresh; 0581 DCFill; 0582 } 0583 0584 0585 If you though that was cool,check out probability dithering. This will make a 0586 shading effect. You can change the percentage of what color gets used to make a 0587 shading of your choice.The CDC->dither_probability_u16 is a 16bit percentage of 0588 the the colors being used. If the dither_probability_u16 is 0,it will use 0589 dc->color,otherwise it will use dc->color.u8[2] if the probability is U16_MAX; 0590 0591 Let's rock(.u8[2] is 16 bits over): 0592 0593 CDC *dc=DCAlias; 0594 I64 cnt; 0595 for(cnt=0;cnt!=100;cnt++) { 0596 dc->color=BLACK; 0597 GrRect(dc,0,0,100,100); 0598 dc->color=LTRED+YELLOW<<16+ROPF_PROBABILITY_DITHER; 0599 dc->dither_probability_u16=U16_MAX*ToF64(cnt)/100.; 0600 GrFloodFill(dc,10,10); 0601 Refresh; 0602 DCFill; 0603 } 0604 DCDel(dc); 0605 0606 Runtime Part 2: Making Noises 0607 0608 TempleOS makes sounds that will bring you back to the days of Atari games. The 0609 simplest way to make a tone is Snd(23);(This higher the number the higher the 0610 pitch). Call "Snd;" to cancel the sound. 0611 0612 If you want to go the extra mile and make a bodacious explosioon sound,use No 0613 ise(milliseconds,min_pitch,max_pitch);. Or if you want a jumping sound,use Sweep 0614 . 0615 0616 Runtime Part 3: Making Music 0617 0618 TempleOS let's you make some epic jams. To do this,we use the Music 0619 0620 A simple song looks like this: 0621 0622 Play("wChDqEeFwGwAwB"); 0623 0624 0625 There are special charactors that change the duration/properties of the 0626 notes,so without further ado,here is a list 0627 -] # 0628 0629 Make a note sharp(comes after the note) 0630 0631 -] w 0632 0633 When before a note,it makes it a whole note 0634 0635 -] h 0636 0637 Makes a half note 0638 0639 -] q 0640 0641 Makes a 1/4 note 0642 0643 -] e 0644 0645 Makes a tiny eigth note 0646 0647 0648 You can change the tempo of the music via the global vairable music.tempo(Be 0649 sure to reset the music's settings via MusicSettingsRst) 0650 0651 Try this: 0652 0653 0654 music.tempo=8; 0655 Play( 0656 "hEhEwEhChEwGqG" 0657 "wCqGqEqAqBqA#qAqGhEhGwAhFhGwEhChDqB" 0658 "wCqGqEqAqBqA#qAqGhEhGwAhFhGwEhChDqB" 0659 "hGhF#hFhD#wEqG#qAhCqAhChD" 0660 "hGhF#hFhD#wE.wC.wC.wC" 0661 "hGhF#hFhD#wEqG#qAhCqAhChDwD#wDwC" 0662 "hGhF#hFhD#wEqG#qAhCqAhChD" 0663 "hGhF#hFhD#wE.wC.wC.wC" 0664 "hGhF#hFhD#wEqG#qAhCqAhChDwD#wDwC" 0665 ); 0666 MusicSettingsRst; 0667 0668 Runtime Part 4: Meta-data and Reflection 0669 0670 HolyC is a mainly just in time language. This means when the code gets 0671 compiled,the information about the code is still in memory. This is great for 0672 having the code reflect on itself and saves a lot of time doing meanial things 0673 like serializing a class. The primary way to do this is via MetaData. This means 0674 data about the self. 0675 0676 To get the metadata of a class out of the compiler,we must use the CTask's 0677 hash table and do these steps 0678 0679 -] Step 1 0680 0681 Lookup the class by it's name CHashClass 0682 *findc=HashFind(cls,Fs->hash_table,HTT_CLASS); 0683 0684 -] Step 2 0685 0686 Lookup the class by it's name CMemberLst 0687 *member=MemberFind("member_name",findc); 0688 0689 -] Step 3 0690 0691 Lookup the meta data I64 meta_data=MemberMeta("META_DATA",member); 0692 0693 0694 0695 Perhaps an example will help: 0696 0697 class CMeta { 0698 I64 a fmt "A:%d\n"; 0699 I64 b fmt "B:%d\n"; 0700 F64 c fmt "C:%n\n"; 0701 }; 0702 CMeta abc={1,2,3}; 0703 U0 Main(U8 *ptr,U8 *cls=lastclass) { 0704 CHashClass *findc=HashFind(cls,Fs->hash_table,HTT_CLASS); 0705 CMemberLst *ml; 0706 U64 sf; 0707 if(!findc) return; 0708 ml=MemberFind("a",findc); 0709 sf=(ptr+ml->offset)[0](U64); 0710 if(MemberMetaFind("fmt",ml)) { 0711 Print(MemberMetaData("fmt",ml),sf); 0712 } 0713 } 0714 Main(&abc); //Here we use lastclass to get the class of abc 0715 0716 0717 If you want to make a form using meta data,you can use PopUpForm 0718 0719 0720 class CInput { 0721 //Be sure to use -P with strings 0722 U8 name[STR_LEN] format "\n"; 0723 I64 age format "\n"; 0724 Bool is_tall format "\n"; 0725 }; 0726 CInput inp; 0727 PopUpForm(&inp); 0728 "%s is %d years old\n",inp.name,inp.age; 0729 if(inp.is_tall) 0730 "Tall!\n"; 0731 0732 0733 Runtime Part 5: Filesystem 0734 0735 If you are used to using TempleOS,use the Cd("Folder"); to move into a folder. 0736 You can list the contents of the directory via Dir(".");("." is the current 0737 folder). Sometimes you want your programs to be aware of the folders. Luckily 0738 for you,you have come to the right place 0739 0740 In TempleOS,each task has a current directory path in Fs->cur_dir(this doesnt 0741 include the drive letter). If you want the full path,use DirCur. 0742 0743 To make a file,use FileWrite("filename","text",4 /*text length*/);. When you 0744 want to read it use FilleRead("filename",&len); FileRead will always put a NULL 0745 terminator at the end of the file for your,so you can use it like a string. 0746 0747 Like C,in TempleOS you can read files in a stream,But in TempleOS,all file 0748 reads/writes act directly on the Hard-Disks sectors(Which are BLK_SIZE bytes 0749 big). You FOpen("filename","w") for writing FOpen("filename","r") for reading. 0750 To open a file for adding more data to it,use FOpen("filename","w+"). Lets see 0751 an example 0752 0753 0754 // 0755 // Files opened with FOpen MUST WRITE BLK_SIZE bytes at once 0756 // A BLK is the size of a hard-disk sector 0757 // 0758 CFile *file=FOpen("Database.BIN","w"); 0759 class CFileEnt { 0760 U8 name[STR_LEN]; 0761 U8 password[STR_LEN]; 0762 }; 0763 #assert sizeof(CFileEnt)<=BLK_SIZE 0764 CFileEnt clayton={"Clayton","123"}; 0765 CFileEnt root={"Root","toor"}; 0766 U8 buffer[BLK_SIZE]; 0767 MemCpy(buffer,&root,sizeof(CFileEnt)); 0768 FBlkWrite(file,buffer,0,1); //Write 1 blk at the first block(blk 0) 0769 MemCpy(buffer,&clayton,sizeof(CFileEnt)); 0770 FBlkWrite(file,buffer,1,1); //Write 1 blk at the second block(blk 1) 0771 FClose(file); 0772 // 0773 // Now we read 0774 // 0775 file=FOpen("Database.BIN","r"); 0776 CFileEnt user; 0777 while(FBlkRead(file,buffer,,1)) { 0778 MemCpy(&user,buffer,sizeof(CFileEnt)); 0779 "Got user \"%s\" with password \"%s\"\n",user.name,user.password; 0780 } 0781 FClose(file); 0782 0783 0784 Making and reading files is fun,but first you need to figure out where a file 0785 is. To do this use, . This will return a CDirEntry of the results(which may be 0786 multiple files). Assuming you are familiar with wildcards from Linux,DOS and 0787 CP/M. Look at this example 0788 0789 0790 FileWrite("abc.TXT","abc",3); 0791 FileWrite("def.TXT","def",3); 0792 FileWrite("ghi.TXT","ghi",3); 0793 CDirEntry *cur,*root=FilesFind("*.TXT",FUF_JUST_FILES); 0794 for(cur=root;cur!=NULL;cur=cur->next) { 0795 "I Found %s\n",cur->full_name; 0796 } 0797 DirEntryDel(root); 0798 0799 0800 A CDirEntry has much information about the directory structure. The most 0801 important is full_name which tells you the full name of the file as you may 0802 expect(name is the filename without the path). When you are done with a CDirEntr 0803 y be sure to free the root data with . 0804 0805 To check if a file exists,you can use FileFind("file.HC") to check if a file 0806 exists. 0807 0808 Time to get to the nitty gritty. Has some epic flags you can use.Im not going 0809 to waste time with exposiiton,rather I will give you a table of flags 0810 0811 0812 -] FUF_RECURSE 0813 0814 This will search in the child folders for the pattern too 0815 0816 -] FUF_JUST_DIRS 0817 0818 Chooses only directories(folders) 0819 0820 -] FUF_JUST_FILES 0821 0822 Chooses only files 0823 0824 -] FUF_JUST_TXT 0825 0826 Chooses only text files 0827 0828 -] FUF_JUST_DD 0829 0830 Chooses only DolDoc files 0831 0832 -] FUF_JUST_SRC 0833 0834 Chooses only source files 0835 0836 -] FUF_Z_OR_NOT_Z 0837 0838 This will ignore Ziped named of files and just check as normal 0839 0840 -] FUF_FLATTEN_TREE 0841 0842 This will flatten a FUF_RECURSE tree for you conveince 0843 0844 0845 If you want to delete files,use DelTree("folder/files");,or if you just want 0846 to remove a fule use Del("file"); 0847 0848 There are 2 ways to make a folder,use Cd("a/b/c/d/e",TRUE); to make a path,or 0849 make a folder one at a time via DirMk("folder_name");. Copy your stuff via CopyT 0850 ree("old","new") or just a file via Copy("old","new"). 0851 0852 And by the way you can open a file chooser via PopUpPickFile("T:/"); 0853 0854 Runtime Part 6: Data structures(1 CQue) 0855 0856 TempleOS comes loaded with useful data structures but it may be confusing at 0857 first. The most important one is a CQue. This means a Circular Queue. It's likle 0858 a loop,ill draw a picture for you. 0859 0860 0861 0862 <9>
0863 0864 0865 0866 0867 0868 0869 0870 0871 0872 As you can see(poorly drawn) is that each item has 2 pointers( the CQue->last 0873 and the CQue->next).The ->last pointer is the previous item in the chain,not the 0874 "last" one. 0875 0876 To make a new CQue,use QueInit on the item make both pointers point to the 0877 item,which means an empty CQue. You can insert items into the CQue via QueIns(to 0878 _insert,at). Perhaps an example will help you. 0879 0880 In our below example,I start at head and also end at head as the queue is 0881 ciruclar 0882 0883 0884 CQue *head=MAlloc(sizeof CQue),*one=MAlloc(sizeof CQue),*two=MAlloc(sizeof 0885 CQue),*cur; 0886 QueInit(head); 0887 QueIns(one,head); 0888 QueIns(two,one); 0889 for(cur=head->next;cur!=head;cur=cur->next) 0890 "Current element(excuding HEAD):%P\n",cur; 0891 QueDel(head); //Remove all items in the CQue 0892 Free(head); //QueDel doesnt Free the head 0893 0894 0895 To get the count of items in your queue use QueCnt(head). And to remove an 0896 item form the queue(not Free it),use QueRem which will detach the item from a 0897 queue 0898 0899 0900 CQue *head=MAlloc(sizeof CQue),*one=MAlloc(sizeof CQue),*two=MAlloc(sizeof 0901 CQue),*cur; 0902 QueInit(head); 0903 QueIns(one,head); 0904 QueIns(two,one); 0905 QueRem(one); //Detach one from the CQue 0906 Free(one); //Free it's data 0907 for(cur=head->next;cur!=head;cur=cur->next) 0908 "Current element(excuding HEAD):%P\n",cur; 0909 QueDel(head); //Remove all items in the CQue 0910 Free(head); //QueDel doesnt Free the head 0911 0912 0913 You can insert get the item count of the QueCnt(head) 0914 0915 Here is a reference section: 0916 -] QueInit(head) 0917 0918 Intialize the head of a queue 0919 0920 -] QueIns(to_ins,elem) 0921 0922 Insert an item after the elem 0923 0924 -] QueInsRev(to_ins,elem) 0925 0926 Insert an item before the elem 0927 0928 -] QueRem(elem) 0929 0930 Detach an item from the queue(doesnt free it) 0931 0932 -] QueDel(head) 0933 0934 Frees all items in the queue 0935 0936 -] QueCnt(head) 0937 0938 How many items in the queue(excluding the head) 0939 0940 0941 Runtime Part 7: Data structures 2(HashTable) 0942 0943 Hash tables are like dictionary data structures and each task has one in Fs->h 0944 ash_table. Each CHash has a type and a str. 0945 0946 When you look up a hash from a hash-table you will need the type. For 0947 example,if we want to grab a define(HTT_DEFINE_STR) from our current task,we do: 0948 0949 #define FOO 123 0950 CHashDefineStr *def=HashFind("FOO",Fs->hash_table,HTT_DEFINE_STR); 0951 if(def) 0952 "%s\n",def->data; 0953 0954 We looked up foo with type HTT_DEFINE_STR. Sometimes we want to add things to 0955 a CHashTable. To do this we need to use HashAdd. 0956 0957 CHashDefineStr *d=CAlloc(sizeof(CHashDefineStr)); 0958 d->str=StrNew("Hello"); //Must allocate string on heap 0959 d->type=HTT_DEFINE_STR; 0960 d->data=StrNew("10"); 0961 HashAdd(d,Fs->hash_table); 0962 //We added the macro Hello into the hash table 0963 "%d\n",Hello; 0964 0965 0966 Sometimes you want to make your own hashtables. You can do this via HashTableN 0967 ew(size). size MUST BE A POWER OF 2. 0968 0969 Any generic data in the hashtable should use type HTT_FRAME_PTR as HashTableDe 0970 l doesnt try to make assuptions on how to free the data 0971 0972 Perhaps an example will help: 0973 0974 CHashTable *ht=HashTableNew(0x100); 0975 CHashGeneric *ent=CAlloc(sizeof CHashGeneric); 0976 ent->user_data0=1; 0977 ent->user_data1=2; 0978 ent->user_data2=3; 0979 ent->type=HTT_FRAME_PTR; 0980 ent->str=StrNew("look"); 0981 HashAdd(ent,ht); 0982 CHashGeneric *g=HashFind("look",ht,HTT_FRAME_PTR); 0983 "%d,%d,%d\n",g->user_data0,g->user_data1,g->user_data2; 0984 HashTableDel(ht); 0985 0986 0987 Here is a reference of hash table functions 0988 0989 -] HashAdd(item,table) 0990 0991 Adds an item to the hash table 0992 0993 -] HashRemDel(item,table) 0994 0995 Delete an item from the hash table 0996 0997 -] HashFind(str,table,type) 0998 0999 Find an item in the table 1000 1001 -] HashSingleTableFind(str,table) 1002 1003 Find an item in the table,but dont check parent task's thing 1004 1005 -] HashTableNew(sz) 1006 1007 Make new hashtable,sz must be a power of 2 1008 1009 1010 Runtime Part 8: Data structures 3(Fifo) 1011 1012 Fifo's mean "First In First Out" and do things like store key presses. The 1013 first key you press is the the first one you get out. They also have a maximum 1014 size,which means that if you get too many keys,the old ones will be discarded 1015 1016 It looks like this: 1017 <10>
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 First create a FIFO with FifoI64New,Size must be a power of 2 1034 1035 CFifoI64 *fifoI64=FifoI64New(4); 1036 FifoI64Ins(fifoI64,1); 1037 FifoI64Ins(fifoI64,2); 1038 FifoI64Ins(fifoI64,3); 1039 1040 You can remove an item with FifoI64Rem. This takes a pointer and returns TRUE 1041 1042 CFifoI64 *fifoI64=FifoI64New(4); 1043 FifoI64Ins(fifoI64,1); 1044 FifoI64Ins(fifoI64,2); 1045 FifoI64Ins(fifoI64,3); 1046 I64 val; 1047 while(FifoI64Rem(fifoI64,&val)) 1048 "Got a %d\n",val; 1049 1050 1051 Here is a reference section 1052 1053 -] FifoI64New(sz) 1054 1055 Make a new fifo,sz must be a power of 2 1056 1057 -] FifoI64Flush(f) 1058 1059 Remove all the items from the fifo 1060 1061 -] FifoI64Cnt(f) 1062 1063 Get a count of all the items in the fifo 1064 1065 -] FifoI64Peek(f,&val) 1066 1067 Look at the next item in the fifo without removing it 1068 1069 -] FifoI64Del(f) 1070 1071 Free the fifo 1072 1073 -] FifoI64Rem(f,&val) 1074 1075 Remove an item from the fifo 1076 1077 -] FifoI64Ins(f,val) 1078 1079 Insert an item into the fifo 1080 1081 -] FifoU8Flush(f) 1082 1083 Remove all the items from the fifo 1084 1085 -] FifoU8Cnt(f) 1086 1087 Get a count of all the items in the fifo 1088 1089 -] FifoU8Peek(f,&val) 1090 1091 Look at the next item in the fifo without removing it 1092 1093 -] FifoU8Del(f) 1094 1095 Free the fifo 1096 1097 -] FifoU8Rem(f,&val) 1098 1099 Remove an item from the fifo 1100 1101 -] FifoU8Ins(f,val) 1102 1103 Insert an item into the fifo 1104 1105 -] FifoU8New(sz) 1106 1107 Make a new fifo,sz must be a power of 2 1108 1109 1110 Runtime Part 9: User Input 1111 1112 TempleOS lets you do lit stuff like click on things and use the keyboard. 1113 These events are passed through messages. We use GetMsg to get the 1114 messages,along with a message mask. 1115 1116 I64 x,y; 1117 U0 DrawIt(CTask *t,CDC *dc) { 1118 dc->color=RED; 1119 GrRect(dc,x,y,100,100); 1120 } 1121 U0 Run() { 1122 Fs->draw_it=&DrawIt; 1123 I64 m,x2,y2; 1124 while(TRUE) { 1125 m=GetMsg(&x2,&y2,1<<MSG_MS_MOVE+1<<MSG_MS_R_DOWN); 1126 if(m==MSG_MS_R_DOWN) 1127 break; 1128 x=x2; 1129 y=y2; 1130 Refresh; 1131 } 1132 } 1133 Run; 1134 1135 1136 Keyboard messages can be gotten via ScanKey(&ch,&sc). The first argument is 1137 the ASCII charactor,and the second one is the scancode. The scancode is the raw 1138 key being pressed and has flags in it. I'll give an example usage of the 1139 function first before I dive into details. 1140 1141 I64 x,y; 1142 U0 DrawIt(CTask*,CDC*dc) { 1143 dc->color=GREEN; 1144 GrRect(dc,x,y,100,100); 1145 } 1146 U0 Run() { 1147 Fs->draw_it=&DrawIt; 1148 I64 msg,sc,ch; 1149 for(;TRUE;) { 1150 if(ScanKey(&ch,&sc)) { 1151 if(sc&0xff==SC_ESC) break; 1152 if(sc&0xff==SC_CURSOR_UP) { 1153 y-=3; 1154 } else if(sc&0xff==SC_CURSOR_DOWN) { 1155 y+=3; 1156 } else if(sc&0xff==SC_CURSOR_LEFT) { 1157 x-=3; 1158 } else if(sc&0xff==SC_CURSOR_RIGHT) { 1159 x+=3; 1160 } 1161 } else { 1162 Refresh; 1163 } 1164 } 1165 } 1166 Run; 1167 1168 As you can see,I check the first 8 bits(0xff) of the scan code to test what 1169 key it is. There also flags on the scancode that tell you things like if the 1170 shift key is down etc. 1171 1172 The first byte of scancode is the key code,but the other bytes are flags which 1173 can be tested via the "&" operator 1174 1175 1176 I64 x,y; 1177 I64 color=GREEN; 1178 U0 DrawIt(CTask*,CDC*dc) { 1179 dc->color=color; 1180 GrRect(dc,x,y,100,100); 1181 dc->color=RED; 1182 } 1183 U0 Run() { 1184 Fs->draw_it=&DrawIt; 1185 I64 msg,sc,ch; 1186 for(;TRUE;) { 1187 if(ScanMsg(&ch,&sc,1<<MSG_KEY_UP|1<<MSG_KEY_DOWN)) { 1188 if(sc.u8[0]==SC_ESC) break; 1189 if(sc.u8[0]==SC_CURSOR_UP) { 1190 y-=3; 1191 } else if(sc.u8[0]==SC_CURSOR_DOWN) { 1192 y+=3; 1193 } else if(sc.u8[0]==SC_CURSOR_LEFT) { 1194 x-=3; 1195 } else if(sc.u8[0]==SC_CURSOR_RIGHT) { 1196 x+=3; 1197 } 1198 if(sc&SCF_CTRL) 1199 color=RED; 1200 else if(sc&SCF_SHIFT) 1201 color=YELLOW; 1202 else 1203 color=GREEN; 1204 } else { 1205 Refresh; 1206 } 1207 } 1208 } 1209 Run; 1210 1211 1212 Here's a list of scancode flags: 1213 1214 -] SCF_KEY_UP 1215 1216 The key was released 1217 1218 -] SCF_CTRL 1219 1220 The Ctrl key is down 1221 1222 -] SCF_SHIFT 1223 1224 The shift key is down 1225 1226 -] SCF_ALT 1227 1228 The alt key is down 1229 1230 -] SCF_CAPS 1231 1232 The Caps lock key is down 1233 1234 -] SCF_NUM 1235 1236 The NumLock key is kdown 1237 1238 -] SCF_SCROLL 1239 1240 Scroll Lock key is down 1241 1242 -] SCF_MS_L_DOWN 1243 1244 The left mouse is down 1245 1246 -] SCF_MS_R_DOWN 1247 1248 The right mouse is down 1249 1250 -] SCF_NO_SHIFT 1251 1252 There is no shift 1253 1254 1255 Here's a list of scancode keys: 1256 1257 -] SC_ESC 1258 1259 The escape key 1260 1261 -] SC_BACKSPACE 1262 1263 The backspace key 1264 1265 -] SC_TAB 1266 1267 The tab key 1268 1269 -] SC_ENTER 1270 1271 The enter key 1272 1273 -] SC_CTRL 1274 1275 The ctrl key 1276 1277 -] SC_ALT 1278 1279 The alt key 1280 1281 -] SC_CAPS 1282 1283 The caps lock key 1284 1285 -] SC_NUM 1286 1287 The num lock key 1288 1289 -] SC_SCROLL 1290 1291 The scroll lock key 1292 1293 -] SC_CURSOR_UP 1294 1295 The up key 1296 1297 -] SC_CURSOR_DOWN 1298 1299 The down key 1300 1301 -] SC_CURSOR_LEFT 1302 1303 The left key 1304 1305 -] SC_CURSOR_RIGHT 1306 1307 The right key 1308 1309 -] SC_PAGE_DOWN 1310 1311 The page down key 1312 1313 -] SC_PAGE_UP 1314 1315 The page up key 1316 1317 -] SC_HOME 1318 1319 The home key 1320 1321 -] SC_END 1322 1323 The end key 1324 1325 -] SC_INS 1326 1327 The insert key 1328 1329 -] SC_DELETE 1330 1331 The delete key 1332 1333 -] SC_F1-SC_F12 1334 1335 The Fxx keys 1336 1337 -] SC_PAUSE 1338 1339 The pause key 1340 1341 -] SC_GUI 1342 1343 The logo key 1344 1345 -] SC_PRTSCRN1 1346 1347 The print screen key 1348 1349 -] SC_PRTSCRN2 1350 1351 The print screen key 1352 1353 1354 I mentioned eariler about GetMsg,and I used ScanMsg. GetMsg waits for an 1355 event,but ScanMsg doesn't. There are also message codes 1356 1357 -] MSG_KEY_DOWN(ch,scancode) 1358 1359 A Key is put down 1360 1361 -] MSG_KEY_UP(ch,scancode) 1362 1363 A Key is release 1364 1365 -] MSG_MS_MOVE(x,y) 1366 1367 The mouse is moved 1368 1369 -] MSG_MS_L_DOWN(x,y) 1370 1371 The left button is down 1372 1373 -] MSG_MS_L_UP(x,y) 1374 1375 The left button is down 1376 1377 -] MSG_MS_R_DOWN(x,y) 1378 1379 The right button is down 1380 1381 -] MSG_MS_R_UP(x,y) 1382 1383 The right button is down 1384 1385 1386 Runtime Part 9: Multithreading 1387 1388 TempleOS is non-premptive. This means each Task has to manually tell the 1389 computer when to context swap. The way to do this and prevent freezing is to Yie 1390 ld 1391 1392 In TempleOS,spawning task's is easy,use the Spawn function 1393 1394 1395 U0 Foo(U8 *data) { 1396 Beep; 1397 } 1398 Spawn(&Foo,"Some_data","TaskName"); 1399 1400 1401 You can make a user terminal via User. You can talk to that task via XTalk 1402 1403 1404 CTask *u=User; 1405 XTalk(u,"\"Exiting in 5 seconds\\n\";\n"); //Be sure to put a semi-colon at the 1406 end as we are "the-user". 1407 Sleep(5000); 1408 XTalk(u,"Exit;\n"); 1409 1410 1411 Sometimes you want to wait for a task to die,to do this use DeathWait 1412 1413 1414 CTask *t=User; 1415 DeathWait(&t); //Note address of t 1416 Beep; //Will beep when you exit the User task 1417 1418 1419 There is also a BirthWait 1420 1421 1422 CTask *t=User; 1423 BirthWait(&t); //Note address of t 1424 Beep; //Will beep when you exit the User task 1425 1426 1427 To avoid race conditions we use locks. In TempleOS this is acheived through 1428 locked bit instructions with spinlocks. How it works is LBts will set the 1429 bit,and return the old value of the bit. We keep on setting the bit. If the old 1430 value is not set,it means we have access to the lock,otherwise we keep on 1431 looping. Be sure to reset the bit when you are done with LBtr. 1432 1433 1434 I64 beep_lock=0; 1435 U0 OneThread(I64 snd) { 1436 //This will spin until bit 0 is reset(look at the end of the function) 1437 while(LBts(&beep_lock,0)) //LBts has a side effect of setting the bit after it 1438 is checked 1439 Yield; //We are going to be beeping for awhile so Yield out control to other 1440 tasks 1441 Beep(snd); 1442 //We reset bit 0 of beep_lock to signify we are done with it. 1443 LBtr(&beep_lock,0); 1444 } 1445 I64 i; 1446 for(i;i!=10;i++) { 1447 Spawn(&OneThread,i*7+10); 1448 "Spawned a thread!!\n"; 1449 } 1450 1451 Runtime Part 10: Jobs 1452 1453 In TempleOS,each core has a seth_task. This task does lit stuff like run Jobs 1454 which can be created via TaskExe and you get the results via JobResGet 1455 1456 1457 CJob *job=TaskExe(Gs->seth_task,Fs,"1+1;;;",0); 1458 res=JobResGet(job); 1459 Kill(jobber); 1460 "I got %d\n",res; 1461 1462 With cpu_structs,you can spawn jobs on other cores 1463 1464 1465 CTask *parent_task=Fs; 1466 I64 core=0; 1467 //mp_cnt is the number of cpus 1468 CJob *jobs[mp_cnt]; 1469 for(core=0;core!=mp_cnt;core++) { 1470 jobs[core]=TaskExe(cpu_structs[core].seth_task,Fs, 1471 "Sleep(RandI64%1000);" 1472 "Gs->num;;", //Gs is the current CCPU for the core,->num is the cpu number 1473 0); 1474 } 1475 for(core=0;core!=mp_cnt;core++) { 1476 "Core %d return %d\n",core,JobResGet(jobs[core]); 1477 } 1478 1479 1480 If you want to have the parent task wait while a job runs,you can use the JOBf 1481 _WAKE_MASTER flag. 1482 1483 1484 CTask *parent_task=Fs; 1485 //Things ending in a lowecase f as bits(and need to be shifted to be flags) 1486 TaskExe(Gs->seth_task,parent_task,"Play(\"EGBDF\");",(1<<JOBf_WAKE_MASTER)); 1487 1488 Runtime Part 11: DolDoc 1489 1490 Most of the text you see on screen is from the DolDoc layout engine. It uses a 1491 series of dollar signs to set things like the text color and make elements. The 1492 are stored as a circular queue of CDocEntry's. The easyiest way to make a DolDoc 1493 element is to use DocPrint,use DocPut to get the current task's document. 1494 1495 1496 //BT is a button 1497 CDocEntry *de=DocPrint(DocPut,"\n\n$BT,\"Hello\"$\n\n"); 1498 1499 1500 As you can see,the DolDoc entries have a type and argument. They are 1501 surrounded by $'s. They can also have flags too. This let's you do things like 1502 center the text. Lets see an example: 1503 1504 1505 //TX is a text,+CX is the center flag 1506 CDocEntry *de=DocPrint(DocPut,"\n\n$TX+CX,\"Hello\"$\n\n"); 1507 1508 1509 DolDoc entries can also take an argument,Links use this to figure out where to 1510 go when you click them. Arguments for DolDoc entries come after the comma,some 1511 of the arguments are named and have the format "name=value" 1512 1513 1514 CDocEntry 1515 *de=DocPrint(DocPut,"\n\n$LK,\"Text\",A=\"FL:/PersonalMenu.DD\"$\n\n"); 1516 1517 1518 You can interact directly with the generated CDocEntrys. You can put things 1519 like callbacks into them. In our below example I set the left_cb function 1520 pointer to Beep2 and I tell the entry that it has a callback with DOCEF_LEFT_CB. 1521 1522 1523 I64 Beep2(CDoc *,CDocEntry *) { 1524 Beep; 1525 } 1526 CDocEntry *de=DocPrint(DocPut,"\n\n$BT+CX,\"Hello\"$\n\n"); 1527 de->de_flags|=DOCEF_LEFT_CB; 1528 de->left_cb=&Beep2; 1529 1530 1531 You can use the DocMenu function to get a value from your document. I use the 1532 LE for a left-click-expression. 1533 1534 1535 U0 CreateDialog() { 1536 CDocEntry *nums[3]; 1537 I64 i; 1538 DocClear(DocPut); 1539 "$TX+CX,\"Pick a number:\"$\n"; 1540 for(i=0;i!=3;i++) { 1541 nums[i]=DocPrint(DocPut,"\n\n$BT+CX,\"%d\",LE=%d$\n\n",i,i); 1542 } 1543 DocBottom(DocPut); 1544 switch(DocMenu(DocPut)) { 1545 start: 1546 DocClear(DocPut); 1547 case 0: 1548 "You picked nothing lol.\n"; 1549 break; 1550 case 1: 1551 "One is the one\n"; 1552 break; 1553 case 2: 1554 "Two is too good\n"; 1555 break; 1556 end: 1557 } 1558 } 1559 CreateDialog; 1560 1561 1562 You can use PopUpForm to use a class's meta data for making a menu. 1563 1564 1565 U0 CreateDialog() { 1566 class CInput { 1567 //Be sure to use -P with strings 1568 U8 name[STR_LEN] format "\n"; 1569 I64 age format "\n"; 1570 Bool is_tall format "\n"; //CB is a Check box 1571 }; 1572 CInput inp; 1573 PopUpForm(&inp); 1574 "%s is %d years old\n",inp.name,inp.age; 1575 if(inp.is_tall) 1576 "Tall!\n"; 1577 1578 1579 Yeah time for some reference section ehh: 1580 1581 -] TX 1582 1583 Text 1584 1585 -] CR 1586 1587 Newline 1588 1589 -] CU 1590 1591 Cursor pos,normally a ASCII #5 1592 1593 -] TB 1594 1595 Tab 1596 1597 -] CL 1598 1599 Clears all elements without the "+H" flag 1600 1601 -] PB 1602 1603 Page break 1604 1605 -] PL 1606 1607 Page length 1608 1609 -] LM 1610 1611 Left margin 1612 1613 -] RM 1614 1615 Right margin 1616 1617 -] HD 1618 1619 Header margin 1620 1621 -] FO 1622 1623 Footer margin 1624 1625 -] ID 1626 1627 Indent,use wit tree elements,and use with a negative number to un-indent 1628 1629 -] FD 1630 1631 Forground default color 1632 1633 -] BD 1634 1635 Background default color 1636 1637 -] PT 1638 1639 Command Line Prompt 1640 1641 -] WW 1642 1643 Use 1 to enable word wrap,use 0 to disable 1644 1645 -] UL 1646 1647 Use 1/0 to enable/disable underline 1648 1649 -] IV 1650 1651 Disable/enable Inverting of colors 1652 1653 -] BK 1654 1655 Burger Kind,just kidding,it's actually for blinking 1656 1657 -] SX 1658 1659 Shift the text by a amount of pixels 1660 1661 -] SY 1662 1663 Shift the text up/down by an amount of pixels 1664 1665 -] CB 1666 1667 Checkbox 1668 1669 -] LS 1670 1671 Major Lit Alert 1672 Use with the "D" argument to make a list(from a DefineListLoad),do this 1673 $LS,"potato",D="ST_BIBLE_BOOKS"$ 1674 Clicking on this will make a menu to pick an item from the list 1675 1676 -] MA 1677 1678 A macro,clicking on this will insert LM into the command line prompt 1679 1680 -] TR 1681 1682 A Tree wigdet,use this with ID to nest the tree's 1683 1684 -] HL 1685 1686 Turn HolyC syntax highting on/off 1687 1688 1689 Here is a reference section for the flags,they can be added/removed with 1690 +/-(For example you can do "$TX+CX+H,\"I have CX and H flags.\"$\n";) 1691 1692 -] H 1693 1694 Hold,this will prevent CL from deleting this element 1695 1696 -] L 1697 1698 This will make the element act as a link 1699 1700 -] TR 1701 1702 This will make the element act as a tree 1703 1704 -] LS 1705 1706 This will make the element act as a list 1707 1708 -] PU 1709 1710 This will make a macro run in a popup window 1711 1712 -] C 1713 1714 This will collapse a tree,use -C to uncollapse the tree 1715 1716 -] X 1717 1718 This will save and Exit after the macro is done 1719 1720 -] UD 1721 1722 Update data on typing 1723 1724 1725 Here is a reference section for the argument codes,use them like "$TX,T=\"123\"$ 1726 " 1727 1728 -] T 1729 1730 Tag text,this is the text that gets displayed. 1731 1732 -] LEN 1733 1734 Sets the length of the DA element. 1735 1736 -] A 1737 1738 Sets the link location 1739 1740 -] LE 1741 1742 Left expression,runs an expression on left click 1743 1744 -] RE 1745 1746 Right expression,runs an expression on right click 1747 1748 -] LM 1749 1750 Left macro,runs text on left click 1751 1752 -] RM 1753 1754 Right macro,runs text on right click 1755 1756 -] RT 1757 1758 Raw type of DA 1759 1760 -] U 1761 1762 User data 1763 1764 -] SCX 1765 1766 Scroll x columns Makes a amazing scrolling effect 1767 1768 -] SX 1769 1770 Scroll x pixels 1771 1772 -] SY 1773 1774 Scroll y pixels 1775 1776 1777 Making links is easy,to do this we use "$LK,\"text\",A=\"BF:Acts,2:3\"$"; Here 1778 is a reference for the link codes: 1779 1780 -] FI 1781 1782 File index,FI="file" or FI="file,line" 1783 1784 -] FF 1785 1786 File Find,FF="file,text" 1787 1788 -] BF 1789 1790 Bible Find,BF="book,text". "text" can be a chapter/verse 1791 1792 -] HI 1793 1794 Help Index,HI="Help Index". Make help indexes via #help_index 1795 1796 -] A 1797 1798 Symbol address, takes a pointer A="0x11223344" 1799 1800 1801 Now a function reference: 1802 1803 -] DocBottom 1804 1805 Move to the bottom of the document 1806 1807 -] DocCenter 1808 1809 Make ->cur_entry be in the viewport 1810 1811 -] DocClear 1812 1813 Clear all elements except those with the +H flag 1814 1815 -] DocCollapse(collapsed,doc) 1816 1817 Collapse or un-collapse all trees in the document 1818 1819 -] DocDel 1820 1821 Delete a documents memory 1822 1823 -] DocEntryDel(doc,elem) 1824 1825 Deletes a document entry 1826 1827 -] DocEntryCopy(doc,elem) 1828 1829 Copy an element 1830 1831 -] DocInsDoc(to,from) 1832 1833 Insert a document into an other document 1834 1835 -] DocLock 1836 1837 Lock a document 1838 1839 -] DocUnlock 1840 1841 Unlock a document 1842 1843 -] DocRst 1844 1845 Reset the document 1846 1847 -] DocTop 1848 1849 Go to the top of the document 1850 1851 -] DocLineRead(filename,line) 1852 1853 Read a line from a file 1854 1855 -] DocLineWrite(filename,line,text) 1856 1857 Write a line into a file 1858 1859 -] DocRead(filename) 1860 1861 Read a document from a file 1862 1863 -] DocLoad(into_doc,ptr,len) 1864 1865 Read a document from memory into a docuemnt 1866 1867 -] DocSave(doc,len_ptr) 1868 1869 Save a document into memory 1870 1871 -] DocWrite(doc) 1872 1873 Save a document to disk. Filename is detirmnined by DocNew("filename"); 1874 1875 -] DocMenu 1876 1877 Interact with a document until a value is found 1878 1879 -] DocForm 1880 1881 Use a class's meta-data to make a form for you to fill out 1882 1883 -] DocNew(filename) 1884 1885 Make a new document that will be saved to filename 1886 1887 -] DocGR(doc,filename.GR) 1888 1889 Insert a .GR file into a document 1890 1891 -] DocPrint 1892 1893 Print text into a document 1894 1895 -] DocPut 1896 1897 Get the current document for a task 1898 1899 -] DocType(doc,filename) 1900 1901 Type a file into a document