// Visual Periodic Table 89 // A graphical periodic table written in C // Compile: tigcc -O2 vpt89.c #include #include int _ti89; char _comment[] = "Visual Periodic Table 89 v2.0"; static char tempindex = 0; static char tempsymb[] = "CKF"; static char symbol[] = "H\0\0He\0Li\0Be\0B\0\0C\0\0N\0\0O\0\0F\0\0Ne\0Na\0Mg\0Al\0Si\0P\0\0S\0\0Cl\0Ar\0K\0\0Ca\0Sc\0Ti\0V\0\0Cr\0Mn\0Fe\0Co\0Ni\0Cu\0Zn\0Ga\0Ge\0As\0Se\0Br\0Kr\0Rb\0Sr\0Y\0\0Zr\0Nb\0Mo\0Tc\0Ru\0Rh\0Pd\0Ag\0Cd\0In\0Sn\0Sb\0Te\0I\0\0Xe\0Cs\0Ba\0La\0Ce\0Pr\0Nd\0Pm\0Sm\0Eu\0Gd\0Tb\0Dy\0Ho\0Er\0Tm\0Yb\0Lu\0Hf\0Ta\0W\0\0Re\0Os\0Ir\0Pt\0Au\0Hg\0Tl\0Pb\0Bi\0Po\0At\0Rn\0Fr\0Ra\0Ac\0Th\0Pa\0U\0\0Np\0Pu\0Am\0Cm\0Bk\0Cf\0Es\0Fm\0Md\0No\0Lr\0Rf\0Db\0Sg\0Bh\0Hs\0Mt"; static char name[] = "Hydrogen\0\0\0\0\0Helium\0\0\0\0\0\0\0Lithium\0\0\0\0\0\0Beryllium\0\0\0\0Boron\0\0\0\0\0\0\0\0Carbon\0\0\0\0\0\0\0Nitrogen\0\0\0\0\0Oxygen\0\0\0\0\0\0\0Fluorine\0\0\0\0\0Neon\0\0\0\0\0\0\0\0\0Sodium\0\0\0\0\0\0\0Magnesium\0\0\0\0Aluminum\0\0\0\0\0Silicon\0\0\0\0\0\0Phosphorus\0\0\0Sulfur\0\0\0\0\0\0\0Chlorine\0\0\0\0\0Argon\0\0\0\0\0\0\0\0Potassium\0\0\0\0Calcium\0\0\0\0\0\0Scandium\0\0\0\0\0Titanium\0\0\0\0\0Vanadium\0\0\0\0\0Chromium\0\0\0\0\0Manganese\0\0\0\0Iron\0\0\0\0\0\0\0\0\0Cobalt\0\0\0\0\0\0\0Nickel\0\0\0\0\0\0\0Copper\0\0\0\0\0\0\0Zinc\0\0\0\0\0\0\0\0\0Gallium\0\0\0\0\0\0Germanium\0\0\0\0Arsenic\0\0\0\0\0\0Selenium\0\0\0\0\0Bromine\0\0\0\0\0\0Krypton\0\0\0\0\0\0" "Rubidium\0\0\0\0\0Strontium\0\0\0\0Yttrium\0\0\0\0\0\0Zirconium\0\0\0\0Niobium\0\0\0\0\0\0Molybdenum\0\0\0Technetium\0\0\0Ruthenium\0\0\0\0Rhodium\0\0\0\0\0\0Palladium\0\0\0\0Silver\0\0\0\0\0\0\0Cadmium\0\0\0\0\0\0Indium\0\0\0\0\0\0\0Tin\0\0\0\0\0\0\0\0\0\0Antimony\0\0\0\0\0Tellurium\0\0\0\0Iodine\0\0\0\0\0\0\0Xenon\0\0\0\0\0\0\0\0Cesium\0\0\0\0\0\0\0Barium\0\0\0\0\0\0\0Lanthanum\0\0\0\0Cerium\0\0\0\0\0\0\0Praseodymium\0Neodymium\0\0\0\0Promethium\0\0\0Samarium\0\0\0\0\0Europium\0\0\0\0\0Gadolinium\0\0\0Terbium\0\0\0\0\0\0Dysprosium\0\0\0Holmium\0\0\0\0\0\0Erbium\0\0\0\0\0\0\0Thulium\0\0\0\0\0\0Ytterbium\0\0\0\0Lutetium\0\0\0\0\0Hafnium\0\0\0\0\0\0Tantalum\0\0\0\0\0" "Tungsten\0\0\0\0\0Rhenium\0\0\0\0\0\0Osmium\0\0\0\0\0\0\0Iridium\0\0\0\0\0\0Platinum\0\0\0\0\0Gold\0\0\0\0\0\0\0\0\0Mercury\0\0\0\0\0\0Thallium\0\0\0\0\0Lead\0\0\0\0\0\0\0\0\0Bismuth\0\0\0\0\0\0Polonium\0\0\0\0\0Astatine\0\0\0\0\0Radon\0\0\0\0\0\0\0\0Francium\0\0\0\0\0Radium\0\0\0\0\0\0\0Actinium\0\0\0\0\0Thorium\0\0\0\0\0\0Protactinium\0Uranium\0\0\0\0\0\0Neptunium\0\0\0\0Plutonium\0\0\0\0Americium\0\0\0\0Curium\0\0\0\0\0\0\0Berkelium\0\0\0\0Californium\0\0Einstenium\0\0\0Fermium\0\0\0\0\0\0Mendelevium\0\0Nobelium\0\0\0\0\0Lawrencium\0\0\0Rutherford'm\0Dubnium\0\0\0\0\0\0Seaborgium\0\0\0Bohrium\0\0\0\0\0\0Hassium\0\0\0\0\0\0Meitnerium\0\0\0"; static short int atommass[109] = {101,400,694,901,1081,1201,1401,1600,1900,2018,2299,2431,2698,2809,3097,3206,3545,3995,3910,4008,4496,4788,5094,5200,5494,5585,5890,5869,6355,6539,6972,7259,7492,7896,7990,8380,8547,8762,8891,9122,9291,9594,9890,10107,10291,10642,10787,11241,11482,11871,12175,12760,12691,13129,13291,13733,13891,14012,14091,14424,14500,15036,15196,15725,15893,16250,16493,16726,16893,17304,17497,17849,18095,18385,18621,19020,19222,19508,19697,20059,20438,20720,20898,20898,20999,22202,22302,22603,22703,23204,23104,23803,23705,24406,24306,24700,24700,25100,25400,25700,25700,25800,25900,26100,26200,26300,26200,26500,26600}; static BYTE electroneg[109] = {21,0,10,15,20,25,30,35,40,0,9,12,15,18,21,25,30,0,8,10,13,15,16,16,15,18,18,18,19,16,16,18,20,24,28,0,8,10,12,14,16,18,19,22,22,22,19,17,17,18,19,21,25,0,7,9,1,0,0,0,0,0,0,0,0,0,0,0,0,0,13,15,17,19,22,22,22,24,19,18,18,19,22,0,7,9,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static unsigned long int temp[109] = {41|3080192,300|2031616,481|107937792,1578|214302720,2600|186777600,3670|336003072,90|6815744,82|7667712,80|7340032,51|3538944,398|77529088,949|91095040,960|181338112,1710|173998080,344|38010880,419|48824320,199|17367040,111|7471104,364|70385664,1140|116916224,1839|205258752,1960|235077632,2190|241172480,2160|194772992,1544|148242432,1835|199884800,1795|207749120,1753|198705152,1383|187891712,720|79101952,330|177143808,1237|205127680,300|59834368,517|64552960,293|23527424,143|9699328, 339|64749568,1069|110362624,1820|238354432,2152|306511872,2770|330432512,2917|321912832,2472|339279872,2610|275251200,2266|262144000,1852|225443840,1262|164626432,621|69795840,457|155975680,532|167772160,931|134348800,750|84541440,414|31719424,188|12648448,328|64094208,1025|127139840,1220|246022144,1098|233111552,1231|230162432,1310|224591872,1468|180879360,1370|136183808,1122|124321792,1611|231538688,1660|218955776,1712|187564032,1774|196280320,1822|184156160,1800|132841472, 1124|97845248,1956|236912640,2530|321257472,3296|373555200,3710|390594560,3480|388431872,3350|349306880,2710|290324480,2072|268697600,1367|203620352,261|43057152,604|115343360,628|133693440,571|121896960,554|82706432,602|41746432,229|15597568,327|64028672,1000|94371840,1350|229376000,2050|333578240,1900|19660800,1432|269877248,940|275382272,941|231473152,1294|190513152,1640|19660800,300|19660800,300|19660800,300|19660800,300|19660800,300|19660800,300|19660800,300|19660800,300|19660800,300|19660800,300|19660800,300|19660800,300|19660800,300|19660800}; static char *types[8] = {"Alkali metal","Alkali earth metal","Transition metal","Lanthanide series","Actinide series","Metal","Nonmetal","Inert gas"}; static char type[110]="1812777778126777781233333333336677781233333333336667781244444444444444433333333366667812555555555555555333303"; static unsigned short int oxnum[109] = { 256,0, 256,512,1024,2048,5124,2,1,0, 256,512,1024,2048,5120,10242,1,0, 256,512,1024,2048,7168,9216,18944,1536,1536,3584,768,512,1024,2560,5124,10242,1,0, 256,512,1024,2048,7168,15872,32256,3584,3072,3584,256,512,1024,2560,5124,10242,1,0, 256,512,1024,3072,3072,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024, 2048,4096,15872,31744,43008,3072,3584,1280,768,1280,2560,1024,10754,1,0, 256,512,0,2048,6144,10240,31744,5120,1024,1024,1024,1024,1024,1024,1536,0,0,0,0,0,0,0,0}; static char attrs[] = "reactive \0\0\0\0\0brittle \0\0\0\0\0\0silver \0\0\0\0\0\0\0white \0\0\0\0\0\0\0\0gray \0\0\0\0\0\0\0\0\0metallic \0\0\0\0\0semimetallic \0inert \0\0\0\0\0\0\0\0hard \0\0\0\0\0\0\0\0\0soft \0\0\0\0\0\0\0\0\0magnetic \0\0\0\0\0nonmetallic \0\0yellow \0\0\0\0\0\0\0green \0\0\0\0\0\0\0\0brown \0\0\0\0\0\0\0\0red \0\0\0\0\0\0\0\0\0\0blue \0\0\0\0\0\0\0\0\0crystalline \0\0poisonous \0\0\0\0radioactive \0\0black \0\0\0\0\0\0\0\0"; static BYTE aorder[21] = {18,19,0,7,10,11,17,5,6,8,9,1,2,3,4,20,14,15,16,13,12};//set order of attributes unsigned long int attr[109] = {1,128,45,50,322,0,0,1024,0,0,525,12,0,64,2048,6144,12288,128,545,44,556, 44,44,48,46,1068,1068,44,49184,65576,32,131418,262208,64,262144,0,33,33, 44,32,52,32,524320,56,44,556,40,44,556,32,65610,78,1114113,0,297,517,32, 560,36,36,524320,290,548,44,32,32,36,32,52,548,44,32,40,32,44,65576,298, 160,4640,32,66096,65584,32800,524320,524288,524288,524320,524333,524320, 524320,524320,524321,524320,524320,524320,524288,524320,524288,524288, 524288,524288,524320,524320,0,0,0,0,0,0}; static unsigned long gridpos[9] = {0x20001,0x3003F,0x3003F,0x3FFFF,0x3FFFF,0x37FFF,0x37E00,0x7FFF,0x7FFF}; static SCR_RECT screen_area={0,0,159,99}; static SCR_RECT draw_area ={5,8,154,89}; static BYTE cursorx = 0; static BYTE cursory = 0; static int key = 268; static signed char xoffset = 10; char *capitalize(char *str); void draw_str(int x,int y,char *str); void chemprint(int x, int y, char *str); void drawkoeff(int x, int y, char *str, char *koeff); void input_str(char *str,int x,int y,int maxlen); SCR_RECT *MakeScrRect(int x0, int y0, int x1, int y1); char *sprintdec(char buffer[], int num, int decimals); char *tempconv(char buffer[], int degrees); void draw_window(int x1, int y1, int x2, int y2, char *title); void getcoords(int index, BYTE *x, BYTE *y); int getindex(); void draw_grid(int x, int y); char *capitalize(char *str) { int i = 1; str[0] = toupper(str[0]); for(; i < strlen(str); i++) str[i] = tolower(str[i]); return str; } void draw_str(int x,int y,char *str) { DrawStr(x,y,str,A_REPLACE); } void chemprint(int x, int y, char *str) { int i = 0; char cbuf[2] = " "; while(cbuf[0] = str[i]) { if(isdigit(cbuf[0])) { FontSetSys(F_4x6); draw_str(x,y+4,cbuf); x += 4; } else { FontSetSys(F_6x8); draw_str(x,y,cbuf); x += 6; } i++; } FontSetSys(F_4x6); } void drawkoeff(int x, int y, char *str, char *koeff) { int i = 0,k,nkoeff = 0; char cbuf[2] = " ",cbuf2[8],separator = TRUE; while(str[i]) { while(str[i] == ' ') i++;//skip spaces if(/*i == 0 || */separator) { while(str[i] == ' ' || isdigit(str[i])) i++;//skip spaces and koefficients separator = FALSE; nkoeff++; for(k = 0; koeff[nkoeff] != ',' && koeff[nkoeff] != '}'; nkoeff++,k++) cbuf2[k] = koeff[nkoeff]; cbuf2[k] = 0; if(strcmp(cbuf2,"1")) { draw_str(x,y,cbuf2); x += 4*k; } x++; } if(str[i] == '+' || str[i] == '\26') { separator = TRUE; x++; } cbuf[0] = str[i]; draw_str(x,y + (isdigit(str[i]) ? 2 : 0),cbuf); if(separator) x++; x += FontCharWidth(str[i]); i++; } strcpy(koeff,koeff+nkoeff); } void input_str(char *str,int x,int y,int maxlen) { int i=strlen(str),key=0; while(key!=13) { strcpy(str+i,"_ "); draw_str(x,y,str); key = ngetchx(); ST_busy(ST_CLEAR); if(i < maxlen && (key >= ' ' && key <= '~')) str[i++] = key; if(key == 257 && i) i--; if(key == 263 && i)//Clear { for(i = maxlen; i > 0; i--) draw_str(x+i*4,y," "); } if(key == 264)//Escape { str[0] = 0; return; } } draw_str(x+DrawStrWidth(str,F_4x6)-9,y," "); str[i]=0; } SCR_RECT *MakeScrRect(int x0, int y0, int x1, int y1) { static SCR_RECT rect;// = {x0,y0,x1,y1}; rect.xy.x0 = x0; rect.xy.x1 = x1; rect.xy.y0 = y0; rect.xy.y1 = y1; return ▭ } char *sprintdec(char buffer[], int num, int decimals) { int i,len; sprintf(buffer,"%d ",num); len = strlen(buffer); for(i = 1; i <= decimals; i++) buffer[len-i] = buffer[len-i-1]; buffer[len-i] = '.'; return buffer; } char *tempconv(char buffer[], int degrees) { if(degrees) { switch(tempindex){ case 1: degrees = degrees+273; break; case 2: degrees = 5*degrees/9+32; } buffer[sprintf(buffer,"%d ",degrees)-1] = tempsymb[tempindex]; } else//no temp data buffer[0] = 0; return buffer; } void draw_window(int x1, int y1, int x2, int y2, char *title) { int i,w = DrawStrWidth(title,F_4x6)/2; SCR_RECT rect = {x1,y1,x2,y2}; ScrRectFill(&rect,&screen_area,A_REVERSE); for(i=0;i<=3;i++) { if(i != 2) DrawClipRect(MakeWinRect(i+x1,i+y1,x2-i,y2-i),&screen_area,A_NORMAL); } rect.xy.x0 += 3; rect.xy.x1 -= 3; rect.xy.y1 = y1 + 6; ScrRectFill(&rect,&screen_area,A_NORMAL); for(i=1;i<=5;i+=4) DrawLine(x1+2,y1+i,x2-2,y1+i,A_REVERSE); rect.xy.x0 = 79-1-w; rect.xy.x1 = 79+1+w; ScrRectFill(&rect,&screen_area,A_NORMAL); FontSetSys(F_4x6); DrawStr(79-w,y1+1,title,A_REVERSE); } int getindex()//return atomnumber from gridpos { register int row,col,i,pos; for(row = 0,pos = 1; row < 9; row++) { if(row == 7) pos = 57; else if(row == 8) pos = 89; for(col = 0; col < 18; col++) if((gridpos[row] << (col+14)) >> 31) { if(col == cursorx && row == cursory) return pos-1; if(++pos == 57) pos = 72; else if(pos == 89) pos = 104; } } return pos-1; } void getcoords(int index, BYTE *x, BYTE *y)//return gridpos from atomnumber { register int row,col,i,pos; for(row = 0,pos = 1; row < 9; row++) { if(row == 7) pos = 57; else if(row == 8) pos = 89; for(col = 0; col < 18; col++) if((gridpos[row] << (col+14)) >> 31) { if(pos == index) { *x = col; *y = row; return; } if(++pos == 57) pos = 72; else if(pos == 89) pos = 104; } } return; } void draw_grid(int x, int y) { register int row,col,i,pos; int mov,cent,w; char buffer[3],*chr; FontSetSys(F_4x6); for(col = 0,mov = 4; col < 18; col++) { if(col == 9) mov = 2; sprintf(buffer,"%d",col+1); for(i = 0; buffer[i]; i++) DrawClipChar(x+col*11+mov+4*i,y-6,buffer[i],&draw_area,A_REPLACE); } for(row = 0; row < 7; row++) { sprintf(buffer,"%d",row+1); DrawClipChar(x-5,y+2+row*8,buffer[0],&draw_area,A_REPLACE); DrawClipChar(x+200,y+2+row*8,75+row,&draw_area,A_REPLACE); } for(row = 0,mov = 0,pos = 1; row < 9; row++) { if(row == 7) { mov = 3; pos = 57; } else if(row == 8) pos = 89; for(col = 0; col < 18; col++) if((gridpos[row] << (col+14)) >> 31) { DrawClipRect(MakeWinRect(x+col*11,y+row*8+mov,x+col*11+11,y+row*8+8+mov),&draw_area,A_NORMAL); if(pos <= 109) { chr = (char *)(symbol+(pos-1)*3); w = FontCharWidth(chr[0]); cent = 5-(w + (chr[1] ? FontCharWidth(chr[1]) : 0))/2; for(i = 0; chr[i]; i++,cent+=w) DrawClipChar(x+col*11+cent,y+row*8+mov+2,chr[i],&draw_area,A_NORMAL); } if(++pos == 57) pos = 72; if(pos == 89) pos = 104; } } } void _main(void) { register int i; int prevx = -2,prevy = -2; int row,col,mov,pos,a,b,c,len,mass; ti_float sum,partsum; char cbuf[30],cbuf2[30],info[34],info2[34],SearchString[60]; LCD_BUFFER buffer,TIOSScreen; LCD_save(TIOSScreen); ClrScr(); draw_window(0,0,159,93,_comment); draw_grid(xoffset,14); while(key != 264)//escape { if(key == 43 && pos < 108) pos++;//+ key else if(key == 45 && pos > 0) pos--;//- key else if(key == 344)//Right do if(++cursorx > 17) cursorx = 0; while(!((gridpos[cursory] << (cursorx+14)) >> 31)); else if(key == 338)//Left do if(--cursorx > 17) cursorx = 17; while(!((gridpos[cursory] << (cursorx+14)) >> 31)); else if(key == 337)//Up do if(--cursory > 8) cursory = 8; while(!((gridpos[cursory] << (cursorx+14)) >> 31)); else if(key == 340)//Down do if(++cursory > 8) cursory = 0; while(!((gridpos[cursory] << (cursorx+14)) >> 31)); if(key == 43 || key == 45)//+ or - key getcoords(pos+1,&cursorx,&cursory); if(cursorx != prevx || cursory != prevy) { mov = xoffset; if(xoffset == 10 && cursorx > 11) xoffset = -52; else if(xoffset == -52 && cursorx < 6) xoffset = 10; if(xoffset != mov) { ClrScr(); draw_window(0,0,159,93,_comment); draw_grid(xoffset,14); mov = prevy < 7 ? 15 : 18; } else { mov = prevy < 7 ? 15 : 18; ScrRectFill(MakeScrRect(xoffset+prevx*11+1,prevy*8+mov,xoffset+prevx*11+10,prevy*8+6+mov),&draw_area,A_XOR); } mov = cursory < 7 ? 15 : 18; ScrRectFill(MakeScrRect(xoffset+cursorx*11+1,cursory*8+mov,xoffset+cursorx*11+10,cursory*8+6+mov),&draw_area,A_XOR); prevx = cursorx; prevy = cursory; pos = getindex(); FontSetSys(F_8x10); ScrRectFill(MakeScrRect(xoffset+65,16,xoffset+95,37),&screen_area,A_REVERSE); draw_str(xoffset+(symbol[pos*3+1]?70:74),22,(char *)(symbol+pos*3)); FontSetSys(F_4x6); draw_str(70+xoffset,16,sprintdec(cbuf,atommass[pos],2)); printf_xy(70+xoffset,32,"%3d",pos+1); } if(key == 4360)//2nd-esc { off(); key = 0; } else if(key == 268)//F1: Help/About { int i; LCD_save(buffer); draw_window(18,7,141,90,"About"); FontSetSys(F_8x10); draw_str(44,18,"* VPT89 *"); FontSetSys(F_4x6); draw_str(36,31,"Arrowkeys, +/-: Navigate"); draw_str(40,39,"Enter: Display, Esc: Exit"); draw_str(28,47,"F1: Help, F2: Scale, F3: Search"); draw_str(32,55,"F4: Mass calc, F5: Eq. solver"); draw_str(33,63,"Programming: Markus Kvist"); draw_str(44,71,"theraven@swipnet.se"); draw_str(33,79,"Special thanks: Janne West"); ngetchx(); LCD_restore(buffer); key = 0; } else if(key == 269)//F2: set temp scale { LCD_save(buffer); draw_window(19,28,140,71,"Set scale"); do { strcpy(cbuf,"Temperature unit (C/K/F): "); cbuf[26] = tempsymb[tempindex]; draw_str(28,40,cbuf); draw_str(28,49,"Celsius / Kelvin / Farenheit"); draw_str(28,58,"Use [Left] / [Right] to change"); if((key = ngetchx()) == 344 && tempindex < 2) tempindex++; if(key == 338 && tempindex > 0) tempindex--; } while(key != 13 && key != 264); LCD_restore(buffer); key = 0; } else if(key == 270)//F3: Search { LCD_save(buffer); draw_window(19,36,140,62,"Search"); SearchString[0] = 0; input_str(SearchString,28,48,20); capitalize(SearchString); if(isdigit(SearchString[0]))//atomnumber { for(i = 0; i < 109; i++) { sprintf(cbuf,"%d",i+1); if(!strcmp(cbuf,SearchString)) break; } } else if(strlen(SearchString) <= 2)//symbol { for(i = 0; i < 109; i++) if(!strcmp((char *)(symbol+i*3),SearchString)) break; } else if(strlen(SearchString) > 2)//name { for(i = 0; i < 109; i++) if(!strncmp(name+i*13,SearchString,strlen(name+i*13) < strlen(SearchString) ? strlen(name+i*13) : strlen(SearchString)))//search for name or part of it break; } if(i != 109)//Found { getcoords(i+1,&cursorx,&cursory); key = 13;//Open Display } else key = 0; LCD_restore(buffer); } else if(key == 271)//F4: Molecule mass { LCD_save(buffer); draw_window(10,23,149,76,"Calculate mass"); draw_str(20,35,"Molecule:"); SearchString[0] = 0; input_str(SearchString,20,43,20); for(i = 20; i < 140; i += 4) draw_str(i,43," "); chemprint(20,43,SearchString); draw_str(20,55,"Mass:"); len = strlen(SearchString); sum = partsum = ZERO; for(a = c = mass = 0; a <= len; a++) { if(c >= 2 || a == len) { if(!(b = atoi(SearchString + a))) b = 1; c -= 2; if(c == 1)//in parenthesis? partsum = fadd(partsum,flt(mass*b)); else if(c >= 0) { if(c > 0) sum = fadd(sum,fmul(partsum,flt(b))); else sum = fadd(sum,flt(mass*b)); partsum = ZERO; c = 0; } sprintf(cbuf,"%#.2f",fdiv(sum,FLT(100))); draw_str(40,55,cbuf); } if(SearchString[a] == '(') c = 1; else if(SearchString[a] == ')') c = 4; else if(isupper(SearchString[a])) { b = a; cbuf[0] = SearchString[a]; if(islower(SearchString[a+1])) cbuf[1] = SearchString[++a]; cbuf[a-b+1] = 0; for(i = 0; i < 109; i++) if(!strcmp((char *)(symbol+i*3),cbuf)) { mass = atommass[i]; c += 2; break; } } } if(len) { draw_str(20,63,"[Sto]: Copy to clipboard"); if(ngetchx() == 258) CB_replaceTEXT(cbuf,strlen(cbuf),1);//copy to clipboard } key = 0; LCD_restore(buffer); } else if(key == 272)//F5: Balance Formula { BYTE index[20],atom[20][20],temp[20],ntemp,pos,nmol,nindex,x,y; ntemp = nmol = nindex = 0; LCD_save(buffer); draw_window(0,24,159,74,"Chemistry Equation Solver"); while(TRUE) { draw_str(8,35,"Enter reagents (separated with +)"); SearchString[0] = cbuf[0] = 0; input_str(SearchString,8,43,24); if(!SearchString[0])//no input break; strcat(SearchString," \26 "); draw_str(8,51,"Enter products (separated with +)"); input_str(cbuf,8,59,24); if(!cbuf[0])//no input break; ScrRectFill(MakeScrRect(4,31,155,70),&screen_area,A_REVERSE);//clear window draw_str(8,35,"Please wait..."); strcat(SearchString,cbuf); for(a = 0; a < 20; a++) { index[a] = 0; for(b = 0; b < 20; b++) atom[b][a] = 0; } len = strlen(SearchString); for(a = c = 0; a <= len; a++) { if(c >= 2 || a == len)//found an atom or end parenthesis { if(!(b = atoi(SearchString + a))) b = 1;//see if there is a number c -= 2; if(c < 2) { if(c == 1) temp[pos] += b-1; else atom[nmol][pos] += b-1; } else if(c >= 0)//outside of parenthesis { if(c > 0)//end parenthesis { for(y = 0; y < 20; y++) { atom[nmol][y] += b*temp[y];//add found contents to first list } } c = 0; } } if(SearchString[a] == '+' || SearchString[a] == '\26') nmol++; else if(SearchString[a] == '(') { for(y = 0; y < 20; y++)//clear temp var before use temp[y] = 0; c = 1; } else if(SearchString[a] == ')') c = 4; else if(isupper(SearchString[a])) { b = a; cbuf[0] = SearchString[a]; if(islower(SearchString[a+1])) cbuf[1] = SearchString[++a]; cbuf[a-b+1] = 0;//cbuf now contains an atom symbol for(i = 0; i < 109; i++)//find atomnumber if(!strcmp((char *)(symbol+i*3),cbuf)) { i++; //add atomnumber to list //find matching atom number or pick new slot for(pos = 0; index[pos] && index[pos] != i; pos++); if(!index[pos]) index[pos] = i; if(c == 1) temp[pos]++; else atom[nmol][pos]++; c += 2; break; } } }//end for { char expr[1024] = "abs(left(mat\22list(rowSwap(rref([",result[128]; HANDLE hResult; reset_control_flags(); for(pos = strlen(expr),nindex = 0; index[nindex]; nindex++,pos+=2)//count through atoms { for(y = 0; y <= nmol; y++)//count through molecules pos += sprintf(expr+pos,"%d,",(int)atom[y][nindex]); strcat(expr,(y == nmol ? "0;" : "0;1")); } for(x = 1; x <= nmol+1; x++) strcat(expr,(x == nmol+1 ? ",1" : ",0")); pos = strlen(expr); sprintf(expr+pos,"])™,1,%d)),%d))\26tmp",(int)(nmol+2),(int)(nmol+1)); push_parse_text(expr);//push to estack NG_rationalESI(top_estack);//evaluate hResult = display_statements(top_estack, 1, 1);//get result strcpy(result,HeapDeref(hResult));//save result HeapFree(hResult); HeapFree(HS_popEStack());//clear estack strcat(result,"/"); for(x = 0; x < nmol; x++) sprintf(result+strlen(result),"gcd(tmp[%d],",x+1); sprintf(result+strlen(result),"tmp[%d]",x+1); for(x = 0; x < nmol; x++) strcat(result,")"); strcat(result,"\26tmp"); push_parse_text(result);//push to estack NG_rationalESI(top_estack);//evaluate hResult = display_statements(top_estack, 1, 1);//get result strcpy(result,HeapDeref(hResult));//save result HeapFree(hResult); HeapFree(HS_popEStack());//clear estack //Delete tmp variable SymDel($(tmp)); if(strchr(result,'u'))//undefined result { draw_str(8,35,"Could not solve equation."); draw_str(8,43,"Please recheck formula."); ngetchx(); break; } draw_str(8,35,"The balanced formula is:"); if(strlen(SearchString) > 24) { pos = strchr(SearchString,'\26')-SearchString; strncpy(expr,SearchString,pos+1); expr[pos+1] = 0; drawkoeff(8,45,expr,result); draw_str(8,55,strcpy(cbuf,"\26")); drawkoeff(14,55,SearchString+pos+2,result); } else drawkoeff(8,43,SearchString,result); } ngetchx(); break; }//end while(TRUE) LCD_restore(buffer); key = 0; } else key = ngetchx(); if(key == 13)//Display { do { LCD_save(buffer); if(key == 43 || key == 45 || key >= 337 && key <= 344)//+ or - or arrow key { if((key == 43 || key == 344 || key == 337) && pos < 108) pos++;//+/right/up key else if((key == 45 || key == 338 || key == 340) && pos > 0) pos--;//-/down/left key getcoords(pos+1,&cursorx,&cursory); } draw_window(18,7,141,93,"Info"); pos = getindex(); FontSetSys(F_6x8); draw_str(26,16,name+pos*13); FontSetSys(F_4x6); printf_xy(110,18,"%d",pos+1); draw_str(124,18,(char *)(symbol+pos*3)); draw_str(26,27,"Type:"); draw_str(72,27,types[type[pos]-'1']); draw_str(26,34,"Atomic mass:"); draw_str(72,34,sprintdec(cbuf,atommass[pos],2)); draw_str(26,43,"Melt point:"); draw_str(72,43,tempconv(cbuf,(int)temp[pos]-300)); draw_str(26,50,"Boil point:"); draw_str(72,50,tempconv(cbuf,(int)(temp[pos]>>16)-300)); draw_str(26,59,"Electroneg:"); if(electroneg[pos]) draw_str(72,59,sprintdec(cbuf,electroneg[pos],1)); cbuf2[0] = 0; for(i = 7; i >= 0; i--) if((oxnum[pos] >> i)&1) { sprintf(cbuf," -%d",i+1); strcat(cbuf2,cbuf); } for(i = 0; i < 8; i++) if((oxnum[pos] >> (i+8))&1) { sprintf(cbuf," +%d",i+1); strcat(cbuf2,cbuf); } draw_str(26,66,"Ox numbers:"); draw_str(72,66,cbuf2); info[0] = info2[0] = 0; if(pos < 104) for(i = 0; i < 21; i++) if((attr[pos]>>aorder[i])&1) if(i < 9) strcat(info,attrs+aorder[i]*14); else strcat(info2,attrs+aorder[i]*14); draw_str(26,75,info); draw_str(26,82,info2); key = ngetchx(); LCD_restore(buffer); } while(key == 43 || key == 45 || key >= 337 && key <= 344); key = 0; } } key = 0; //static variable LCD_restore(TIOSScreen); } // Please send any questions, ideas or source improvements to: // e-mail: theraven@swipnet.se // ICQ: 13652495 // // Markus Kvist // // If you copy or modify this code, please leave these lines here.