robo_ed.cpp 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964
  1. /* $Id$
  2. * MegaZeux
  3. *
  4. * Copyright (C) 2004 Gilead Kutnick - exophase@adelphia.net
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation; either version 2 of
  9. * the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20. // Reconstructed robot editor. This is only a shell - the actual
  21. // robot assembly/disassembly code is in rasm.cpp.
  22. #include <string.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include "robo_ed.h"
  26. #include "rasm.h"
  27. #include "world.h"
  28. #include "event.h"
  29. #include "window.h"
  30. #include "graphics.h"
  31. #include "intake.h"
  32. #include "param.h"
  33. #include "char_ed.h"
  34. #include "helpsys.h"
  35. #include "edit.h"
  36. #define combine_colors(a, b) \
  37. (a) | (b << 4) \
  38. char key_help[(81 * 3) + 1] =
  39. {
  40. " F1:Help F2:Color F3:Char F4:Param F5:Char edit F6-F10:Macros (see Alt+O) \n"
  41. " Alt+Home/S:Mark start Alt+End/E:Mark end Alt+U:Unmark Alt+B:Block Action \n"
  42. " Alt+Ins:Paste Alt+X:Export Alt+I:Import Alt+V:Verify Ctrl+I/D/C:Valid Mark \n"
  43. };
  44. const char top_line_connect = 194;
  45. const char bottom_line_connect = 193;
  46. const char vertical_line = 179;
  47. const char horizontal_line = 196;
  48. const char top_char = 219;
  49. const char bottom_char = 219;
  50. const char bg_char = 32;
  51. const char bg_color = 8;
  52. const char bg_color_solid = combine_colors(0, 8);
  53. const char top_color = 4;
  54. const char bottom_color = 1;
  55. const char line_color = combine_colors(15, 8);
  56. const char top_text_color = combine_colors(15, 4);
  57. const char bottom_text_color = combine_colors(15, 1);
  58. const char top_highlight_color = combine_colors(14, 4);
  59. const char current_line_color = combine_colors(11, 8);
  60. const char mark_color = combine_colors(0, 7);
  61. // Default colors for color coding:
  62. // current line - 11
  63. // immediates - 10
  64. // characters - 14
  65. // colors - color box or 2
  66. // directions - 3
  67. // things - 11
  68. // params - 2
  69. // strings - 14
  70. // equalities - 0
  71. // conditions - 15
  72. // items - 11
  73. // extras - 7
  74. // commands and command fragments - 15
  75. const int max_size = 65535;
  76. char **copy_buffer = NULL;
  77. int copy_buffer_lines;
  78. char macros[5][64];
  79. void robot_editor(World *mzx_world, Robot *cur_robot)
  80. {
  81. int key;
  82. int i;
  83. int current_line = 0;
  84. int current_char = 0;
  85. int total_lines = 0;
  86. int total_chars = 0;
  87. int size = 2;
  88. int max_size = 65535;
  89. int include_ignores = mzx_world->conf.disassemble_extras;
  90. int disassemble_base = mzx_world->conf.disassemble_base;
  91. int line_text_length, line_bytecode_length;
  92. char command_buffer[512];
  93. char error_buffer[512];
  94. char arg_types[32];
  95. char current_line_buffer[6];
  96. char total_lines_buffer[6];
  97. char size_buffer[6];
  98. char max_size_buffer[6];
  99. char *current_robot_pos = cur_robot->program + 1;
  100. char *next;
  101. char *current_macro = macros[0];
  102. char *active_macro = NULL;
  103. char *object_code_position;
  104. int first_line_draw_position;
  105. int first_line_count_back;
  106. int lines_to_draw;
  107. int current_x = 0;
  108. int new_line;
  109. int color_code = mzx_world->conf.color_coding_on;
  110. int arg_count;
  111. int last_color = 0;
  112. int last_char = 0;
  113. robot_line base;
  114. robot_line *current_rline;
  115. robot_line *previous_rline = &base;
  116. robot_line *draw_rline;
  117. robot_line *next_line;
  118. int mark_mode = 0;
  119. int mark_start;
  120. int mark_end;
  121. int mark_current_line;
  122. int show_line_numbers = 0;
  123. robot_line *mark_start_rline;
  124. robot_line *mark_end_rline;
  125. char *ccodes = mzx_world->conf.color_codes;
  126. int current_line_color = combine_colors(ccodes[0], bg_color);
  127. validity_types default_invalid =
  128. (validity_types)(mzx_world->conf.default_invalid_status);
  129. base.previous = NULL;
  130. base.line_bytecode_length = -1;
  131. // Disassemble robots into lines
  132. do
  133. {
  134. new_line = disassemble_line(current_robot_pos, &next,
  135. command_buffer, error_buffer, &line_text_length,
  136. include_ignores, arg_types, &arg_count, disassemble_base);
  137. if(new_line)
  138. {
  139. current_rline = (robot_line *)malloc(sizeof(robot_line));
  140. line_bytecode_length = next - current_robot_pos;
  141. current_rline->line_text_length = line_text_length;
  142. current_rline->line_bytecode_length = line_bytecode_length;
  143. current_rline->line_text = (char *)malloc(line_text_length + 1);
  144. current_rline->line_bytecode = (char *)malloc(line_bytecode_length);
  145. current_rline->num_args = arg_count;
  146. current_rline->validity_status = valid;
  147. memcpy(current_rline->arg_types, arg_types, 20);
  148. memcpy(current_rline->line_bytecode, current_robot_pos,
  149. line_bytecode_length);
  150. memcpy(current_rline->line_text, command_buffer, line_text_length + 1);
  151. previous_rline->next = current_rline;
  152. current_rline->previous = previous_rline;
  153. total_lines++;
  154. current_robot_pos = next;
  155. previous_rline = current_rline;
  156. size += line_bytecode_length;
  157. }
  158. else
  159. {
  160. previous_rline->next = NULL;
  161. }
  162. } while(new_line);
  163. // Add a blank line to the end too if there aren't any lines
  164. if(!total_lines)
  165. {
  166. if(add_blank_line(NULL, &base, &size))
  167. total_lines++;
  168. }
  169. current_rline = base.next;
  170. current_line = 1;
  171. save_screen();
  172. fill_line(80, 0, 0, top_char, top_color);
  173. write_string(key_help, 0, 22, bottom_text_color, 0);
  174. sprintf(max_size_buffer, "%05d", max_size);
  175. strcpy(command_buffer, current_rline->line_text);
  176. do
  177. {
  178. draw_char(top_line_connect, line_color, 0, 1);
  179. draw_char(top_line_connect, line_color, 79, 1);
  180. draw_char(bottom_line_connect, line_color, 0, 21);
  181. draw_char(bottom_line_connect, line_color, 79, 21);
  182. for(i = 1; i < 79; i++)
  183. {
  184. draw_char(horizontal_line, line_color, i, 1);
  185. draw_char(horizontal_line, line_color, i, 21);
  186. }
  187. for(i = 2; i < 11; i++)
  188. {
  189. draw_char(vertical_line, line_color, 0, i);
  190. draw_char(vertical_line, line_color, 79, i);
  191. fill_line(78, 1, i, bg_char, bg_color_solid);
  192. }
  193. for(i = 12; i < 21; i++)
  194. {
  195. draw_char(vertical_line, line_color, 0, i);
  196. draw_char(vertical_line, line_color, 79, i);
  197. fill_line(78, 1, i, bg_char, bg_color_solid);
  198. }
  199. sprintf(current_line_buffer, "%05d", current_line);
  200. sprintf(total_lines_buffer, "%05d", total_lines);
  201. sprintf(size_buffer, "%05d", size);
  202. write_string("Line:", 1, 0, top_highlight_color, 0);
  203. write_string(current_line_buffer, 7, 0, top_text_color, 0);
  204. write_string("/", 12, 0, top_highlight_color, 0);
  205. write_string(total_lines_buffer, 13, 0, top_text_color, 0);
  206. write_string("Character:", 26, 0, top_highlight_color, 0);
  207. write_string("/", 40, 0, top_highlight_color, 0);
  208. write_string("Size:", 51, 0, top_highlight_color, 0);
  209. write_string(size_buffer, 57, 0, top_text_color, 0);
  210. write_string("/", 62, 0, top_highlight_color, 0);
  211. write_string(max_size_buffer, 63, 0, top_text_color, 0);
  212. // Now, draw the lines. Start with 9 back from the current.
  213. if(current_line >= 10)
  214. {
  215. first_line_draw_position = 2;
  216. first_line_count_back = 10 - 1;
  217. }
  218. else
  219. {
  220. // Or go back as many as we can
  221. first_line_draw_position = 2 + (10 - current_line);
  222. first_line_count_back = current_line - 1;
  223. }
  224. draw_rline = current_rline;
  225. for(i = 0; i < first_line_count_back; i++)
  226. {
  227. draw_rline = draw_rline->previous;
  228. }
  229. // Now draw start - 20 + 1 lines, or until bails
  230. for(i = first_line_draw_position; (i < 21) && draw_rline; i++)
  231. {
  232. if(i != 11)
  233. display_robot_line(draw_rline, i, color_code, ccodes);
  234. draw_rline = draw_rline->next;
  235. }
  236. // Mark block selection area
  237. mark_current_line = 0;
  238. if(mark_mode)
  239. {
  240. int draw_start = current_line - 9;
  241. int draw_end = current_line + 9;
  242. if(mark_end > total_lines)
  243. mark_end = total_lines;
  244. if(mark_start <= draw_end)
  245. {
  246. if(mark_start > draw_start)
  247. draw_start = mark_start;
  248. if(mark_end < draw_end)
  249. draw_end = mark_end;
  250. draw_start += 11 - current_line;
  251. draw_end += 11 - current_line;
  252. if(draw_start < 2)
  253. draw_start = 2;
  254. if(draw_end > 20)
  255. draw_end = 20;
  256. if(draw_end > 2)
  257. {
  258. for(i = draw_start; i < draw_end + 1; i++)
  259. {
  260. color_line(80, 0, i, mark_color);
  261. }
  262. draw_char('S', mark_color, 0, draw_start);
  263. if(draw_start != draw_end)
  264. draw_char('E', mark_color, 0, draw_end);
  265. if((draw_start <= 11) && (draw_end >= 11))
  266. mark_current_line = 1;
  267. }
  268. }
  269. }
  270. update_screen();
  271. if(mark_current_line)
  272. {
  273. draw_char(bg_char, mark_color, 1, 11);
  274. key = intake(command_buffer, 240, 2, 11, mark_color, 2, 0, 0,
  275. &current_x, 1, active_macro);
  276. }
  277. else
  278. {
  279. draw_char(bg_char, bg_color_solid, 1, 11);
  280. key = intake(command_buffer, 240, 2, 11, current_line_color, 2,
  281. 0, 0, &current_x, 1, active_macro);
  282. }
  283. active_macro = NULL;
  284. switch(key)
  285. {
  286. case SDLK_UP:
  287. {
  288. next_line = move_line_up(current_rline, 1, &current_line);
  289. if(next_line)
  290. {
  291. change_line(current_rline, command_buffer, include_ignores,
  292. disassemble_base, default_invalid, &size);
  293. current_rline = next_line;
  294. strcpy(command_buffer, current_rline->line_text);
  295. }
  296. break;
  297. }
  298. case SDLK_DOWN:
  299. {
  300. next_line = move_line_down(current_rline, 1, &current_line);
  301. if(next_line)
  302. {
  303. change_line(current_rline, command_buffer, include_ignores,
  304. disassemble_base, default_invalid, &size);
  305. current_rline = next_line;
  306. strcpy(command_buffer, current_rline->line_text);
  307. }
  308. else
  309. {
  310. if(command_buffer[0])
  311. {
  312. if(add_blank_line(current_rline->next, current_rline, &size))
  313. {
  314. total_lines++;
  315. next_line = move_line_down(current_rline, 1, &current_line);
  316. change_line(current_rline, command_buffer, include_ignores,
  317. disassemble_base, default_invalid, &size);
  318. current_rline = next_line;
  319. strcpy(command_buffer, current_rline->line_text);
  320. }
  321. }
  322. }
  323. break;
  324. }
  325. case SDLK_PAGEUP:
  326. {
  327. next_line = move_line_up(current_rline, 9, &current_line);
  328. if(next_line)
  329. {
  330. change_line(current_rline, command_buffer, include_ignores,
  331. disassemble_base, default_invalid, &size);
  332. current_rline = next_line;
  333. strcpy(command_buffer, current_rline->line_text);
  334. }
  335. break;
  336. }
  337. case SDLK_PAGEDOWN:
  338. {
  339. int old_current_line = current_line;
  340. next_line = move_line_down(current_rline, 9, &current_line);
  341. if(next_line)
  342. {
  343. change_line(current_rline, command_buffer, include_ignores,
  344. disassemble_base, default_invalid, &size);
  345. current_rline = next_line;
  346. strcpy(command_buffer, current_rline->line_text);
  347. }
  348. if((command_buffer[0]) && ((current_line - old_current_line) < 9))
  349. {
  350. if(add_blank_line(current_rline->next, current_rline, &size))
  351. {
  352. total_lines++;
  353. next_line = move_line_down(current_rline, 1, &current_line);
  354. change_line(current_rline, command_buffer, include_ignores,
  355. disassemble_base, default_invalid, &size);
  356. current_rline = next_line;
  357. strcpy(command_buffer, current_rline->line_text);
  358. }
  359. }
  360. break;
  361. }
  362. case SDLK_BACKSPACE:
  363. {
  364. if(!current_x)
  365. {
  366. current_x = 10000;
  367. next_line = move_line_up(current_rline, 1, &current_line);
  368. if(command_buffer[0] == 0)
  369. {
  370. if(total_lines != 1)
  371. {
  372. if(next_line == NULL)
  373. next_line = current_rline->next;
  374. change_line(current_rline, command_buffer, include_ignores,
  375. disassemble_base, default_invalid, &size);
  376. size += remove_line(current_rline);
  377. total_lines--;
  378. current_rline = next_line;
  379. strcpy(command_buffer, current_rline->line_text);
  380. }
  381. }
  382. else
  383. {
  384. if(next_line)
  385. {
  386. change_line(current_rline, command_buffer, include_ignores,
  387. disassemble_base, default_invalid, &size);
  388. current_rline = next_line;
  389. strcpy(command_buffer, current_rline->line_text);
  390. }
  391. }
  392. }
  393. break;
  394. }
  395. case SDLK_DELETE:
  396. {
  397. if(command_buffer[0] == 0)
  398. {
  399. next_line = current_rline->next;;
  400. if(next_line)
  401. {
  402. change_line(current_rline, command_buffer, include_ignores,
  403. disassemble_base, default_invalid, &size);
  404. size += remove_line(current_rline);
  405. total_lines--;
  406. current_rline = next_line;
  407. strcpy(command_buffer, current_rline->line_text);
  408. }
  409. }
  410. break;
  411. }
  412. case SDLK_RETURN:
  413. {
  414. if(current_x)
  415. {
  416. if(current_line == total_lines)
  417. {
  418. if(add_blank_line(current_rline->next, current_rline, &size))
  419. total_lines++;
  420. }
  421. next_line = move_line_down(current_rline, 1, &current_line);
  422. if(next_line)
  423. {
  424. current_x = 0;
  425. change_line(current_rline, command_buffer, include_ignores,
  426. disassemble_base, default_invalid, &size);
  427. current_rline = next_line;
  428. strcpy(command_buffer, current_rline->line_text);
  429. }
  430. }
  431. else
  432. {
  433. if(add_blank_line(current_rline, current_rline->previous, &size))
  434. {
  435. current_line++;
  436. total_lines++;
  437. }
  438. }
  439. break;
  440. }
  441. case SDLK_F1: // F1
  442. {
  443. m_show();
  444. help_system(mzx_world);
  445. break;
  446. }
  447. case SDLK_F2:
  448. {
  449. int new_color = color_selection(last_color, 1);
  450. if(new_color >= 0)
  451. {
  452. char color_buffer[16];
  453. last_color = new_color;
  454. print_color(new_color, color_buffer);
  455. insert_string(command_buffer, color_buffer, &current_x);
  456. }
  457. break;
  458. }
  459. case SDLK_F3:
  460. {
  461. int new_char = char_selection(last_char);
  462. if(new_char >= 0)
  463. {
  464. char char_buffer[16];
  465. last_char = new_char;
  466. sprintf(char_buffer, "%c", new_char);
  467. insert_string(command_buffer, char_buffer, &current_x);
  468. }
  469. break;
  470. }
  471. case SDLK_F4:
  472. {
  473. int start_x = current_x;
  474. int matched_thing;
  475. char *next;
  476. char temp_char = command_buffer[current_x];
  477. if(!command_buffer[start_x])
  478. start_x--;
  479. while(start_x && (command_buffer[start_x] == ' '))
  480. start_x--;
  481. while(start_x && (command_buffer[start_x] != ' '))
  482. start_x--;
  483. start_x++;
  484. command_buffer[current_x] = 0;
  485. matched_thing = is_thing(command_buffer + start_x, &next);
  486. command_buffer[current_x] = temp_char;
  487. if((matched_thing != -1) && (matched_thing < 122))
  488. {
  489. int new_param = edit_param(mzx_world, matched_thing, -1);
  490. if(new_param >= 0)
  491. {
  492. char param_buffer[16];
  493. sprintf(param_buffer, " p%02x", new_param);
  494. insert_string(command_buffer, param_buffer, &current_x);
  495. }
  496. }
  497. break;
  498. }
  499. case SDLK_F5:
  500. {
  501. int char_edited = char_editor(mzx_world);
  502. char char_buffer[14];
  503. char char_string_buffer[64];
  504. ec_read_char(char_edited, char_buffer);
  505. char *char_string_buffer_position = char_string_buffer;
  506. for(i = 0; i < 13; i++, char_string_buffer_position += 4)
  507. {
  508. sprintf(char_string_buffer_position, "$%02x ", char_buffer[i]);
  509. }
  510. sprintf(char_string_buffer_position, "$%02x", char_buffer[i]);
  511. insert_string(command_buffer, char_string_buffer, &current_x);
  512. break;
  513. }
  514. case SDLK_F6:
  515. {
  516. active_macro = macros[0];
  517. break;
  518. }
  519. case SDLK_F7:
  520. {
  521. active_macro = macros[1];
  522. break;
  523. }
  524. case SDLK_F8:
  525. {
  526. active_macro = macros[2];
  527. break;
  528. }
  529. case SDLK_F9:
  530. {
  531. active_macro = macros[3];
  532. break;
  533. }
  534. case SDLK_F10:
  535. {
  536. active_macro = macros[4];
  537. break;
  538. }
  539. case SDLK_v:
  540. {
  541. change_line(current_rline, command_buffer, include_ignores,
  542. disassemble_base, default_invalid, &size);
  543. if(get_alt_status(keycode_SDL))
  544. {
  545. change_line(current_rline, command_buffer, include_ignores,
  546. disassemble_base, default_invalid, &size);
  547. validate_lines(mzx_world, base.next, 1, &size);
  548. change_line(current_rline, command_buffer, include_ignores,
  549. disassemble_base, default_invalid, &size);
  550. }
  551. break;
  552. }
  553. case SDLK_ESCAPE:
  554. {
  555. change_line(current_rline, command_buffer, include_ignores,
  556. disassemble_base, default_invalid, &size);
  557. if(validate_lines(mzx_world, base.next, 0, &size))
  558. key = 0;
  559. change_line(current_rline, command_buffer, include_ignores,
  560. disassemble_base, default_invalid, &size);
  561. break;
  562. }
  563. // Mark start/end
  564. case SDLK_s:
  565. case SDLK_e:
  566. case SDLK_HOME:
  567. case SDLK_END:
  568. {
  569. if(get_alt_status(keycode_SDL))
  570. {
  571. int mark_switch;
  572. change_line(current_rline, command_buffer, include_ignores,
  573. disassemble_base, default_invalid, &size);
  574. if(mark_mode == 2)
  575. {
  576. if((key == SDLK_HOME) || (key == SDLK_s))
  577. mark_switch = 0;
  578. else
  579. mark_switch = 1;
  580. }
  581. else
  582. {
  583. mark_switch = mark_mode;
  584. mark_mode++;
  585. }
  586. switch(mark_switch)
  587. {
  588. case 0:
  589. {
  590. // Always mark the start
  591. mark_start = current_line;
  592. mark_start_rline = current_rline;
  593. if(mark_mode == 1)
  594. {
  595. // If this is the real start, mark the end too
  596. mark_end = current_line;
  597. mark_end_rline = current_rline;
  598. }
  599. break;
  600. }
  601. case 1:
  602. {
  603. // Always mark the end
  604. mark_end = current_line;
  605. mark_end_rline = current_rline;
  606. break;
  607. }
  608. }
  609. // We have more than a start, so possibly swap
  610. if(mark_mode && (mark_start > mark_end))
  611. {
  612. int mark_swap;
  613. robot_line *mark_swap_rline;
  614. mark_swap = mark_start;
  615. mark_start = mark_end;
  616. mark_end = mark_start;
  617. mark_swap_rline = mark_start_rline;
  618. mark_start_rline = mark_end_rline;
  619. mark_end_rline = mark_swap_rline;
  620. }
  621. }
  622. break;
  623. }
  624. // Block action menu
  625. case SDLK_b:
  626. {
  627. if(get_alt_status(keycode_SDL))
  628. {
  629. int block_command = block_menu(mzx_world);
  630. if(!mark_mode)
  631. {
  632. mark_start_rline = current_rline;
  633. mark_end_rline = current_rline;
  634. mark_start = current_line;
  635. mark_end = current_line;
  636. }
  637. switch(block_command)
  638. {
  639. case 0:
  640. {
  641. // Copy block into buffer
  642. copy_block_to_buffer(mark_start_rline,
  643. (mark_end - mark_start) + 1);
  644. break;
  645. }
  646. case 1:
  647. {
  648. // Copy block into buffer, then clear block
  649. copy_block_to_buffer(mark_start_rline,
  650. (mark_end - mark_start) + 1);
  651. current_rline = clear_block(mark_start, mark_start_rline,
  652. mark_end - mark_start + 1, &current_line, &total_lines, &size,
  653. current_rline);
  654. strcpy(command_buffer, current_rline->line_text);
  655. mark_mode = 0;
  656. break;
  657. }
  658. case 2:
  659. {
  660. // Clear block
  661. current_rline = clear_block(mark_start, mark_start_rline,
  662. mark_end - mark_start + 1, &current_line, &total_lines, &size,
  663. current_rline);
  664. strcpy(command_buffer, current_rline->line_text);
  665. mark_mode = 0;
  666. break;
  667. }
  668. case 3:
  669. {
  670. // Export block - text only
  671. export_block(mzx_world, &base, mark_start_rline,
  672. mark_end_rline, 1);
  673. break;
  674. }
  675. }
  676. }
  677. break;
  678. }
  679. case SDLK_g:
  680. {
  681. if(get_ctrl_status(keycode_SDL))
  682. {
  683. char line_number[16];
  684. line_number[0] = 0;
  685. save_screen();
  686. draw_window_box(18, 12, 47, 14, EC_DEBUG_BOX, EC_DEBUG_BOX_DARK,
  687. EC_DEBUG_BOX_CORNER, 1, 1);
  688. write_string("Goto line number:", 20, 13, EC_DEBUG_LABEL, 0);
  689. if(intake(line_number, 7, 38, 13, 15, 1, 0) != SDLK_ESCAPE)
  690. {
  691. int line = strtol(line_number, NULL, 10);
  692. int num_lines;
  693. if(line > total_lines)
  694. line = total_lines;
  695. if(line < 0)
  696. line = 0;
  697. if(line < current_line)
  698. {
  699. num_lines = current_line - line;
  700. for(i = 0; i < num_lines; i++)
  701. {
  702. current_rline = current_rline->previous;
  703. current_line--;
  704. }
  705. }
  706. else
  707. {
  708. num_lines = line - current_line;
  709. for(i = 0; i < num_lines; i++)
  710. {
  711. current_rline = current_rline->next;
  712. current_line++;
  713. }
  714. }
  715. strcpy(command_buffer, current_rline->line_text);
  716. }
  717. restore_screen();
  718. }
  719. break;
  720. }
  721. case SDLK_l:
  722. {
  723. if(get_ctrl_status(keycode_SDL))
  724. show_line_numbers ^= 1;
  725. break;
  726. }
  727. case SDLK_d:
  728. {
  729. if(current_rline->validity_status != valid)
  730. {
  731. current_rline->validity_status = invalid_discard;
  732. change_line(current_rline, command_buffer, include_ignores,
  733. disassemble_base, default_invalid, &size);
  734. }
  735. break;
  736. }
  737. case SDLK_c:
  738. {
  739. if(current_rline->validity_status != valid)
  740. {
  741. current_rline->validity_status = invalid_comment;
  742. change_line(current_rline, command_buffer, include_ignores,
  743. disassemble_base, default_invalid, &size);
  744. }
  745. else
  746. if(command_buffer[0] != '.')
  747. {
  748. char comment_buffer[512];
  749. char current_char;
  750. char *in_position = command_buffer;
  751. char *out_position = comment_buffer + 3;
  752. comment_buffer[0] = '.';
  753. comment_buffer[1] = ' ';
  754. comment_buffer[2] = '"';
  755. do
  756. {
  757. current_char = *in_position;
  758. if(current_char == '"')
  759. {
  760. *out_position = '\\';
  761. out_position++;
  762. }
  763. *out_position = current_char;
  764. out_position++;
  765. in_position++;
  766. } while(current_char);
  767. *(out_position - 1) = '"';
  768. *out_position = 0;
  769. strcpy(command_buffer, comment_buffer);
  770. }
  771. else
  772. if(get_ctrl_status(keycode_SDL) &&
  773. (command_buffer[0] == '.') && (command_buffer[1] == ' ') &&
  774. (command_buffer[2] == '"') &&
  775. (command_buffer[strlen(command_buffer) - 1] == '"'))
  776. {
  777. char uncomment_buffer[512];
  778. char current_char;
  779. char *in_position = command_buffer + 3;
  780. char *out_position = uncomment_buffer;
  781. do
  782. {
  783. current_char = *in_position;
  784. if((current_char == '\\') && (in_position[1] == '"'))
  785. {
  786. current_char = '"';
  787. in_position++;
  788. }
  789. *out_position = current_char;
  790. out_position++;
  791. in_position++;
  792. } while(current_char);
  793. *(out_position - 2) = 0;
  794. strcpy(command_buffer, uncomment_buffer);
  795. }
  796. break;
  797. }
  798. case SDLK_p:
  799. case SDLK_INSERT:
  800. {
  801. if(get_alt_status(keycode_SDL) && copy_buffer)
  802. {
  803. paste_buffer(current_rline, &total_lines, &current_line, &size,
  804. include_ignores, disassemble_base, default_invalid);
  805. }
  806. break;
  807. }
  808. // Import file
  809. case SDLK_i:
  810. {
  811. if(get_alt_status(keycode_SDL))
  812. {
  813. import_block(mzx_world, current_rline, &total_lines,
  814. &current_line, &size, include_ignores, disassemble_base,
  815. default_invalid);
  816. }
  817. else
  818. if(get_ctrl_status(keycode_SDL))
  819. {
  820. if(current_rline->validity_status != valid)
  821. {
  822. current_rline->validity_status = invalid_uncertain;
  823. change_line(current_rline, command_buffer, include_ignores,
  824. disassemble_base, default_invalid, &size);
  825. }
  826. }
  827. break;
  828. }
  829. // Export file
  830. case SDLK_x:
  831. {
  832. if(get_alt_status(keycode_SDL))
  833. {
  834. if(mark_mode)
  835. {
  836. export_block(mzx_world, &base, mark_start_rline, mark_end_rline, 1);
  837. }
  838. else
  839. {
  840. export_block(mzx_world, &base, mark_start_rline, mark_end_rline, 0);
  841. }
  842. }
  843. break;
  844. }
  845. // Options
  846. case SDLK_o:
  847. {
  848. if(get_alt_status(keycode_SDL))
  849. edit_settings(mzx_world);
  850. break;
  851. }
  852. // Unmark
  853. case SDLK_u:
  854. {
  855. if(get_alt_status(keycode_SDL))
  856. mark_mode = 0;
  857. break;
  858. }
  859. }
  860. } while(key != SDLK_ESCAPE);
  861. // Package time
  862. reallocate_robot(cur_robot, size);
  863. current_rline = base.next;
  864. object_code_position = cur_robot->program;
  865. object_code_position[0] = 0xFF;
  866. object_code_position++;
  867. while(current_rline)
  868. {
  869. if((current_rline->next != NULL) || (current_rline->line_text[0]))
  870. {
  871. if(current_rline->validity_status == invalid_comment)
  872. {
  873. object_code_position[0] = current_rline->line_text_length + 3;
  874. object_code_position[1] = 107;
  875. object_code_position[2] = current_rline->line_text_length + 1;
  876. strcpy(object_code_position + 3, current_rline->line_text);
  877. object_code_position[current_rline->line_text_length + 4] =
  878. current_rline->line_text_length + 3;
  879. object_code_position += current_rline->line_text_length + 5;
  880. }
  881. else
  882. if(current_rline->validity_status == valid)
  883. {
  884. memcpy(object_code_position, current_rline->line_bytecode,
  885. current_rline->line_bytecode_length);
  886. object_code_position += current_rline->line_bytecode_length;
  887. }
  888. }
  889. else
  890. {
  891. // Get rid of trailing three bytes if present
  892. size -= current_rline->line_bytecode_length;
  893. reallocate_robot(cur_robot, size);
  894. object_code_position = cur_robot->program + size - 1;
  895. }
  896. free(current_rline->line_bytecode);
  897. free(current_rline->line_text);
  898. next_line = current_rline->next;
  899. free(current_rline);
  900. current_rline = next_line;
  901. }
  902. object_code_position[0] = 0;
  903. if(size > 2)
  904. {
  905. cur_robot->used = 1;
  906. cur_robot->cur_prog_line = 1;
  907. cur_robot->label_list = cache_robot_labels(cur_robot, &(cur_robot->num_labels));
  908. }
  909. restore_screen();
  910. }
  911. void insert_string(char *dest, char *string, int *position)
  912. {
  913. int n_pos = *position;
  914. int remainder = strlen(dest + n_pos) + 1;
  915. int insert_length = strlen(string);
  916. memmove(dest + n_pos + insert_length, dest + n_pos, remainder);
  917. memcpy(dest + n_pos, string, insert_length);
  918. *position = n_pos + insert_length;
  919. }
  920. robot_line *move_line_up(robot_line *current_rline, int count,
  921. int *current_line)
  922. {
  923. int i;
  924. for(i = 0; (i < count) || (i == -1); i++)
  925. {
  926. if(current_rline->previous->line_bytecode_length == -1)
  927. break;
  928. current_rline = current_rline->previous;
  929. }
  930. if(i)
  931. {
  932. *current_line -= i;
  933. return current_rline;
  934. }
  935. return NULL;
  936. }
  937. robot_line *move_line_down(robot_line *current_rline, int count,
  938. int *current_line)
  939. {
  940. int i;
  941. for(i = 0; (i < count) || (i == -1); i++)
  942. {
  943. if(!current_rline->next)
  944. break;
  945. current_rline = current_rline->next;
  946. }
  947. if(i)
  948. {
  949. *current_line += i;
  950. return current_rline;
  951. }
  952. return NULL;
  953. }
  954. void display_robot_line(robot_line *current_rline, int y,
  955. int color_code, char *color_codes)
  956. {
  957. int i;
  958. int x = 2;
  959. int current_color, current_arg;
  960. char current_char;
  961. char temp_buffer[512];
  962. char temp_char;
  963. char *line_pos = current_rline->line_text;
  964. int arg_length;
  965. if(current_rline->line_text[0] != 0)
  966. {
  967. if(current_rline->validity_status != valid)
  968. {
  969. current_color =
  970. combine_colors(color_codes[S_CMD + current_rline->validity_status + 1],
  971. bg_color);
  972. if(strlen(current_rline->line_text) > 76)
  973. {
  974. temp_char = current_rline->line_text[76];
  975. current_rline->line_text[76] = 0;
  976. write_string(current_rline->line_text, x, y, current_color, 0);
  977. current_rline->line_text[76] = temp_char;
  978. }
  979. else
  980. {
  981. write_string(current_rline->line_text, x, y, current_color, 0);
  982. }
  983. }
  984. else
  985. {
  986. arg_length = 0;
  987. if(!color_code)
  988. {
  989. current_color =
  990. combine_colors(color_codes[S_STRING + 1], bg_color);
  991. }
  992. if(color_code)
  993. current_color = combine_colors(color_codes[S_CMD + 1], bg_color);
  994. get_word(temp_buffer, line_pos, ' ');
  995. arg_length = strlen(temp_buffer) + 1;
  996. write_string(temp_buffer, x, y, current_color, 0);
  997. line_pos += arg_length;
  998. x += arg_length;
  999. for(i = 0; i < current_rline->num_args; i++)
  1000. {
  1001. current_arg = current_rline->arg_types[i];
  1002. if(current_arg == S_STRING)
  1003. {
  1004. temp_buffer[0] = '"';
  1005. get_word(temp_buffer + 1, line_pos + 1, '"');
  1006. arg_length = strlen(temp_buffer);
  1007. temp_buffer[arg_length] = '"';
  1008. temp_buffer[arg_length + 1] = 0;
  1009. arg_length += 2;
  1010. }
  1011. else
  1012. {
  1013. get_word(temp_buffer, line_pos, ' ');
  1014. arg_length = strlen(temp_buffer) + 1;
  1015. }
  1016. if((current_arg == S_COLOR) && (color_codes[current_arg + 1] == 255))
  1017. {
  1018. unsigned int color = get_color(line_pos);
  1019. draw_color_box(color, color >> 8, x, y);
  1020. }
  1021. else
  1022. {
  1023. if(color_code)
  1024. {
  1025. current_color =
  1026. combine_colors(color_codes[current_arg + 1], bg_color);
  1027. }
  1028. if((x + arg_length) > 78)
  1029. {
  1030. temp_buffer[78 - x] = 0;
  1031. write_string(temp_buffer, x, y, current_color, 0);
  1032. break;
  1033. }
  1034. write_string(temp_buffer, x, y, current_color, 0);
  1035. }
  1036. line_pos += arg_length;
  1037. x += arg_length;
  1038. }
  1039. }
  1040. }
  1041. }
  1042. int change_line(robot_line *current_rline, char *command_buffer,
  1043. int include_ignores, int base, validity_types invalid_status,
  1044. int *size)
  1045. {
  1046. char bytecode_buffer[512];
  1047. char error_buffer[512];
  1048. char new_command_buffer[512];
  1049. char arg_types[32];
  1050. int color_code = 1;
  1051. int arg_count;
  1052. int bytecode_length =
  1053. assemble_line(command_buffer, bytecode_buffer, error_buffer,
  1054. arg_types, &arg_count);
  1055. int last_bytecode_length = current_rline->line_bytecode_length;
  1056. int current_size = *size;
  1057. if(bytecode_length != -1)
  1058. {
  1059. char *next;
  1060. int line_text_length;
  1061. if((current_size + bytecode_length - last_bytecode_length) > MAX_OBJ_SIZE)
  1062. return 0;
  1063. disassemble_line(bytecode_buffer, &next, new_command_buffer,
  1064. error_buffer, &line_text_length, include_ignores, arg_types,
  1065. &arg_count, base);
  1066. current_rline->line_text_length = line_text_length;
  1067. current_rline->line_bytecode_length = bytecode_length;
  1068. current_rline->line_text =
  1069. (char *)realloc(current_rline->line_text, line_text_length + 1);
  1070. current_rline->line_bytecode =
  1071. (char *)realloc(current_rline->line_bytecode, bytecode_length);
  1072. current_rline->num_args = arg_count;
  1073. current_rline->validity_status = valid;
  1074. memcpy(current_rline->arg_types, arg_types, 20);
  1075. strcpy(current_rline->line_text, new_command_buffer);
  1076. memcpy(current_rline->line_bytecode, bytecode_buffer, bytecode_length);
  1077. *size = current_size + bytecode_length - last_bytecode_length;
  1078. return 1;
  1079. }
  1080. else
  1081. {
  1082. int line_text_length = strlen(command_buffer);
  1083. current_rline->line_text =
  1084. (char *)realloc(current_rline->line_text, line_text_length + 1);
  1085. current_rline->line_text_length = line_text_length;
  1086. strcpy(current_rline->line_text, command_buffer);
  1087. if((current_rline->validity_status != invalid_comment) &&
  1088. (invalid_status != invalid_comment))
  1089. {
  1090. current_rline->line_bytecode_length = 0;
  1091. if(current_rline->validity_status == valid)
  1092. current_rline->validity_status = invalid_status;
  1093. *size = current_size - last_bytecode_length;
  1094. return 1;
  1095. }
  1096. else
  1097. {
  1098. if((current_size + (line_text_length + 5) - last_bytecode_length) >
  1099. MAX_OBJ_SIZE)
  1100. return 0;
  1101. if(current_rline->validity_status == valid)
  1102. current_rline->validity_status = invalid_comment;
  1103. current_rline->line_bytecode_length = line_text_length + 5;
  1104. *size = current_size + (line_text_length + 5) - last_bytecode_length;
  1105. return 1;
  1106. }
  1107. }
  1108. }
  1109. int add_blank_line(robot_line *next_rline, robot_line *previous_rline,
  1110. int *size)
  1111. {
  1112. robot_line *current_rline = (robot_line *)malloc(sizeof(robot_line));
  1113. int old_size = *size;
  1114. current_rline->line_text_length = 0;
  1115. current_rline->line_text = (char *)malloc(1);
  1116. current_rline->line_bytecode = (char *)malloc(3);
  1117. current_rline->line_text[0] = 0;
  1118. current_rline->line_bytecode[0] = 1;
  1119. current_rline->line_bytecode[1] = 47;
  1120. current_rline->line_bytecode[2] = 1;
  1121. current_rline->next = next_rline;
  1122. current_rline->previous = previous_rline;
  1123. current_rline->validity_status = valid;
  1124. if((old_size + 3) < MAX_OBJ_SIZE)
  1125. {
  1126. previous_rline->next = current_rline;
  1127. if(next_rline)
  1128. {
  1129. current_rline->line_bytecode_length = 3;
  1130. next_rline->previous = current_rline;
  1131. (*size) += 3;
  1132. }
  1133. else
  1134. {
  1135. current_rline->line_bytecode_length = 0;
  1136. return 1;
  1137. }
  1138. }
  1139. else
  1140. {
  1141. free(current_rline->line_text);
  1142. free(current_rline->line_bytecode);
  1143. free(current_rline);
  1144. return 0;
  1145. }
  1146. }
  1147. int add_line(robot_line *next_rline, robot_line *previous_rline,
  1148. int *size, char *command_buffer, int include_ignores, int base,
  1149. validity_types invalid_status)
  1150. {
  1151. robot_line *current_rline = (robot_line *)malloc(sizeof(robot_line));
  1152. int old_size = *size;
  1153. current_rline->line_text = NULL;
  1154. current_rline->line_bytecode = NULL;
  1155. current_rline->line_bytecode_length = 0;
  1156. current_rline->validity_status = valid;
  1157. if(change_line(current_rline, command_buffer, include_ignores,
  1158. base, invalid_status, size))
  1159. {
  1160. current_rline->next = next_rline;
  1161. current_rline->previous = previous_rline;
  1162. previous_rline->next = current_rline;
  1163. if(next_rline)
  1164. next_rline->previous = current_rline;
  1165. return 1;
  1166. }
  1167. else
  1168. {
  1169. free(current_rline->line_text);
  1170. free(current_rline->line_bytecode);
  1171. free(current_rline);
  1172. return 0;
  1173. }
  1174. }
  1175. int remove_line(robot_line *current_rline)
  1176. {
  1177. int last_size = current_rline->line_bytecode_length;
  1178. robot_line *next = current_rline->next;
  1179. robot_line *previous = current_rline->previous;
  1180. previous->next = next;
  1181. if(next)
  1182. next->previous = previous;
  1183. free(current_rline->line_text);
  1184. free(current_rline->line_bytecode);
  1185. free(current_rline);
  1186. return -last_size;
  1187. }
  1188. #define VALIDATE_ELEMENTS 60
  1189. #define MAX_ERRORS 256
  1190. // This will only check for errors after current_rline, so the
  1191. // base should be passed.
  1192. int validate_lines(World *mzx_world, robot_line *current_rline,
  1193. int show_none, int *size)
  1194. {
  1195. // 70x5-21 square that displays up to 13 error messages,
  1196. // and up to 48 buttons for delete/comment out/ignore. In total,
  1197. // the elements are text display to tell how many erroroneous
  1198. // lines there are, 13 text bars to display the error message
  1199. // and validity status, 13 delete buttons, 13 comment buttons,
  1200. // 13 ignore buttons, a next button, a previous button,
  1201. // and yes/no buttons. There can thus be up to 57 or so elements.
  1202. // The first one is always text, and the second are always
  1203. // yes/no buttons. The rest are variable depending on how
  1204. // many errors there are. The text button positions cannot be
  1205. // determined until the number of errors is.
  1206. // Doesn't take any more errors after the number of erroneous
  1207. // lines exceeds MAX_ERRORS.
  1208. char information[64];
  1209. char di_types[VALIDATE_ELEMENTS] = { DE_TEXT, DE_BUTTON, DE_BUTTON };
  1210. char di_xs[VALIDATE_ELEMENTS] = { 5, 28, 38 };
  1211. char di_ys[VALIDATE_ELEMENTS] = { 2, 18, 18 };
  1212. char *di_strs[VALIDATE_ELEMENTS] = { information, "OK", "Cancel" };
  1213. int di_p1s[VALIDATE_ELEMENTS] = { 0, 0, -1 };
  1214. int di_p2s[VALIDATE_ELEMENTS] = { 0 };
  1215. void *di_storage[VALIDATE_ELEMENTS] = { NULL };
  1216. int start_line = 0;
  1217. int num_errors = 0;
  1218. int error_lines[MAX_ERRORS];
  1219. char error_messages[MAX_ERRORS][64];
  1220. char null_buffer[256];
  1221. robot_line *line_pointers[MAX_ERRORS];
  1222. validity_types validity_options[MAX_ERRORS];
  1223. int redo = 1;
  1224. int element_pos;
  1225. int errors_shown;
  1226. int multi_pages = 0;
  1227. int line_number = 0;
  1228. int dialog_result;
  1229. int num_ignore = 0;
  1230. int current_size = *size;
  1231. int i;
  1232. dialog di =
  1233. {
  1234. 5, 2, 74, 22, "Command summary", 3, di_types, di_xs, di_ys,
  1235. di_strs, di_p1s, di_p2s, di_storage, 0
  1236. };
  1237. // First, collect the number of errors, and process error messages
  1238. // by calling assemble_line.
  1239. while(current_rline != NULL)
  1240. {
  1241. if(current_rline->validity_status != valid)
  1242. {
  1243. memset(error_messages[num_errors], ' ', 64);
  1244. sprintf(error_messages[num_errors], "%05d: ", line_number + 1);
  1245. assemble_line(current_rline->line_text, null_buffer,
  1246. error_messages[num_errors] + 7, NULL, NULL);
  1247. error_messages[num_errors][strlen(error_messages[num_errors])] = ' ';
  1248. line_pointers[num_errors] = current_rline;
  1249. validity_options[num_errors] = current_rline->validity_status;
  1250. if(current_rline->validity_status == invalid_uncertain)
  1251. num_ignore++;
  1252. if(num_errors == MAX_ERRORS)
  1253. break;
  1254. num_errors++;
  1255. }
  1256. current_rline = current_rline->next;
  1257. line_number++;
  1258. }
  1259. // The button return messages are as such:
  1260. // 0 - ok
  1261. // -1 - cancel
  1262. // 1 - previous
  1263. // 2 - next
  1264. // 100-113 - ignore line
  1265. // 200-213 - delete line
  1266. // 300-313 - ignore line
  1267. if(num_errors > 12)
  1268. {
  1269. multi_pages = 1;
  1270. }
  1271. if(num_ignore || show_none)
  1272. {
  1273. do
  1274. {
  1275. errors_shown = num_errors - start_line;
  1276. if(errors_shown > 12)
  1277. errors_shown = 12;
  1278. for(i = 0, element_pos = 3; i < errors_shown; i++,
  1279. element_pos += 4)
  1280. {
  1281. // Text line
  1282. di_types[element_pos] = DE_TEXT;
  1283. // Validation buttons
  1284. di_types[element_pos + 1] = DE_BUTTON;
  1285. di_types[element_pos + 2] = DE_BUTTON;
  1286. di_types[element_pos + 3] = DE_BUTTON;
  1287. di_strs[element_pos] = error_messages[start_line + i];
  1288. switch(validity_options[start_line + i])
  1289. {
  1290. case invalid_uncertain:
  1291. {
  1292. sprintf(error_messages[start_line + i] + 45, "(ignore)");
  1293. break;
  1294. }
  1295. case invalid_discard:
  1296. {
  1297. sprintf(error_messages[start_line + i] + 45, "(delete)");
  1298. break;
  1299. }
  1300. case invalid_comment:
  1301. {
  1302. sprintf(error_messages[start_line + i] + 44, "(comment)");
  1303. break;
  1304. }
  1305. }
  1306. di_strs[element_pos + 1] = "I";
  1307. di_strs[element_pos + 2] = "D";
  1308. di_strs[element_pos + 3] = "C";
  1309. di_xs[element_pos] = 2;
  1310. di_xs[element_pos + 1] = 56;
  1311. di_xs[element_pos + 2] = 60;
  1312. di_xs[element_pos + 3] = 64;
  1313. di_ys[element_pos] = i + 4;
  1314. di_ys[element_pos + 1] = i + 4;
  1315. di_ys[element_pos + 2] = i + 4;
  1316. di_ys[element_pos + 3] = i + 4;
  1317. di_p1s[element_pos + 1] = start_line + i + 100;
  1318. di_p1s[element_pos + 2] = start_line + i + 200;
  1319. di_p1s[element_pos + 3] = start_line + i + 300;
  1320. }
  1321. if(multi_pages)
  1322. {
  1323. if(start_line)
  1324. {
  1325. di_types[element_pos] = DE_BUTTON;
  1326. di_strs[element_pos] = "Previous";
  1327. di_xs[element_pos] = 5;
  1328. di_ys[element_pos] = 17;
  1329. di_p1s[element_pos] = 1;
  1330. element_pos++;
  1331. }
  1332. if((start_line + 12) < num_errors)
  1333. {
  1334. di_types[element_pos] = DE_BUTTON;
  1335. di_strs[element_pos] = "Next";
  1336. di_xs[element_pos] = 61;
  1337. di_ys[element_pos] = 17;
  1338. di_p1s[element_pos] = 2;
  1339. element_pos++;
  1340. }
  1341. sprintf(information, "%d errors found; displaying %d through %d.\n", num_errors,
  1342. start_line + 1, start_line + 1 + errors_shown);
  1343. }
  1344. else
  1345. {
  1346. if(num_errors == 1)
  1347. {
  1348. sprintf(information, "1 error found.");
  1349. }
  1350. else
  1351. if(!num_errors)
  1352. {
  1353. sprintf(information, "No errors found.");
  1354. }
  1355. else
  1356. {
  1357. sprintf(information, "%d errors found.", num_errors);
  1358. }
  1359. }
  1360. di.num_elements = element_pos;
  1361. dialog_result = run_dialog(mzx_world, &di, 0, 0);
  1362. if(dialog_result == -1)
  1363. {
  1364. // Cancel - bails
  1365. redo = 0;
  1366. }
  1367. else
  1368. if(dialog_result == 0)
  1369. {
  1370. // Okay, update validity options
  1371. redo = 0;
  1372. for(i = 0; i < num_errors; i++)
  1373. {
  1374. (line_pointers[i])->validity_status = validity_options[i];
  1375. if(validity_options[i] == invalid_comment)
  1376. {
  1377. (line_pointers[i])->line_bytecode_length =
  1378. (line_pointers[i])->line_text_length + 5;
  1379. }
  1380. else
  1381. {
  1382. (line_pointers[i])->line_bytecode_length = 0;
  1383. (line_pointers[i])->line_text_length = 0;
  1384. }
  1385. }
  1386. *size = current_size;
  1387. }
  1388. else
  1389. if((dialog_result >= 100) && (dialog_result < 200))
  1390. {
  1391. // If the last is comment, adjust size
  1392. if(validity_options[dialog_result - 100] == invalid_comment)
  1393. {
  1394. current_size -=
  1395. (line_pointers[dialog_result - 100])->line_text_length + 5;
  1396. }
  1397. // Make it ignore
  1398. validity_options[dialog_result - 100] = invalid_uncertain;
  1399. }
  1400. else
  1401. if((dialog_result >= 200) && (dialog_result < 300))
  1402. {
  1403. // If the last is comment, adjust size
  1404. if(validity_options[dialog_result - 200] == invalid_comment)
  1405. {
  1406. current_size -=
  1407. (line_pointers[dialog_result - 200])->line_text_length + 5;
  1408. }
  1409. // Make it delete
  1410. validity_options[dialog_result - 200] = invalid_discard;
  1411. }
  1412. else
  1413. if((dialog_result >= 300) && (dialog_result < 400))
  1414. {
  1415. if(current_size +
  1416. ((line_pointers[dialog_result - 300])->line_text_length + 5) <
  1417. MAX_OBJ_SIZE)
  1418. {
  1419. // If the last is not comment, adjust size
  1420. if(validity_options[dialog_result - 300] != invalid_comment)
  1421. {
  1422. current_size +=
  1423. (line_pointers[dialog_result - 300])->line_text_length + 5;
  1424. }
  1425. // Make it comment
  1426. validity_options[dialog_result - 300] = invalid_comment;
  1427. }
  1428. }
  1429. else
  1430. if(dialog_result == 1)
  1431. {
  1432. start_line -= 13;
  1433. }
  1434. else
  1435. if(dialog_result == 2)
  1436. {
  1437. start_line += 13;
  1438. }
  1439. } while(redo);
  1440. }
  1441. return num_ignore;
  1442. }
  1443. int block_menu(World *mzx_world)
  1444. {
  1445. char di_types[3] = { DE_RADIO, DE_BUTTON, DE_BUTTON };
  1446. char di_xs[3] = { 2, 5, 15 };
  1447. char di_ys[3] = { 2, 7, 7 };
  1448. char *di_strs[3] =
  1449. {
  1450. "Copy block\n"
  1451. "Cut block\n"
  1452. "Clear block\n"
  1453. "Export block\n",
  1454. "OK", "Cancel"
  1455. };
  1456. int di_p1s[3] = { 4, 0, -1 };
  1457. int di_p2s[1] = { 21 };
  1458. int block_op = 0;
  1459. void *di_storage[1] = { &block_op };
  1460. dialog di =
  1461. {
  1462. 26, 6, 53, 15, "Choose block command", 3, di_types, di_xs,
  1463. di_ys, di_strs, di_p1s, di_p2s, di_storage, 0
  1464. };
  1465. if(run_dialog(mzx_world, &di, 0, 0) == -1)
  1466. return -1;
  1467. else
  1468. return block_op;
  1469. }
  1470. void copy_block_to_buffer(robot_line *start_rline, int num_lines)
  1471. {
  1472. robot_line *current_rline;
  1473. int line_length;
  1474. int i;
  1475. // First, if there's something already there, clear all the lines and
  1476. // the buffer.
  1477. if(copy_buffer)
  1478. {
  1479. for(i = 0; i < copy_buffer_lines; i++)
  1480. {
  1481. free(copy_buffer[i]);
  1482. }
  1483. free(copy_buffer);
  1484. }
  1485. copy_buffer = (char **)malloc(sizeof(char *) * num_lines);
  1486. copy_buffer_lines = num_lines;
  1487. current_rline = start_rline;
  1488. for(i = 0; i < num_lines; i++)
  1489. {
  1490. line_length = current_rline->line_text_length + 1;
  1491. copy_buffer[i] = (char *)malloc(line_length);
  1492. memcpy(copy_buffer[i], current_rline->line_text, line_length);
  1493. current_rline = current_rline->next;
  1494. }
  1495. }
  1496. void paste_buffer(robot_line *current_rline, int *total_lines,
  1497. int *current_line, int *size, int include_ignores, int base,
  1498. validity_types invalid_status)
  1499. {
  1500. int i;
  1501. for(i = 0; i < copy_buffer_lines; i++)
  1502. {
  1503. if(add_line(current_rline, current_rline->previous, size,
  1504. copy_buffer[i], include_ignores, base, invalid_status))
  1505. {
  1506. (*current_line)++;
  1507. (*total_lines)++;
  1508. }
  1509. else
  1510. {
  1511. break;
  1512. }
  1513. }
  1514. }
  1515. robot_line *clear_block(int first_line, robot_line *first_rline,
  1516. int num_lines, int *current_line, int *total_lines, int *size,
  1517. robot_line *cursor_rline)
  1518. {
  1519. robot_line *current_rline, *next_line;
  1520. robot_line *previous = first_rline->previous;
  1521. int n_current_line = *current_line;
  1522. int i;
  1523. for(current_rline = first_rline, i = 0; i < num_lines; i++)
  1524. {
  1525. next_line = current_rline->next;
  1526. *size += remove_line(current_rline);
  1527. (*total_lines)--;
  1528. current_rline = next_line;
  1529. }
  1530. if(*total_lines == 0)
  1531. {
  1532. // Add a new line
  1533. if(add_blank_line(NULL, previous, size))
  1534. *total_lines = 1;
  1535. cursor_rline = previous->next;
  1536. }
  1537. else
  1538. if(n_current_line >= first_line)
  1539. {
  1540. if(n_current_line > (first_line + num_lines))
  1541. {
  1542. *current_line = n_current_line - num_lines;
  1543. }
  1544. else
  1545. {
  1546. *current_line = first_line;
  1547. if(current_rline)
  1548. {
  1549. cursor_rline = current_rline;
  1550. }
  1551. else
  1552. {
  1553. cursor_rline = previous;
  1554. *current_line = first_line - 1;
  1555. }
  1556. }
  1557. }
  1558. return cursor_rline;
  1559. }
  1560. void export_block(World *mzx_world, robot_line *base, robot_line *block_start,
  1561. robot_line *block_end, int region_default)
  1562. {
  1563. robot_line *current_rline;
  1564. robot_line *end_rline;
  1565. char di_types[6] = { DE_INPUT, DE_RADIO, DE_BUTTON, DE_BUTTON, DE_RADIO };
  1566. char di_xs[5] = { 5, 31, 15, 31, 5 };
  1567. char di_ys[5] = { 2, 4, 7, 7, 4 };
  1568. char *di_strs[5] =
  1569. {
  1570. "Export robot as: ",
  1571. "Text\n"
  1572. "Bytecode",
  1573. "OK", "Cancel",
  1574. "Entire robot\n"
  1575. "Current block"
  1576. };
  1577. int di_p1s[5] = { 32, 2, 0, -1, 2 };
  1578. int di_p2s[5] = { 192, 8, 0, 0, 13 };
  1579. int export_region = region_default;
  1580. int export_type = 0;
  1581. char export_name[64];
  1582. void *di_storage[5] = { export_name, &export_type, NULL, NULL, &export_region };
  1583. dialog di =
  1584. {
  1585. 10, 8, 69, 17, "Export Robot", 5, di_types, di_xs,
  1586. di_ys, di_strs, di_p1s, di_p2s, di_storage, 0
  1587. };
  1588. export_name[0] = 0;
  1589. if(!region_default)
  1590. {
  1591. di.num_elements = 4;
  1592. }
  1593. if(!run_dialog(mzx_world, &di, 0, 0))
  1594. {
  1595. FILE *export_file;
  1596. if(!export_region)
  1597. {
  1598. current_rline = base->next;
  1599. end_rline = NULL;
  1600. }
  1601. else
  1602. {
  1603. current_rline = block_start;
  1604. end_rline = block_end->next;
  1605. }
  1606. if(!export_type)
  1607. {
  1608. add_ext(export_name, ".txt");
  1609. export_file = fopen(export_name, "wt");
  1610. while(current_rline != end_rline)
  1611. {
  1612. fputs(current_rline->line_text, export_file);
  1613. fputc('\n', export_file);
  1614. current_rline = current_rline->next;
  1615. }
  1616. }
  1617. else
  1618. {
  1619. add_ext(export_name, ".bc");
  1620. export_file = fopen(export_name, "wb");
  1621. fputc(0xFF, export_file);
  1622. while(current_rline != end_rline)
  1623. {
  1624. fwrite(current_rline->line_bytecode,
  1625. current_rline->line_bytecode_length, 1, export_file);
  1626. current_rline = current_rline->next;
  1627. }
  1628. fputc(0, export_file);
  1629. }
  1630. fclose(export_file);
  1631. }
  1632. }
  1633. void import_block(World *mzx_world, robot_line *current_rline,
  1634. int *total_lines, int *current_line, int *size, int include_ignores,
  1635. int base, validity_types invalid_status)
  1636. {
  1637. char import_name[128];
  1638. char *txt_ext[] = { ".TXT", NULL };
  1639. if(!choose_file(txt_ext, import_name, "Import Robot", 0))
  1640. {
  1641. FILE *import_file = fopen(import_name, "rt");
  1642. char line_buffer[256];
  1643. int i;
  1644. while(fgets(line_buffer, 255, import_file))
  1645. {
  1646. line_buffer[strlen(line_buffer) - 1] = 0;
  1647. if(add_line(current_rline, current_rline->previous, size,
  1648. line_buffer, include_ignores, base, invalid_status))
  1649. {
  1650. (*current_line)++;
  1651. (*total_lines)++;
  1652. }
  1653. else
  1654. {
  1655. break;
  1656. }
  1657. }
  1658. }
  1659. }
  1660. void edit_settings(World *mzx_world)
  1661. {
  1662. // 38 x 12
  1663. char di_types[8] = { DE_TEXT, DE_INPUT, DE_INPUT, DE_INPUT, DE_INPUT,
  1664. DE_INPUT, DE_BUTTON, DE_BUTTON };
  1665. char di_xs[8] = { 5, 5, 5, 5, 5, 5, 15, 37 };
  1666. char di_ys[8] = { 2, 4, 5, 6, 7, 8, 10, 10 };
  1667. char new_macros[5][64];
  1668. memcpy(new_macros, macros, 64 * 5);
  1669. char *di_strs[8] =
  1670. {
  1671. "Macros:",
  1672. "F6- ", "F7- ", "F8- ", "F9- ", "F10- ",
  1673. "OK", "Cancel"
  1674. };
  1675. int di_p1s[8] = { 0, 43, 43, 43, 43, 43, 0, -1 };
  1676. int di_p2s[8] = { 0 };
  1677. void *di_storage[8] = { 0, new_macros[0], new_macros[1], new_macros[2],
  1678. new_macros[3], new_macros[4] };
  1679. dialog di =
  1680. {
  1681. 10, 6, 69, 17, "Edit settings", 8, di_types, di_xs,
  1682. di_ys, di_strs, di_p1s, di_p2s, di_storage, 1
  1683. };
  1684. if(!run_dialog(mzx_world, &di, 0, 0))
  1685. memcpy(macros, new_macros, 64 * 5);
  1686. }