editor.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/stat.h>
  4. #include <X11/Xlib.h>
  5. #include <X11/Xutil.h>
  6. #include <X11/Xos.h>
  7. #include <X11/Xatom.h>
  8. #include <X11/keysym.h>
  9. #include <X11/Intrinsic.h>
  10. #include <X11/cursorfont.h>
  11. #include <dirent.h>
  12. #include <fcntl.h>
  13. #include <zlib.h>
  14. #include "xinit.h"
  15. #include "xstoneage.h"
  16. //other variables
  17. extern int alt_pressed;
  18. extern int mousebutton_pressed;
  19. extern int mousex,mousey;
  20. int currtile,tilewin,codewin,codeptr;
  21. level levelmap;
  22. extern XImage *tiles;
  23. extern XImage *sidebars;
  24. extern XImage *bgr;
  25. extern XImage *fonts;
  26. int fr,fg,fb; //default foreground
  27. int br,bg,bb; //default background
  28. int ifr,ifg,ifb; //default input foreground
  29. int ibr,ibg,ibb; //default input background
  30. int val3d; //sharpness of 3d boxes
  31. XWindowAttributes win_attr;
  32. /**
  33. * create color variations
  34. */
  35. long MkDarkColor(int r,int g,int b)
  36. {
  37. r=br-val3d; g=bg-val3d; b=bb-val3d; if(r<0) r=0; if(g<0) g=0; if(b<0) b=0;
  38. if (red_shift>=0) r<<=red_shift; else r>>=-red_shift;
  39. if (green_shift>=0) g<<=green_shift; else g>>=-green_shift;
  40. if (blue_shift>=0) b<<=blue_shift; else b>>=-blue_shift;
  41. r&=vsl->red_mask;
  42. g&=vsl->green_mask;
  43. b&=vsl->blue_mask;
  44. return r+g+b;
  45. }
  46. long MkLightColor(int r,int g,int b)
  47. {
  48. r=br+val3d; g=bg+val3d; b=bb+val3d; if(r>255) r=255; if(g>255) g=255; if(b>255) b=255;
  49. if (red_shift>=0) r<<=red_shift; else r>>=-red_shift;
  50. if (green_shift>=0) g<<=green_shift; else g>>=-green_shift;
  51. if (blue_shift>=0) b<<=blue_shift; else b>>=-blue_shift;
  52. r&=vsl->red_mask;
  53. g&=vsl->green_mask;
  54. b&=vsl->blue_mask;
  55. return r+g+b;
  56. }
  57. /**
  58. * draw a button
  59. */
  60. void button(int pressed, int x, int y, int width, int height){
  61. int dco,co,lco,i,r,g,b;
  62. dco=MkDarkColor(r,g,b);
  63. co=MkColor(br,bg,bb);
  64. lco=MkLightColor(r,g,b);
  65. if(pressed==TRUE){i=dco; dco=lco; lco=i;}
  66. XSetForeground(dis, gc, lco);
  67. XDrawRectangle(dis, win, gc, x+1, y, width-3, 1);
  68. XDrawRectangle(dis, win, gc, x, y+1, 1, height-3);
  69. XSetForeground(dis, gc, dco);
  70. XDrawRectangle(dis, win, gc, x+1, y+height-2, width-3, 1);
  71. XDrawRectangle(dis, win, gc, x+width-2, y+1, 1, height-3);
  72. }
  73. /**
  74. * change cursor
  75. */
  76. void SetCursor(Cursor cursor)
  77. {
  78. XSetWindowAttributes swa;
  79. swa.cursor=XCreateFontCursor(dis,cursor);
  80. XChangeWindowAttributes(dis, win, CWCursor, &swa);
  81. }
  82. /**
  83. * draw editor window
  84. */
  85. void exposehandlered(){
  86. int i,j;
  87. char dummy[8];
  88. byte tmp;
  89. XGetWindowAttributes(dis, win, &win_attr);
  90. XSetForeground(dis, gc, MkColor(bg,bg,bg));
  91. XFillRectangle(dis, win, gc, 640, 0, 100, 400);
  92. //menu
  93. XSetForeground(dis, gc, MkColor(fr,fg,fb));
  94. XSetFont(dis,gc,XLoadFont(dis,"-*-*-*-*-*-*-14-*-*-*-*-*-*-*"));
  95. XDrawString(dis,win,gc,660,35,"<- Back",7);
  96. XDrawString(dis,win,gc,660,75,"New",3);
  97. XDrawString(dis,win,gc,660,105,"Save",4);
  98. XDrawString(dis,win,gc,660,135,"Load",4);
  99. XDrawString(dis,win,gc,660,165,"Backgrnd",8);
  100. XDrawString(dis,win,gc,660,195,"Tile Set",8);
  101. XDrawString(dis,win,gc,700,225,"...",3);
  102. XDrawString(dis,win,gc,660,275,"Time +/=",8);
  103. XDrawString(dis,win,gc,650,315,"Code:",5);
  104. XDrawString(dis,win,gc,660,335,levelmap.code,strlen(levelmap.code));
  105. XDrawString(dis,win,gc,650,355,"Next level:",11);
  106. XDrawString(dis,win,gc,660,375,levelmap.nextlink,strlen(levelmap.nextlink));
  107. button(FALSE,640,0,win_attr.width-640,win_attr.height);
  108. button(FALSE,650,20,win_attr.width-660,20);
  109. button(FALSE,650,60,win_attr.width-660,20);
  110. button(FALSE,650,90,win_attr.width-660,20);
  111. button(FALSE,650,120,win_attr.width-660,20);
  112. button(FALSE,650,150,win_attr.width-660,20);
  113. button(FALSE,650,180,win_attr.width-660,20);
  114. button(TRUE,650,210,36,36);
  115. button(tilewin,690,210,win_attr.width-700,20);
  116. button(FALSE,650,260,win_attr.width-660,20);
  117. button(codewin%2,650,320,win_attr.width-660,20);
  118. button(codewin/2,650,360,win_attr.width-660,20);
  119. XPutImage(dis, win, gc, tiles, (currtile/3)*32, (currtile%3)*32+levelmap.tileset*96,652,212,32,32);
  120. //scene
  121. for(i=0;i<11;i++){
  122. for(j=0;j<20;j++){
  123. tmp=levelmap.map[i*20+j];
  124. if(tmp==0xff) {
  125. XSetForeground(dis, gc, MkColor(255,255,255));
  126. XFillRectangle(dis, win, gc, j*32, i*32+31, 31, 1);
  127. XFillRectangle(dis, win, gc, j*32+31, i*32, 1, 31);
  128. XPutImage(dis, win, gc, bgr, levelmap.tileset*640+j*32,levelmap.background*352+i*32,j*32,i*32,31,31);
  129. } else {
  130. XPutImage(dis, win, gc, tiles, (tmp/3)*32, (tmp%3)*32+levelmap.tileset*96,j*32,i*32,32,32);
  131. }
  132. }
  133. }
  134. //side bar and time to solve puzzle
  135. XPutImage(dis, win, gc, sidebars, 0, levelmap.sidebar*45,0,win_attr.height-48,640,45);
  136. XSetForeground(dis, gc, MkColor(255,255,255));
  137. sprintf(dummy,"%d",levelmap.soltime);
  138. for(i=0;i<strlen(dummy);i++){
  139. XPutImage(dis, win, gc, fonts, (dummy[i]-'0')*16, 34,95-(strlen(dummy)-i)*16,368,16,16);
  140. }
  141. if(tilewin){
  142. XPutImage(dis, win, gc, tiles, 0, levelmap.tileset*96,(640-352)/2,140,352,96);
  143. button(TRUE,(640-352)/2-2,138,356,100);
  144. button(FALSE,(640-352)/2-4,136,360,104);
  145. }
  146. XSync(dis,FALSE);
  147. }
  148. /**
  149. * read a level map
  150. */
  151. void readmap(char* filename){
  152. char fn[256];
  153. int f;
  154. if(filename==NULL || strlen(filename)==0){
  155. if(strlen(levelmap.code)<6){
  156. printf("No legal code given, nothing to be load.\n"); fflush(stdout); return;
  157. }else{
  158. strcpy(fn,getenv("HOME"));
  159. strcat(fn,"/.xstoneage/");
  160. strcat(fn,levelmap.code);
  161. strcat(fn,".map");
  162. filename=fn;
  163. }
  164. }
  165. printf("Loading: %s...",filename);
  166. fflush(stdout);
  167. f=open(filename,O_RDONLY);
  168. if(f<3){
  169. printf(" not found.\n"); fflush(stdout);
  170. } else {
  171. read(f,&levelmap,sizeof(level));
  172. printf(" done.\n"); fflush(stdout);
  173. }
  174. close(f);
  175. }
  176. /**
  177. * save a level map
  178. */
  179. void savemap(char* filename){
  180. char fn[256];
  181. int f,sp=0,ep=0;
  182. for(f=0;f<220;f++) {
  183. if(levelmap.map[f]==12) sp++;
  184. if(levelmap.map[f]==13) ep++;
  185. }
  186. if(filename==NULL || strlen(filename)==0){
  187. if(strlen(levelmap.code)<6){
  188. printf("No legal code given, NOT SAVED.\n"); fflush(stdout); return;
  189. } else if(sp!=1||ep!=1) {
  190. printf("Must have one start and exit blocks, NOT SAVED.\n"); fflush(stdout); return;
  191. } else {
  192. strcpy(fn,getenv("HOME"));
  193. strcat(fn,"/.xstoneage/");
  194. mkdir((const char*)&fn,RIGHTS(7,5,5));
  195. strcat(fn,levelmap.code);
  196. strcat(fn,".map");
  197. filename=fn;
  198. }
  199. }
  200. SetCursor(WORKINGPTR); XFlush(dis);
  201. printf("Saving: %s\n",filename);
  202. fflush(stdout);
  203. f=open(filename,O_CREAT|O_WRONLY,RIGHTS(6,4,4));
  204. write(f,&levelmap,sizeof(level));
  205. close(f);
  206. sleep(1);
  207. SetCursor(STANDARDPTR);
  208. XFlush(dis);
  209. }
  210. /**
  211. * create a new, empty level map
  212. */
  213. void newmap(){
  214. int f;
  215. levelmap.code[0]=0;
  216. levelmap.code[1]=0;
  217. levelmap.code[2]=0;
  218. levelmap.code[3]=0;
  219. levelmap.code[4]=0;
  220. levelmap.code[5]=0;
  221. levelmap.code[6]=0;
  222. if(levelmap.nextlink!=0) {
  223. strcpy(levelmap.code,levelmap.nextlink);
  224. levelmap.nextlink[0]=0;
  225. }
  226. levelmap.tileset=0;
  227. levelmap.background=0;
  228. levelmap.sidebar=0;
  229. levelmap.soltime=100;
  230. for(f=0;f<220;f++)
  231. levelmap.map[f]=0xff;
  232. }
  233. void editor()
  234. {
  235. int f;
  236. char c;
  237. //default colors
  238. br=bg=bb=150;
  239. fr=fg=fb=0;
  240. ibr=ibg=ibb=255;
  241. ifr=ifg=ifb=0;
  242. val3d=63;
  243. //start with empty map
  244. newmap();
  245. levelmap.nextlink[0]='S';
  246. levelmap.nextlink[1]='R';
  247. levelmap.nextlink[2]='T';
  248. levelmap.nextlink[3]='L';
  249. levelmap.nextlink[4]='E';
  250. levelmap.nextlink[5]='V';
  251. levelmap.nextlink[6]=0;
  252. tilewin=0;
  253. exposehandlered();
  254. //menu comes here
  255. while (1) {
  256. report.type=None;
  257. XNextEvent(dis, &report);
  258. switch (report.type) {
  259. case ButtonPress:
  260. #if DEBUG==TRUE
  261. printf("Mouse button pressed at %d %d.\n",report.xbutton.x,report.xbutton.y);
  262. #endif
  263. mousebutton_pressed=TRUE;
  264. mousex=report.xbutton.x;
  265. mousey=report.xbutton.y;
  266. XGetWindowAttributes(dis, win, &win_attr);
  267. if(tilewin==0){
  268. if (mousex<=640 && mousey<=11*32) {
  269. f=(mousey/32*20)+mousex/32;
  270. if(report.xbutton.button==1) levelmap.map[f]=currtile;
  271. if(report.xbutton.button==3) levelmap.map[f]=0xff;
  272. exposehandlered();
  273. }
  274. if (mousex<=640 && mousey>11*32) {
  275. if(report.xbutton.button==1 && levelmap.sidebar<(sidebars->height/45-1)) levelmap.sidebar++;
  276. if(report.xbutton.button==3 && levelmap.sidebar>0) levelmap.sidebar--;
  277. exposehandlered();
  278. }
  279. if (mousex>=650 && mousex<=win_attr.width-10 && mousey>=20 && mousey<=40) {
  280. button(TRUE,650,20,win_attr.width-660,20);
  281. while(report.type!=ButtonRelease){XNextEvent(dis, &report);}
  282. return;
  283. }
  284. if (mousex>=650 && mousex<=win_attr.width-10 && mousey>=60 && mousey<=80) {
  285. button(TRUE,650,60,win_attr.width-660,20);
  286. newmap();
  287. }
  288. if (mousex>=650 && mousex<=win_attr.width-10 && mousey>=90 && mousey<=110) {
  289. button(TRUE,650,90,win_attr.width-660,20);
  290. savemap(NULL);
  291. }
  292. if (mousex>=650 && mousex<=win_attr.width-10 && mousey>=120 && mousey<=140) {
  293. button(TRUE,650,120,win_attr.width-660,20);
  294. readmap(NULL);
  295. }
  296. if (mousex>=650 && mousex<=win_attr.width-10 && mousey>=150 && mousey<=170) {
  297. button(TRUE,650,150,win_attr.width-660,20);
  298. if(report.xbutton.button==1 && levelmap.background<(bgr->height/352-1)) levelmap.background++;
  299. if(report.xbutton.button==3 && levelmap.background>0) levelmap.background--;
  300. while(report.type!=ButtonRelease){XNextEvent(dis, &report);}
  301. exposehandlered();
  302. }
  303. if (mousex>=650 && mousex<=win_attr.width-10 && mousey>=180 && mousey<=200) {
  304. button(TRUE,650,180,win_attr.width-660,20);
  305. if(report.xbutton.button==1 && levelmap.tileset<(tiles->height/96-1)) levelmap.tileset++;
  306. if(report.xbutton.button==3 && levelmap.tileset>0) levelmap.tileset--;
  307. }
  308. if (mousex>=650 && mousex<=686 && mousey>=210 && mousey<=246) {
  309. if(report.xbutton.button==1 && currtile<32) currtile++;
  310. if(report.xbutton.button==3 && currtile>0) currtile--;
  311. exposehandlered();
  312. }
  313. if (report.xbutton.button==2 ||
  314. (mousex>=690 && mousex<=win_attr.width-10 && mousey>=210 && mousey<=230)) {
  315. tilewin=1;
  316. exposehandlered();
  317. }
  318. if (mousex>=650 && mousex<=win_attr.width-10 && mousey>=260 && mousey<=280) {
  319. button(TRUE,650,260,win_attr.width-660,20);
  320. if(report.xbutton.button==1)
  321. if(levelmap.soltime<4200) levelmap.soltime+=10; else levelmap.soltime=4200;
  322. if(report.xbutton.button==3)
  323. if(levelmap.soltime>10) levelmap.soltime-=10; else levelmap.soltime=10;
  324. }
  325. if (mousex>=650 && mousex<=win_attr.width-10 && mousey>=310 && mousey<=340) {
  326. codewin=1; codeptr=strlen(levelmap.code);
  327. exposehandlered();
  328. }
  329. if (mousex>=650 && mousex<=win_attr.width-10 && mousey>=350 && mousey<=380) {
  330. codewin=2; codeptr=strlen(levelmap.nextlink);
  331. exposehandlered();
  332. }
  333. if(report.xbutton.button==5 && currtile<32) {currtile++; exposehandlered();}
  334. if(report.xbutton.button==4 && currtile>0) {currtile--; exposehandlered();}
  335. } else {
  336. if(mousex>=(640-352)/2 && mousex<=(640+352)/2 && mousey>=140 && mousey<=236) {
  337. currtile=(mousey-140)/32+(mousex-(640-352)/2)/32*3;
  338. }
  339. tilewin=0; exposehandlered();
  340. }
  341. break;
  342. case ButtonRelease:
  343. #if DEBUG==TRUE
  344. printf("Mouse button released at %d %d.\n",report.xbutton.x,report.xbutton.y);
  345. #endif
  346. mousebutton_pressed=FALSE;
  347. XGetWindowAttributes(dis, win, &win_attr);
  348. if(tilewin==0){
  349. if (mousex>=650 && mousex<=win_attr.width-10 && mousey>=60 && mousey<=80) {
  350. button(FALSE,650,60,win_attr.width-660,20);
  351. exposehandlered();
  352. }
  353. if (mousex>=650 && mousex<=win_attr.width-10 && mousey>=90 && mousey<=110) {
  354. button(FALSE,650,90,win_attr.width-660,20);
  355. exposehandlered();
  356. }
  357. if (mousex>=650 && mousex<=win_attr.width-10 && mousey>=120 && mousey<=140) {
  358. button(FALSE,650,120,win_attr.width-660,20);
  359. exposehandlered();
  360. }
  361. if (mousex>=650 && mousex<=win_attr.width-10 && mousey>=150 && mousey<=170) {
  362. button(FALSE,650,150,win_attr.width-660,20);
  363. exposehandlered();
  364. }
  365. if (mousex>=650 && mousex<=win_attr.width-10 && mousey>=180 && mousey<=200) {
  366. button(FALSE,650,180,win_attr.width-660,20);
  367. exposehandlered();
  368. }
  369. if (mousex>=650 && mousex<=win_attr.width-10 && mousey>=260 && mousey<=280) {
  370. button(FALSE,650,260,win_attr.width-660,20);
  371. exposehandlered();
  372. }
  373. }
  374. break;
  375. case ResizeRequest:
  376. #if DEBUG==TRUE
  377. printf("I have been resized.\n");
  378. #endif
  379. XClearWindow(dis,win);
  380. exposehandlered();
  381. break;
  382. case Expose:
  383. #if DEBUG==TRUE
  384. printf("I have been exposed.\n");
  385. #endif
  386. exposehandlered();
  387. break;
  388. case KeyPress:
  389. #if DEBUG==TRUE
  390. printf("keypress: %X\n",XLookupKeysym(&report.xkey, 0));
  391. #endif
  392. /*Close the editor if Escape or F5 is pressed.*/
  393. if (XLookupKeysym(&report.xkey, 0) == XK_Escape) {
  394. if(tilewin==1){
  395. tilewin=0; exposehandlered();
  396. } else if(codewin>0){
  397. codewin=0; exposehandlered();
  398. } else return;
  399. }
  400. if (XLookupKeysym(&report.xkey, 0) == XK_F5) {
  401. return;
  402. }
  403. //level code input
  404. if(codewin>0){
  405. f=1; c=0;
  406. if(XLookupKeysym(&report.xkey,0) == XK_Return)
  407. if(codeptr==6) {codewin=0;f=0;}
  408. if(XLookupKeysym(&report.xkey,0) == XK_BackSpace)
  409. if(codeptr<=0){
  410. codeptr=0;
  411. } else {
  412. codeptr--;
  413. if(codewin==1) levelmap.code[codeptr]=0; else levelmap.nextlink[codeptr]=0;
  414. f=0;
  415. }
  416. if(XLookupKeysym(&report.xkey,0) == XK_a) if(codeptr<6){ c='A'; f=0;}
  417. if(XLookupKeysym(&report.xkey,0) == XK_b) if(codeptr<6){ c='B'; f=0;}
  418. if(XLookupKeysym(&report.xkey,0) == XK_c) if(codeptr<6){ c='C'; f=0;}
  419. if(XLookupKeysym(&report.xkey,0) == XK_d) if(codeptr<6){ c='D'; f=0;}
  420. if(XLookupKeysym(&report.xkey,0) == XK_e) if(codeptr<6){ c='E'; f=0;}
  421. if(XLookupKeysym(&report.xkey,0) == XK_f) if(codeptr<6){ c='F'; f=0;}
  422. if(XLookupKeysym(&report.xkey,0) == XK_g) if(codeptr<6){ c='G'; f=0;}
  423. if(XLookupKeysym(&report.xkey,0) == XK_h) if(codeptr<6){ c='H'; f=0;}
  424. if(XLookupKeysym(&report.xkey,0) == XK_i) if(codeptr<6){ c='I'; f=0;}
  425. if(XLookupKeysym(&report.xkey,0) == XK_j) if(codeptr<6){ c='J'; f=0;}
  426. if(XLookupKeysym(&report.xkey,0) == XK_k) if(codeptr<6){ c='K'; f=0;}
  427. if(XLookupKeysym(&report.xkey,0) == XK_l) if(codeptr<6){ c='L'; f=0;}
  428. if(XLookupKeysym(&report.xkey,0) == XK_m) if(codeptr<6){ c='M'; f=0;}
  429. if(XLookupKeysym(&report.xkey,0) == XK_n) if(codeptr<6){ c='N'; f=0;}
  430. if(XLookupKeysym(&report.xkey,0) == XK_o) if(codeptr<6){ c='O'; f=0;}
  431. if(XLookupKeysym(&report.xkey,0) == XK_p) if(codeptr<6){ c='P'; f=0;}
  432. if(XLookupKeysym(&report.xkey,0) == XK_q) if(codeptr<6){ c='Q'; f=0;}
  433. if(XLookupKeysym(&report.xkey,0) == XK_r) if(codeptr<6){ c='R'; f=0;}
  434. if(XLookupKeysym(&report.xkey,0) == XK_s) if(codeptr<6){ c='S'; f=0;}
  435. if(XLookupKeysym(&report.xkey,0) == XK_t) if(codeptr<6){ c='T'; f=0;}
  436. if(XLookupKeysym(&report.xkey,0) == XK_u) if(codeptr<6){ c='U'; f=0;}
  437. if(XLookupKeysym(&report.xkey,0) == XK_v) if(codeptr<6){ c='V'; f=0;}
  438. if(XLookupKeysym(&report.xkey,0) == XK_w) if(codeptr<6){ c='W'; f=0;}
  439. if(XLookupKeysym(&report.xkey,0) == XK_x) if(codeptr<6){ c='X'; f=0;}
  440. if(XLookupKeysym(&report.xkey,0) == XK_y) if(codeptr<6){ c='Y'; f=0;}
  441. if(XLookupKeysym(&report.xkey,0) == XK_z) if(codeptr<6){ c='Z'; f=0;}
  442. if(f){
  443. printf("\007"); fflush(stdout);
  444. }
  445. if(c){
  446. if(codewin==1){
  447. levelmap.code[codeptr]=c;
  448. levelmap.code[codeptr+1]=0;
  449. }else{
  450. levelmap.nextlink[codeptr]=c;
  451. levelmap.nextlink[codeptr+1]=0;
  452. }
  453. codeptr++;
  454. }
  455. exposehandlered();
  456. }
  457. break;
  458. case KeyRelease:
  459. #if DEBUG==TRUE
  460. printf("keyrelease: %X\n",XLookupKeysym(&report.xkey, 0));
  461. #endif
  462. if (XLookupKeysym(&report.xkey, 0) == XK_Alt_R ||
  463. XLookupKeysym(&report.xkey, 0) == XK_Alt_L) {
  464. alt_pressed=FALSE;
  465. }
  466. break;
  467. default:
  468. break;
  469. }
  470. }
  471. // menu end, this code should be never reached
  472. return;
  473. }