PageRenderTime 63ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/tags/BranchStart-observer/gui/gui_src_asm.c

#
C | 1893 lines | 1408 code | 358 blank | 127 comment | 179 complexity | a3f939b2a7a2bcc7802c93c6c432bc2b MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, LGPL-3.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/errno.h>
  4. #include "../config.h"
  5. #ifdef HAVE_GUI
  6. #include <gtk/gtk.h>
  7. #include <gdk/gdk.h>
  8. #include <gdk/gdkx.h>
  9. #include <gdk/gdkkeysyms.h>
  10. #include <glib.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13. #include <gtkextra/gtkcombobox.h>
  14. #include <gtkextra/gtkbordercombo.h>
  15. #include <gtkextra/gtkcolorcombo.h>
  16. #include <gtkextra/gtksheet.h>
  17. //#include <gtkextra/gtksheetentry.h>
  18. #include "gui.h"
  19. #include <assert.h>
  20. #include "../xpms/pc.xpm"
  21. #include "../xpms/break.xpm"
  22. #define PIXMAP_SIZE 14
  23. #define PIXMAP_POS(sbaw,e) ((e)->pixel+(sbaw)->layout_offset+-PIXMAP_SIZE/2-(e)->font_center)
  24. static GList *sa_xlate_list[SBAW_NRFILES]={NULL}; // lists containing sa_entry pointers
  25. static struct sa_entry *gui_line_to_entry(int id,int line);
  26. static struct sa_entry *gui_index_to_entry(int id, int index);
  27. typedef enum {
  28. MENU_FIND_TEXT,
  29. MENU_FIND_PC,
  30. MENU_MOVE_PC,
  31. MENU_RUN_HERE,
  32. MENU_BP_HERE,
  33. MENU_SELECT_SYMBOL,
  34. MENU_STEP,
  35. MENU_STEP_OVER,
  36. MENU_RUN,
  37. MENU_STOP,
  38. MENU_RETURN,
  39. MENU_RESET
  40. } menu_id;
  41. typedef struct _menu_item {
  42. char *name;
  43. menu_id id;
  44. GtkWidget *item;
  45. } menu_item;
  46. static menu_item menu_items[] = {
  47. {"Find PC", MENU_FIND_PC,NULL},
  48. {"Run here", MENU_RUN_HERE,NULL},
  49. {"Move PC here", MENU_MOVE_PC,NULL},
  50. {"Breakpoint here", MENU_BP_HERE,NULL},
  51. {"Select symbol", MENU_SELECT_SYMBOL,NULL},
  52. {"Find text...", MENU_FIND_TEXT,NULL},
  53. };
  54. static menu_item submenu_items[] = {
  55. {"Step", MENU_STEP,NULL},
  56. {"Step Over", MENU_STEP_OVER,NULL},
  57. {"Run", MENU_RUN,NULL},
  58. {"Stop", MENU_STOP,NULL},
  59. {"Reset", MENU_RESET,NULL},
  60. {"Return", MENU_RETURN,NULL},
  61. };
  62. // this should be in SourceBrowserAsm struct FIXME
  63. static struct {
  64. int found; //
  65. int looped; // if search hit start or end of text
  66. int start; //
  67. int lastfound; // index into text for start of last found string
  68. int i; //
  69. int lastid; //
  70. GtkWidget *window; // the window for find dialog
  71. GtkWidget *entry; // string GtkCombo
  72. GtkWidget *backwards_button; // togglebutton for direction
  73. GtkWidget *case_button; // togglebutton for case sensitivity
  74. GList *combo_strings; // list of strings for combo
  75. char *string; // current string, extracted from entry
  76. } search = {0,0,-1,0,0,0,0,0,0,0};
  77. static int dlg_x=200, dlg_y=200;
  78. // all of these gui_xxxx_to_entry() do linear searching.
  79. // Binary search is possible, the list is sorted. But pic
  80. // sources don't become large (not mine anyways).
  81. //pixel is 0 -> maxfont-1 for line zero.
  82. // maxfont -> maxfont*2-1 for line one
  83. // ...
  84. static struct sa_entry *gui_pixel_to_entry(int id, int pixel)
  85. {
  86. struct sa_entry *e; // to simplify expressions
  87. GList *p; // iterator
  88. assert(sa_xlate_list[id]!=NULL);
  89. if(pixel<0)
  90. return (struct sa_entry*)sa_xlate_list[id]->data;
  91. p=sa_xlate_list[id];
  92. // find listentry with address larger than argument
  93. while(p->next!=NULL)
  94. {
  95. e = (struct sa_entry*)p->data;
  96. if(e->pixel > pixel)
  97. break;
  98. p=p->next;
  99. }
  100. e=(struct sa_entry*)p->data;
  101. return e;
  102. }
  103. static struct sa_entry *gui_line_to_entry(int id, int line)
  104. {
  105. struct sa_entry *e;
  106. GList *p;
  107. assert(sa_xlate_list[id]!=NULL);
  108. assert(line>=0);
  109. p=sa_xlate_list[id];
  110. /*
  111. locate listentry with index larger than argument
  112. */
  113. while(p->next!=NULL)
  114. {
  115. e = (struct sa_entry*)p->data;
  116. if(e->line > line)
  117. break;
  118. p=p->next;
  119. }
  120. assert(p->prev); // FIXME, happens if only one line of source
  121. p=p->prev;
  122. e=(struct sa_entry*)p->data;
  123. return e;
  124. }
  125. static struct sa_entry *gui_index_to_entry(int id, int index)
  126. {
  127. struct sa_entry *e;
  128. GList *p;
  129. assert(sa_xlate_list[id]!=NULL);
  130. assert(index>=0);
  131. p=sa_xlate_list[id];
  132. /*
  133. locate listentry with index larger than argument
  134. */
  135. while(p->next!=NULL)
  136. {
  137. e = (struct sa_entry*)p->data;
  138. if(e->index > index)
  139. break;
  140. p=p->next;
  141. }
  142. assert(p->prev); // FIXME, could happen
  143. p=p->prev;
  144. e=(struct sa_entry*)p->data;
  145. return e;
  146. }
  147. void SourceBrowserAsm_set_pc(SourceBrowserAsm_Window *sbaw, int address)
  148. {
  149. struct sa_entry *e;
  150. int row;
  151. unsigned int pixel;
  152. float inc;
  153. int i;
  154. // static GtkWidget *old_pcw=NULL;
  155. GtkWidget *new_pcw;
  156. int id=-1;
  157. assert(sbaw);
  158. if(!sbaw->source_loaded) return;
  159. // find notebook page containing address 'address'
  160. for(i=0;i<SBAW_NRFILES;i++)
  161. {
  162. if(sbaw->pageindex_to_fileid[i]==gpsim_get_file_id( ((GUI_Object*)sbaw)->gp->pic_id, address))
  163. {
  164. id=i;
  165. }
  166. else
  167. {
  168. if( sbaw->source_pcwidget[i]!=NULL &&
  169. GTK_WIDGET_VISIBLE(sbaw->source_pcwidget[i]) )
  170. gtk_widget_hide(sbaw->source_pcwidget[i]);
  171. }
  172. }
  173. assert(id>-1);
  174. new_pcw = sbaw->source_pcwidget[id];
  175. row = gpsim_get_src_line(((GUI_Object*)sbaw)->gp->pic_id, address);
  176. if(row==INVALID_VALUE)
  177. return;
  178. row--;
  179. gtk_notebook_set_page(GTK_NOTEBOOK(sbaw->notebook),id);
  180. if(sbaw->layout_offset<0)
  181. { // can it normally be less than zero?
  182. // FIXME, this should be done whenever windows are reconfigured.
  183. int xtext,ytext;
  184. int xfixed, yfixed;
  185. if(GTK_TEXT(sbaw->source_text[id])->text_area!=NULL &&
  186. sbaw->source_layout[id]->window!=NULL)
  187. {
  188. gdk_window_get_origin(GTK_TEXT(sbaw->source_text[id])->text_area,&xtext,&ytext);
  189. gdk_window_get_origin(sbaw->source_layout[id]->window,&xfixed,&yfixed);
  190. sbaw->layout_offset = ytext-yfixed;
  191. }
  192. }
  193. e = gui_line_to_entry(id, row);
  194. pixel = PIXMAP_POS(sbaw,e);
  195. inc = GTK_ADJUSTMENT(GTK_TEXT(sbaw->source_text[id])->vadj)->page_increment;
  196. if( pixel<= GTK_TEXT(sbaw->source_text[id])->first_onscreen_ver_pixel ||
  197. pixel>= GTK_TEXT(sbaw->source_text[id])->first_onscreen_ver_pixel+inc )
  198. gtk_adjustment_set_value(GTK_ADJUSTMENT( GTK_TEXT( sbaw->source_text[id])->vadj),
  199. pixel-inc/2);
  200. // if(GTK_IS_WIDGET(old_pcw) && old_pcw!=new_pcw)
  201. // gtk_widget_hide(old_pcw);
  202. // old_pcw=new_pcw;
  203. gtk_layout_move(GTK_LAYOUT(sbaw->source_layout[id]),
  204. new_pcw,
  205. PIXMAP_SIZE,
  206. PIXMAP_POS(sbaw,e)
  207. );
  208. if(!GTK_WIDGET_VISIBLE(new_pcw))
  209. gtk_widget_show(new_pcw);
  210. }
  211. static void pc_changed(struct cross_reference_to_gui *xref, int new_address)
  212. {
  213. SourceBrowserAsm_Window *sbaw;
  214. sbaw = (SourceBrowserAsm_Window*)(xref->parent_window);
  215. if(sbaw->source_loaded)
  216. {
  217. SourceBrowserAsm_set_pc(sbaw, new_address);
  218. }
  219. }
  220. void SourceBrowserAsm_select_address( SourceBrowserAsm_Window *sbaw, int address)
  221. {
  222. struct sa_entry *e;
  223. int id=-1, i;
  224. int pixel;
  225. float inc;
  226. int line;
  227. for(i=0;i<SBAW_NRFILES;i++)
  228. {
  229. if(sbaw->pageindex_to_fileid[i]==gpsim_get_file_id( ((GUI_Object*)sbaw)->gp->pic_id, address))
  230. {
  231. id=i;
  232. }
  233. }
  234. assert(id>-1);
  235. gtk_notebook_set_page(GTK_NOTEBOOK(sbaw->notebook),id);
  236. line = gpsim_get_src_line(((GUI_Object*)sbaw)->gp->pic_id, address);
  237. if(line==INVALID_VALUE)
  238. return;
  239. //line = ((GUI_Object*)sbaw)->gp->p->program_memory[address]->get_src_line();
  240. e = gui_line_to_entry(id, line);
  241. pixel = PIXMAP_POS(sbaw,e);
  242. inc = GTK_ADJUSTMENT(GTK_TEXT(sbaw->source_text[id])->vadj)->page_increment;
  243. if( pixel<= GTK_TEXT(sbaw->source_text[id])->first_onscreen_ver_pixel ||
  244. pixel>= GTK_TEXT(sbaw->source_text[id])->first_onscreen_ver_pixel+inc )
  245. gtk_adjustment_set_value(GTK_ADJUSTMENT( GTK_TEXT( sbaw->source_text[id])->vadj),
  246. pixel-inc/2);
  247. }
  248. /*
  249. this happens when breakpoint is set or unset
  250. ( Can it happen for another reason? )
  251. */
  252. void SourceBrowserAsm_update_line( SourceBrowserAsm_Window *sbaw, int address)
  253. {
  254. int row;
  255. int i,id=-1;
  256. struct sa_entry *e;
  257. assert(sbaw);
  258. assert(sbaw->sbw.gui_obj.wt == WT_asm_source_window);
  259. assert(address>=0);
  260. if(!sbaw->source_loaded) return;
  261. for(i=0;i<SBAW_NRFILES;i++)
  262. {
  263. if(sbaw->pageindex_to_fileid[i]==gpsim_get_file_id( ((GUI_Object*)sbaw)->gp->pic_id, address))
  264. {
  265. id=i;
  266. }
  267. }
  268. if(id==-1)
  269. {
  270. puts("SourceBrowserAsm_update_line(): could not find notebook page");
  271. return;
  272. }
  273. row = gpsim_get_src_line(((GUI_Object*)sbaw)->gp->pic_id, address);
  274. //row = ((GUI_Object*)sbaw)->gp->p->program_memory[address]->get_src_line();
  275. if(row==INVALID_VALUE)
  276. return;
  277. row--;
  278. e = gui_line_to_entry(id,row);
  279. if(e==NULL)
  280. {
  281. puts("This is odd!?");
  282. return;
  283. }
  284. for(i=0;i<MAX_BREAKPOINTS;i++)
  285. { // FIXME, reuse pixmaps or not?
  286. if(sbaw->breakpoint[i].widget==NULL)
  287. break;
  288. if(sbaw->breakpoint[i].address==address)
  289. break;
  290. }
  291. if(i>=MAX_BREAKPOINTS)
  292. return;
  293. if( gpsim_address_has_breakpoint( ((GUI_Object*)sbaw)->gp->pic_id, address))
  294. {
  295. if(sbaw->breakpoint[i].widget==NULL)
  296. {
  297. sbaw->breakpoint[i].widget = gtk_pixmap_new(sbaw->pixmap_break,sbaw->mask);
  298. gtk_layout_put(GTK_LAYOUT(sbaw->source_layout[id]),
  299. sbaw->breakpoint[i].widget,
  300. 0,
  301. PIXMAP_POS(sbaw,e)
  302. );
  303. }
  304. else
  305. {
  306. gtk_layout_move(GTK_LAYOUT(sbaw->source_layout[id]),
  307. sbaw->breakpoint[i].widget,
  308. 0,
  309. PIXMAP_POS(sbaw,e)
  310. );
  311. }
  312. sbaw->breakpoint[i].address=address;
  313. gtk_widget_show(sbaw->breakpoint[i].widget);
  314. }
  315. else if(sbaw->breakpoint[i].widget!=NULL)
  316. {
  317. gtk_widget_hide(sbaw->breakpoint[i].widget);
  318. }
  319. }
  320. SourceBrowserAsm_Window *popup_sbaw;
  321. static void
  322. popup_activated(GtkWidget *widget, gpointer data)
  323. {
  324. menu_item *item;
  325. int id, address, line;
  326. char text[256];
  327. int i,start,end, temp;
  328. int pic_id;
  329. item = (menu_item *)data;
  330. id = gtk_notebook_get_current_page(GTK_NOTEBOOK(popup_sbaw->notebook));
  331. pic_id=((GUI_Object*)popup_sbaw)->gp->pic_id;
  332. switch(item->id)
  333. {
  334. case MENU_FIND_TEXT:
  335. gtk_widget_set_uposition(GTK_WIDGET(search.window),dlg_x,dlg_y);
  336. gtk_widget_show(search.window);
  337. break;
  338. case MENU_FIND_PC:
  339. pic_id = popup_sbaw->sbw.gui_obj.gp->pic_id;
  340. address=gpsim_get_pc_value(pic_id);
  341. SourceBrowserAsm_set_pc(popup_sbaw, address);
  342. // gui_simulation_has_stopped(); // FIXME
  343. break;
  344. case MENU_MOVE_PC:
  345. line = popup_sbaw->menu_data->line;
  346. address = gpsim_find_closest_address_to_line(pic_id,popup_sbaw->pageindex_to_fileid[id],line+1);
  347. if(address!=INVALID_VALUE)
  348. gpsim_put_pc_value(pic_id,address);
  349. break;
  350. case MENU_RUN_HERE:
  351. line = popup_sbaw->menu_data->line;
  352. address = gpsim_find_closest_address_to_line(pic_id,popup_sbaw->pageindex_to_fileid[id],line+1);
  353. if(address!=INVALID_VALUE)
  354. gpsim_run_to_address(pic_id, address);
  355. break;
  356. case MENU_BP_HERE:
  357. line = popup_sbaw->menu_data->line;
  358. gpsim_toggle_break_at_line(pic_id,popup_sbaw->pageindex_to_fileid[id] ,line+1);
  359. break;
  360. case MENU_SELECT_SYMBOL:
  361. start=GTK_EDITABLE(popup_sbaw->source_text[id])->selection_start_pos;
  362. end=GTK_EDITABLE(popup_sbaw->source_text[id])->selection_end_pos;
  363. if(start>end)
  364. {
  365. temp=start;
  366. start=end;
  367. end=temp;
  368. }
  369. if((end-start+2)>256) // FIXME bounds?
  370. end=start+256-2;
  371. for(i=start;i<end;i++)
  372. {
  373. text[i-start]=GTK_TEXT_INDEX(GTK_TEXT(popup_sbaw->source_text[id]),i);
  374. }
  375. text[i-start]=0;
  376. if(!popup_sbaw->sbw.gui_obj.gp->symbol_window->gui_obj.enabled)
  377. {
  378. popup_sbaw->sbw.gui_obj.gp->symbol_window->gui_obj.
  379. change_view(&popup_sbaw->sbw.gui_obj.gp->symbol_window->gui_obj,
  380. VIEW_SHOW);
  381. }
  382. SymbolWindow_select_symbol_name(((GUI_Object*)popup_sbaw)->gp->symbol_window,text);
  383. break;
  384. case MENU_STEP:
  385. gpsim_step(popup_sbaw->sbw.gui_obj.gp->pic_id, 1);
  386. break;
  387. case MENU_STEP_OVER:
  388. gpsim_step_over(popup_sbaw->sbw.gui_obj.gp->pic_id);
  389. break;
  390. case MENU_RUN:
  391. gpsim_run(popup_sbaw->sbw.gui_obj.gp->pic_id);
  392. break;
  393. case MENU_STOP:
  394. case MENU_RESET:
  395. case MENU_RETURN:
  396. puts("Not implemented");
  397. break;
  398. default:
  399. puts("Unhandled menuitem?");
  400. break;
  401. }
  402. }
  403. static GtkWidget *
  404. build_menu(GtkWidget *sheet, SourceBrowserAsm_Window *sbaw)
  405. {
  406. GtkWidget *menu;
  407. GtkWidget *submenu;
  408. GtkWidget *item;
  409. int i;
  410. int id;
  411. popup_sbaw=sbaw;
  412. id = gtk_notebook_get_current_page(GTK_NOTEBOOK(popup_sbaw->notebook));
  413. menu=gtk_menu_new();
  414. for (i=0; i < (sizeof(menu_items)/sizeof(menu_items[0])) ; i++){
  415. item=gtk_menu_item_new_with_label(menu_items[i].name);
  416. menu_items[i].item=item;
  417. gtk_signal_connect(GTK_OBJECT(item),"activate",
  418. (GtkSignalFunc) popup_activated,
  419. &menu_items[i]);
  420. gtk_widget_show(item);
  421. gtk_menu_append(GTK_MENU(menu),item);
  422. }
  423. submenu=gtk_menu_new();
  424. item = gtk_tearoff_menu_item_new ();
  425. gtk_menu_append (GTK_MENU (submenu), item);
  426. gtk_widget_show (item);
  427. for (i=0; i < (sizeof(submenu_items)/sizeof(submenu_items[0])) ; i++){
  428. item=gtk_menu_item_new_with_label(submenu_items[i].name);
  429. submenu_items[i].item=item;
  430. gtk_signal_connect(GTK_OBJECT(item),"activate",
  431. (GtkSignalFunc) popup_activated,
  432. &submenu_items[i]);
  433. GTK_WIDGET_SET_FLAGS (item, GTK_SENSITIVE | GTK_CAN_FOCUS);
  434. if(submenu_items[i].id==MENU_STOP)
  435. {
  436. GTK_WIDGET_UNSET_FLAGS (item,
  437. GTK_SENSITIVE | GTK_CAN_FOCUS);
  438. }
  439. gtk_widget_show(item);
  440. gtk_menu_append(GTK_MENU(submenu),item);
  441. }
  442. item = gtk_menu_item_new_with_label ("Controls");
  443. gtk_menu_append (GTK_MENU (menu), item);
  444. gtk_widget_show (item);
  445. gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
  446. return menu;
  447. }
  448. /*
  449. button event handler for sbaw->source_text[id].
  450. If we get button1 doubleclick event then we toggle breakpoint
  451. If we get button3 buttonpress then we popup menu.
  452. */
  453. static gint sigh_button_event(GtkWidget *widget,
  454. GdkEventButton *event,
  455. SourceBrowserAsm_Window *sbaw)
  456. {
  457. int id;
  458. int i;
  459. GtkWidget *item;
  460. assert(event&&sbaw);
  461. id = gtk_notebook_get_current_page(GTK_NOTEBOOK(sbaw->notebook));
  462. if(event->type==GDK_BUTTON_PRESS &&
  463. event->button==3)
  464. {
  465. GtkWidget *popup=NULL;
  466. popup_sbaw=sbaw;
  467. sbaw->menu_data = gui_pixel_to_entry(id, (int) (event->y + GTK_TEXT(sbaw->source_text[id])->vadj->value));
  468. for (i=0; i < (sizeof(menu_items)/sizeof(menu_items[0])) ; i++){
  469. item=menu_items[i].item;
  470. switch(menu_items[i].id){
  471. case MENU_SELECT_SYMBOL:
  472. // Why does "if(editable->has_selection)" not work? FIXME
  473. if(GTK_EDITABLE(popup_sbaw->source_text[id])->selection_start_pos
  474. ==GTK_EDITABLE(popup_sbaw->source_text[id])->selection_end_pos)
  475. {
  476. gtk_widget_set_sensitive (item, FALSE);
  477. }
  478. else
  479. {
  480. gtk_widget_set_sensitive (item, TRUE);
  481. }
  482. break;
  483. default:
  484. break;
  485. }
  486. }
  487. gtk_menu_popup(GTK_MENU(sbaw->popup_menu), NULL, NULL, NULL, NULL,
  488. 3, event->time);
  489. // override source_text[id]'s handler
  490. // is there a better way? FIXME
  491. gtk_signal_emit_stop_by_name(GTK_OBJECT(sbaw->source_text[id]),"button_press_event");
  492. return TRUE;
  493. }
  494. if(event->type==GDK_BUTTON_PRESS && event->button==4)
  495. { // wheel scroll up
  496. GTK_TEXT(sbaw->source_text[id])->vadj->value-=GTK_TEXT(sbaw->source_text[id])->vadj->page_increment/4.0;
  497. if(GTK_TEXT(sbaw->source_text[id])->vadj->value < GTK_TEXT(sbaw->source_text[id])->vadj->lower)
  498. GTK_TEXT(sbaw->source_text[id])->vadj->value = GTK_TEXT(sbaw->source_text[id])->vadj->lower;
  499. gtk_adjustment_value_changed(GTK_TEXT(sbaw->source_text[id])->vadj);
  500. return TRUE;
  501. }
  502. if(event->type==GDK_BUTTON_PRESS && event->button==5)
  503. { // wheel scroll down
  504. GTK_TEXT(sbaw->source_text[id])->vadj->value+=GTK_TEXT(sbaw->source_text[id])->vadj->page_increment/4.0;
  505. if(GTK_TEXT(sbaw->source_text[id])->vadj->value > GTK_TEXT(sbaw->source_text[id])->vadj->upper-GTK_TEXT(sbaw->source_text[id])->vadj->page_increment)
  506. GTK_TEXT(sbaw->source_text[id])->vadj->value = GTK_TEXT(sbaw->source_text[id])->vadj->upper-GTK_TEXT(sbaw->source_text[id])->vadj->page_increment;
  507. gtk_adjustment_value_changed(GTK_TEXT(sbaw->source_text[id])->vadj);
  508. return TRUE;
  509. }
  510. return FALSE;
  511. }
  512. static void text_adj_cb(GtkAdjustment *adj, GtkAdjustment *adj_to_update)
  513. {
  514. // when sbaw->source_text[id] adjustment changes, we update the layout adj.
  515. // I assume that both adjustments count pixels
  516. assert(adj_to_update&&adj);
  517. if(adj_to_update && adj )
  518. {
  519. if (adj_to_update->upper >= adj->value )
  520. {
  521. gtk_adjustment_set_value(adj_to_update, adj->value);
  522. }
  523. }
  524. }
  525. static float drag_scroll_speed;
  526. static gint drag_scroll_cb(gpointer data)
  527. {
  528. SourceBrowserAsm_Window *sbaw = (SourceBrowserAsm_Window*)data;
  529. int id = gtk_notebook_get_current_page(GTK_NOTEBOOK(sbaw->notebook));
  530. GTK_TEXT(sbaw->source_text[id])->vadj->value+=
  531. GTK_TEXT(sbaw->source_text[id])->vadj->step_increment*drag_scroll_speed;
  532. if(GTK_TEXT(sbaw->source_text[id])->vadj->value < GTK_TEXT(sbaw->source_text[id])->vadj->lower ||
  533. GTK_TEXT(sbaw->source_text[id])->vadj->value > GTK_TEXT(sbaw->source_text[id])->vadj->upper-GTK_TEXT(sbaw->source_text[id])->vadj->page_increment)
  534. {
  535. if(drag_scroll_speed > 0)
  536. GTK_TEXT(sbaw->source_text[id])->vadj->value = GTK_TEXT(sbaw->source_text[id])->vadj->upper-GTK_TEXT(sbaw->source_text[id])->vadj->page_increment;
  537. else
  538. GTK_TEXT(sbaw->source_text[id])->vadj->value = GTK_TEXT(sbaw->source_text[id])->vadj->lower;
  539. }
  540. gtk_adjustment_value_changed(GTK_TEXT(sbaw->source_text[id])->vadj);
  541. return 1;
  542. }
  543. /*
  544. This is handler for motion, button press and release for source_layout.
  545. The GdkEventMotion and GdkEventButton are very similar so I use
  546. the same for both!
  547. This function is too complex, FIXME.
  548. */
  549. static void marker_cb(GtkWidget *w1,
  550. GdkEventButton *event,
  551. SourceBrowserAsm_Window *sbaw)
  552. {
  553. static int dragbreak=0;
  554. static int dragstartline;
  555. static int dragindex;
  556. static int button_pressed;
  557. static int button_pressed_y;
  558. static int button_pressed_x;
  559. static int dragwidget_oldy;
  560. int pixel;
  561. int line;
  562. unsigned int address;
  563. static GtkWidget *dragwidget;
  564. static int dragwidget_x;
  565. int mindiff;
  566. int i;
  567. int diff;
  568. static int timeout_tag=-1;
  569. int id = gtk_notebook_get_current_page(GTK_NOTEBOOK(sbaw->notebook));
  570. int pic_id = ((GUI_Object*)sbaw)->gp->pic_id;
  571. switch(event->type)
  572. {
  573. case GDK_MOTION_NOTIFY:
  574. if(button_pressed == 1 && dragbreak == 0)
  575. {
  576. button_pressed=0;
  577. // actually button is pressed, but setting
  578. // this to zero makes this block of code
  579. // execute exactly once for each drag motion
  580. if(button_pressed_x<PIXMAP_SIZE)
  581. {
  582. // find out if we want to start drag of a breakpoint
  583. i=0;
  584. mindiff=1000000; // large distance
  585. dragindex=-1; // start with invalid index
  586. while(sbaw->breakpoint[i].widget != NULL)
  587. {
  588. diff = button_pressed_y - (sbaw->breakpoint[i].widget->allocation.y+PIXMAP_SIZE/2);
  589. if(abs(diff) < abs(mindiff))
  590. {
  591. mindiff=diff;
  592. dragindex=i;
  593. }
  594. i++;
  595. }
  596. if(mindiff<PIXMAP_SIZE/2)
  597. { // mouse hit breakpoint pixmap with index dragindex
  598. // pixel = (position of pixmap in window)
  599. // - (constant) + (constant)
  600. // + (top of window, counting from top of text)
  601. pixel = sbaw->breakpoint[dragindex].widget->allocation.y-
  602. sbaw->layout_offset+PIXMAP_SIZE/2+
  603. (int)GTK_TEXT(sbaw->source_text[id])->vadj->value;
  604. // we want to remember which line drag started on
  605. // to be able to disable this breakpoint later
  606. // FIXME: perhaps we should simply disable bp now?
  607. dragstartline = gui_pixel_to_entry(id,pixel)->line;
  608. dragbreak=1; // start drag
  609. dragwidget = sbaw->breakpoint[dragindex].widget;
  610. dragwidget_x = 0;
  611. dragwidget_oldy=dragwidget->allocation.y+
  612. (int)GTK_TEXT(sbaw->source_text[id])->vadj->value;
  613. gtk_grab_add(sbaw->source_layout[id]);
  614. }
  615. }
  616. else
  617. { // we see if we hit the pixmap widget
  618. if( abs(button_pressed_y-
  619. (sbaw->source_pcwidget[id]->allocation.y+PIXMAP_SIZE/2)) <PIXMAP_SIZE/2)
  620. { // hit
  621. dragbreak=1; // start drag
  622. dragwidget = sbaw->source_pcwidget[id];
  623. dragwidget_x = PIXMAP_SIZE;
  624. dragwidget_oldy=dragwidget->allocation.y+
  625. (int)GTK_TEXT(sbaw->source_text[id])->vadj->value;
  626. gtk_grab_add(sbaw->source_layout[id]);
  627. }
  628. }
  629. }
  630. else if(dragbreak==1)
  631. { // drag is in progress
  632. if((event->y/GTK_TEXT(sbaw->source_text[id])->vadj->page_size) >0.9
  633. ||(event->y/GTK_TEXT(sbaw->source_text[id])->vadj->page_size) <0.1)
  634. {
  635. if(timeout_tag==-1)
  636. {
  637. timeout_tag = gtk_timeout_add(100,drag_scroll_cb,sbaw);
  638. }
  639. if((event->y/GTK_TEXT(sbaw->source_text[id])->vadj->page_size)>0.5)
  640. drag_scroll_speed = ((event->y/GTK_TEXT(sbaw->source_text[id])->vadj->page_size)-0.9)*100;
  641. else
  642. drag_scroll_speed = -(0.1-(event->y/GTK_TEXT(sbaw->source_text[id])->vadj->page_size))*100;
  643. }
  644. else if(timeout_tag!=-1)
  645. {
  646. gtk_timeout_remove(timeout_tag);
  647. timeout_tag=-1;
  648. }
  649. // update position of dragged pixmap
  650. gtk_layout_move(GTK_LAYOUT(sbaw->source_layout[id]),
  651. dragwidget,dragwidget_x,(int)event->y-PIXMAP_SIZE/2+
  652. (int)GTK_TEXT(sbaw->source_text[id])->vadj->value);
  653. }
  654. break;
  655. case GDK_BUTTON_PRESS:
  656. if(button_pressed==1)
  657. break; // click number two(/three?) of a double click?
  658. button_pressed = 1;
  659. button_pressed_x = (int)event->x; // and initial position of
  660. button_pressed_y = (int)event->y; // possible drag action
  661. break;
  662. case GDK_2BUTTON_PRESS:
  663. if(event->button == 1)
  664. {
  665. line = gui_pixel_to_entry(id, (int)event->y -
  666. sbaw->layout_offset +
  667. (int)GTK_TEXT(sbaw->source_text[id])->vadj->value)->line;
  668. gpsim_toggle_break_at_line(pic_id,sbaw->pageindex_to_fileid[id] ,line+1);
  669. }
  670. break;
  671. case GDK_BUTTON_RELEASE:
  672. button_pressed=0;
  673. if(timeout_tag!=-1)
  674. {
  675. gtk_timeout_remove(timeout_tag);
  676. timeout_tag=-1;
  677. }
  678. if(dragbreak==0)
  679. break; // we weren't dragging, so we don't move anything
  680. dragbreak=0;
  681. gtk_grab_remove(sbaw->source_layout[id]);
  682. // pixel = (position of pixmap in window)
  683. // + (constant) - (constant)
  684. // + (top of window, counting from top of text)
  685. pixel = dragwidget->allocation.y+PIXMAP_SIZE/2-
  686. sbaw->layout_offset+
  687. (int)GTK_TEXT(sbaw->source_text[id])->vadj->value;
  688. line = gui_pixel_to_entry(id,pixel)->line;
  689. if(dragwidget == sbaw->source_pcwidget[id])
  690. {
  691. address = gpsim_find_closest_address_to_line(pic_id,sbaw->pageindex_to_fileid[id],line+1);
  692. if(address!=INVALID_VALUE)
  693. gpsim_put_pc_value(pic_id,address);
  694. }
  695. else
  696. {
  697. gpsim_toggle_break_at_line(pic_id,sbaw->pageindex_to_fileid[id] ,dragstartline+1);
  698. gpsim_toggle_break_at_line(pic_id,sbaw->pageindex_to_fileid[id] ,line+1);
  699. }
  700. break;
  701. default:
  702. printf("Whoops? event type %d\n",event->type);
  703. break;
  704. }
  705. }
  706. /*
  707. Adds a page to the notebook, and returns notebook-id for that page.
  708. */
  709. static int add_page(SourceBrowserAsm_Window *sbaw, int file_id)
  710. {
  711. GtkWidget *hbox, *label, *vscrollbar;
  712. GtkStyle *style=NULL;
  713. int id;
  714. int pic_id = ((GUI_Object*)sbaw)->gp->pic_id;
  715. printf("%d\n",file_id);
  716. hbox = gtk_hbox_new(0,0);
  717. gtk_container_set_border_width (GTK_CONTAINER (hbox), 3);
  718. // label=gtk_label_new(((GUI_Object*)sbaw)->gp->p->files[file_id].name);
  719. label=gtk_label_new(gpsim_get_file_context(pic_id, file_id)->name);
  720. gtk_notebook_append_page(GTK_NOTEBOOK(sbaw->notebook),hbox,label);
  721. id=gtk_notebook_page_num(GTK_NOTEBOOK(sbaw->notebook),hbox);
  722. assert(id<SBAW_NRFILES && id >=0);
  723. sbaw->pageindex_to_fileid[id] = file_id;
  724. sbaw->notebook_child[id]=hbox;
  725. gtk_widget_show(hbox);
  726. sbaw->source_layout_adj[id] = (GtkAdjustment*)gtk_adjustment_new(0.0,0.0,0.0,0.0,0.0,0.0);
  727. sbaw->source_layout[id] = gtk_layout_new(NULL,sbaw->source_layout_adj[id]);
  728. gtk_widget_set_events(sbaw->source_layout[id],
  729. gtk_widget_get_events(sbaw->source_layout[id])|
  730. GDK_BUTTON_PRESS_MASK |
  731. GDK_BUTTON_MOTION_MASK |
  732. GDK_BUTTON_RELEASE_MASK);
  733. gtk_widget_show(sbaw->source_layout[id]);
  734. gtk_widget_set_usize(GTK_WIDGET(sbaw->source_layout[id]),PIXMAP_SIZE*2,0);
  735. gtk_box_pack_start(GTK_BOX(hbox), sbaw->source_layout[id],
  736. FALSE,FALSE, 0);
  737. vscrollbar = gtk_vscrollbar_new(NULL);
  738. gtk_widget_show(vscrollbar);
  739. sbaw->source_text[id] = gtk_text_new(NULL,GTK_RANGE(vscrollbar)->adjustment);
  740. gtk_text_set_word_wrap(GTK_TEXT(sbaw->source_text[id]),0);
  741. gtk_text_set_line_wrap(GTK_TEXT(sbaw->source_text[id]),0);
  742. gtk_widget_show(sbaw->source_text[id]);
  743. style=gtk_style_new();
  744. style->base[GTK_STATE_NORMAL].red=65535;
  745. style->base[GTK_STATE_NORMAL].green=65535;
  746. style->base[GTK_STATE_NORMAL].blue=65535;
  747. gtk_widget_set_style(GTK_WIDGET(sbaw->source_text[id]),style);
  748. gtk_signal_connect(GTK_OBJECT(sbaw->source_text[id]), "button_press_event",
  749. GTK_SIGNAL_FUNC(sigh_button_event), sbaw);
  750. gtk_box_pack_start_defaults(GTK_BOX(hbox), sbaw->source_text[id]);
  751. gtk_box_pack_start(GTK_BOX(hbox), vscrollbar,
  752. FALSE,FALSE, 0);
  753. gtk_signal_connect(GTK_OBJECT(GTK_TEXT(sbaw->source_text[id])->vadj),
  754. "value_changed",GTK_SIGNAL_FUNC(text_adj_cb),sbaw->source_layout_adj[id]);
  755. gtk_signal_connect(GTK_OBJECT(sbaw->source_layout[id]),"motion-notify-event",
  756. GTK_SIGNAL_FUNC(marker_cb),sbaw);
  757. gtk_signal_connect(GTK_OBJECT(sbaw->source_layout[id]),"button_press_event",
  758. GTK_SIGNAL_FUNC(marker_cb),sbaw);
  759. gtk_signal_connect(GTK_OBJECT(sbaw->source_layout[id]),"button_release_event",
  760. GTK_SIGNAL_FUNC(marker_cb),sbaw);
  761. // while(gtk_events_pending()) // display everything, so that
  762. // gtk_main_iteration(); // gtk_notebook_get_current_page() works
  763. // We create pixmaps here, where the gtk_widget_get_style() call will
  764. // succeed. I tried putting this code in CreateSourceBrowserAsmWindow()
  765. // but then the window was not realized. And if I manually realized
  766. // it, then the call to gtk_window_set_default_size() was ignored.
  767. // Was that a bug in gtk? (gtk version 1.2.3)
  768. if(sbaw->pixmap_pc==NULL)
  769. {
  770. style = gtk_widget_get_style(sbaw->sbw.gui_obj.window);
  771. sbaw->mask = NULL;
  772. sbaw->pixmap_pc = gdk_pixmap_create_from_xpm_d(sbaw->sbw.gui_obj.window->window, &sbaw->mask,
  773. &style->bg[GTK_STATE_NORMAL],
  774. (gchar**)pc_xpm);
  775. sbaw->pixmap_break = gdk_pixmap_create_from_xpm_d(sbaw->sbw.gui_obj.window->window, &sbaw->mask,
  776. &style->bg[GTK_STATE_NORMAL],
  777. (gchar**)break_xpm);
  778. }
  779. sbaw->source_pcwidget[id] = gtk_pixmap_new(sbaw->pixmap_pc,sbaw->mask);
  780. gtk_layout_put(GTK_LAYOUT(sbaw->source_layout[id]),
  781. sbaw->source_pcwidget[id],0,0);
  782. return id;
  783. }
  784. /*
  785. Fills sbaw->source_text[id] with text from
  786. file pointer sbaw->sbw.gui_obj.gp->p->files[file_id].file_ptr
  787. */
  788. static void set_text(SourceBrowserAsm_Window *sbaw, int id, int file_id)
  789. {
  790. int totallinesheight;
  791. int instruction_done;
  792. int lineascent, linedescent;
  793. char *p;
  794. char text_buffer[256];
  795. int cblock=0;
  796. int i;
  797. int index;
  798. int pic_id;
  799. int line=0;
  800. struct sa_entry *entry;
  801. GList *iter;
  802. // get a manageable pointer to the processor
  803. pic_id = ((GUI_Object*)sbaw)->gp->pic_id;
  804. gtk_text_freeze(GTK_TEXT(sbaw->source_text[id]));
  805. fseek(gpsim_get_file_context(pic_id,file_id)->file_ptr,
  806. 0,
  807. SEEK_SET);
  808. gtk_editable_delete_text(GTK_EDITABLE(sbaw->source_text[id]),0,-1);
  809. for(iter=sa_xlate_list[id];iter!=NULL;)
  810. {
  811. GList *next=iter->next;
  812. free( (struct sa_entry*)iter->data );
  813. g_list_remove(iter,iter->data); // FIXME. I really need a tutorial
  814. iter=next;
  815. // g_list_free_1(sa_xlate_list[id]); // FIXME, g_list_free() difference?
  816. }
  817. sa_xlate_list[id]=NULL;
  818. for(i=0;i<MAX_BREAKPOINTS;i++)
  819. if(sbaw->breakpoint[i].widget!=NULL)
  820. {
  821. sbaw->breakpoint[i].address=-1;
  822. gtk_widget_hide(sbaw->breakpoint[i].widget);
  823. sbaw->breakpoint[i].widget=NULL;
  824. }
  825. totallinesheight=0;
  826. while(fgets(text_buffer, 256, gpsim_get_file_context(pic_id,file_id)->file_ptr)!=NULL)
  827. {
  828. char *end, *q;
  829. lineascent=-1;
  830. linedescent=-1;
  831. instruction_done=0; // to seperate instruction from other text (symbols)
  832. index=gtk_text_get_length(GTK_TEXT(sbaw->source_text[id]));
  833. p=text_buffer;
  834. /* all of this pattern matching is a hack, the code is
  835. extended when i find misbehaviour */
  836. /* would it be better to use some regex stuff? */
  837. /* gtksctext could be a option, but then i guess gtksctext would
  838. have to be extended with some gtk_sctext_get_pixel_of_line(int line)
  839. or similar funtionality
  840. There is also a gtkextext widget...
  841. */
  842. if(*p=='#' || !strncmp(p,"include",7))
  843. { // not a label
  844. q=p;
  845. q++;
  846. while(isalnum(*q) || *q=='_')
  847. q++;
  848. gtk_text_insert(GTK_TEXT(sbaw->source_text[id]),
  849. sbaw->default_text_style.font,
  850. &sbaw->default_text_style.fg[GTK_STATE_NORMAL],
  851. &sbaw->default_text_style.base[GTK_STATE_NORMAL],
  852. p,
  853. q-p);
  854. p=q;
  855. instruction_done=1; // well, varable misnamed
  856. }
  857. else if( (isalnum(*p) || *p=='_'))
  858. { // a label
  859. // locate end of label
  860. q=p;
  861. while(isalnum(*q) || *q=='_')
  862. q++;
  863. if(lineascent<sbaw->label_text_style.font->ascent)
  864. lineascent=sbaw->label_text_style.font->ascent;
  865. if(linedescent<sbaw->label_text_style.font->descent)
  866. linedescent=sbaw->label_text_style.font->descent;
  867. gtk_text_insert(GTK_TEXT(sbaw->source_text[id]),
  868. sbaw->label_text_style.font,
  869. &sbaw->label_text_style.fg[GTK_STATE_NORMAL],
  870. &sbaw->label_text_style.base[GTK_STATE_NORMAL],
  871. text_buffer,
  872. q-p);
  873. // advance the pointer p
  874. p=q;
  875. }
  876. // 'end' is end of line
  877. end = text_buffer + strlen(text_buffer);
  878. // loop through the rest of the line
  879. while( p < end )
  880. {
  881. if( *p == ';')
  882. { // comment
  883. if(lineascent<sbaw->comment_text_style.font->ascent)
  884. lineascent=sbaw->comment_text_style.font->ascent;
  885. if(linedescent<sbaw->comment_text_style.font->descent)
  886. linedescent=sbaw->comment_text_style.font->descent;
  887. gtk_text_insert(GTK_TEXT(sbaw->source_text[id]),
  888. sbaw->comment_text_style.font,
  889. &sbaw->comment_text_style.fg[GTK_STATE_NORMAL],
  890. &sbaw->comment_text_style.base[GTK_STATE_NORMAL],
  891. p,
  892. -1);
  893. break;
  894. }
  895. else if(isalpha(*p) || *p=='_')
  896. { // instruction, symbol or cblock
  897. q=p;
  898. while(isalnum(*q) || *q=='_')
  899. q++;
  900. if( ( instruction_done==0 && cblock==0) || !strncasecmp(p,"endc",4) )
  901. { // instruction or cblock
  902. instruction_done=1;
  903. cblock=0;
  904. if(lineascent<sbaw->instruction_text_style.font->ascent)
  905. lineascent=sbaw->instruction_text_style.font->ascent;
  906. if(linedescent<sbaw->instruction_text_style.font->descent)
  907. linedescent=sbaw->instruction_text_style.font->descent;
  908. if(!strncasecmp(p,"cblock",6))
  909. {
  910. cblock=1;
  911. }
  912. gtk_text_insert(GTK_TEXT(sbaw->source_text[id]),
  913. sbaw->instruction_text_style.font,
  914. &sbaw->instruction_text_style.fg[GTK_STATE_NORMAL],
  915. &sbaw->instruction_text_style.base[GTK_STATE_NORMAL],
  916. p,
  917. q-p);
  918. }
  919. else
  920. { // symbol
  921. if(lineascent<sbaw->symbol_text_style.font->ascent)
  922. lineascent=sbaw->symbol_text_style.font->ascent;
  923. if(linedescent<sbaw->symbol_text_style.font->descent)
  924. linedescent=sbaw->symbol_text_style.font->descent;
  925. gtk_text_insert(GTK_TEXT(sbaw->source_text[id]),
  926. sbaw->symbol_text_style.font,
  927. &sbaw->symbol_text_style.fg[GTK_STATE_NORMAL],
  928. &sbaw->symbol_text_style.base[GTK_STATE_NORMAL],
  929. p,
  930. q-p);
  931. }
  932. p=q;
  933. }
  934. else if( isxdigit(*p))
  935. { // number
  936. q=p;
  937. if(*p=='0' && toupper(*(p+1))=='X')
  938. q+=2;
  939. while(isxdigit(*q))
  940. q++;
  941. if(lineascent<sbaw->number_text_style.font->ascent)
  942. lineascent=sbaw->number_text_style.font->ascent;
  943. if(linedescent<sbaw->number_text_style.font->descent)
  944. linedescent=sbaw->number_text_style.font->descent;
  945. gtk_text_insert(GTK_TEXT(sbaw->source_text[id]),
  946. sbaw->number_text_style.font,
  947. &sbaw->number_text_style.fg[GTK_STATE_NORMAL],
  948. &sbaw->number_text_style.base[GTK_STATE_NORMAL],
  949. p,
  950. q-p);
  951. p=q;
  952. }
  953. else
  954. { // default
  955. // FIXME, add a 'whitespace_text_style'
  956. // There is a small annoyance here. If the source
  957. // initially on a line have whitespace, followed by
  958. // a comment. Now if the comment have a smaller font
  959. // than the default font then the line will have line
  960. // spacing larger than nessesary.
  961. if(lineascent<sbaw->default_text_style.font->ascent)
  962. lineascent=sbaw->default_text_style.font->ascent;
  963. if(linedescent<sbaw->default_text_style.font->descent)
  964. linedescent=sbaw->default_text_style.font->descent;
  965. gtk_text_insert(GTK_TEXT(sbaw->source_text[id]),
  966. sbaw->default_text_style.font,
  967. &sbaw->default_text_style.fg[GTK_STATE_NORMAL],
  968. &sbaw->default_text_style.base[GTK_STATE_NORMAL],
  969. p,
  970. 1);
  971. p++;
  972. }
  973. } //end of while( p < end )
  974. if(lineascent==-1)
  975. lineascent=sbaw->default_text_style.font->ascent;
  976. if(linedescent==-1)
  977. linedescent=sbaw->default_text_style.font->descent;
  978. totallinesheight+=linedescent+lineascent;
  979. // crate an entry in sa_xlate_list for this source line.
  980. // 'this source line' is the one in 'buf' with line number
  981. // 'line' and index 'index' into text
  982. entry=(struct sa_entry*) malloc(sizeof(struct sa_entry));
  983. entry->index=index;
  984. entry->line=line;
  985. entry->pixel=totallinesheight;
  986. entry->font_center=lineascent-linedescent;
  987. sa_xlate_list[id]=g_list_append(sa_xlate_list[id],entry);
  988. line++;
  989. } // end while(fgets(...)...)
  990. // this made the end case of the search dialog simpler once
  991. gtk_text_insert(GTK_TEXT(sbaw->source_text[id]),
  992. sbaw->default_text_style.font,
  993. &sbaw->default_text_style.fg[GTK_STATE_NORMAL],
  994. &sbaw->default_text_style.base[GTK_STATE_NORMAL],
  995. " ",
  996. 1);
  997. gtk_layout_set_size(GTK_LAYOUT(sbaw->source_layout[id]),2*PIXMAP_SIZE,totallinesheight);
  998. gtk_text_thaw(GTK_TEXT(sbaw->source_text[id]));
  999. }
  1000. void SourceBrowserAsm_close_source(SourceBrowserAsm_Window *sbaw, GUI_Processor *gp)
  1001. {
  1002. int i;
  1003. struct breakpoint_info breakpoint_false={-1,NULL};
  1004. sbaw->load_source=0;
  1005. sbaw->source_loaded = 0;
  1006. if(! ((GUI_Object*)sbaw)->enabled)
  1007. return;
  1008. for(i=0;i<SBAW_NRFILES;i++)
  1009. {
  1010. if(sbaw->notebook_child[i]!=NULL)
  1011. {
  1012. int num=gtk_notebook_page_num(GTK_NOTEBOOK(sbaw->notebook),sbaw->notebook_child[i]);
  1013. gtk_notebook_remove_page(GTK_NOTEBOOK(sbaw->notebook),num);
  1014. sbaw->notebook_child[i]=NULL;
  1015. }
  1016. // sbaw->notebook_child[i]=
  1017. // sbaw->notebook_child[i]=
  1018. // sbaw->source_layout[i]=
  1019. // sbaw->source_text[i]=
  1020. sbaw->source_pcwidget[i]=NULL;
  1021. // sbaw->source_layout_adj[i]=
  1022. sbaw->pageindex_to_fileid[i]=-1;
  1023. }
  1024. sbaw->pixmap_pc=NULL;
  1025. // gtk_widget_remove(sbaw->notebook);
  1026. // sbaw->notebook
  1027. for(i=0;i<MAX_BREAKPOINTS;i++)
  1028. sbaw->breakpoint[i] = breakpoint_false;
  1029. sbaw->layout_offset=-1;
  1030. }
  1031. void SourceBrowserAsm_new_source(SourceBrowserAsm_Window *sbaw, GUI_Processor *gp)
  1032. {
  1033. int i;
  1034. int id;
  1035. int pic_id;
  1036. char *file_name;
  1037. struct file_context *gpsim_file;
  1038. int file_id;
  1039. struct cross_reference_to_gui *cross_reference;
  1040. int address;
  1041. assert(sbaw);
  1042. if(sbaw == NULL || gp == NULL)
  1043. return;
  1044. if(! ((GUI_Object*)sbaw)->enabled)
  1045. {
  1046. sbaw->load_source=1;
  1047. return;
  1048. }
  1049. assert(sbaw->sbw.gui_obj.wt==WT_asm_source_window);
  1050. pic_id = ((GUI_Object*)sbaw)->gp->pic_id;
  1051. SourceBrowserAsm_close_source(sbaw,gp);
  1052. sbaw->load_source=1;
  1053. /* Now create a cross-reference link that the
  1054. * simulator can use to send information back to the gui
  1055. */
  1056. cross_reference = (struct cross_reference_to_gui *) malloc(sizeof(struct cross_reference_to_gui));
  1057. cross_reference->parent_window_type = WT_asm_source_window;
  1058. cross_reference->parent_window = (gpointer) sbaw;
  1059. cross_reference->data = (gpointer) NULL;
  1060. cross_reference->update = pc_changed;
  1061. cross_reference->remove = NULL;
  1062. gpsim_assign_pc_xref(pic_id, cross_reference);
  1063. for(i=0;i<gpsim_get_number_of_source_files(pic_id);i++)
  1064. {
  1065. gpsim_file = gpsim_get_file_context(pic_id, i);
  1066. file_name = gpsim_file->name;
  1067. if(!strcmp(file_name+strlen(file_name)-3,"asm")
  1068. ||!strcmp(file_name+strlen(file_name)-3,"inc")
  1069. )
  1070. {
  1071. // FIXME, gpsim may change sometime making this fail
  1072. file_id = i;
  1073. // Make sure that the file is open
  1074. if(gpsim_file->file_ptr == NULL)
  1075. {
  1076. if(file_name != NULL)
  1077. gpsim_file->file_ptr = fopen(file_name,"r");
  1078. if(gpsim_file->file_ptr == NULL)
  1079. {
  1080. printf("file \"%s\" not found\n",file_name);
  1081. continue;
  1082. }
  1083. }
  1084. id = add_page(sbaw,file_id);
  1085. set_text(sbaw,id,file_id);
  1086. }
  1087. }
  1088. sbaw->source_loaded = 1;
  1089. // Why is this needed? set_page() in SourceBrowserAsm_set_pc()
  1090. // fails with widget_map() -> not visible
  1091. while(gtk_events_pending())
  1092. gtk_main_iteration();
  1093. address = gpsim_get_pc_value(pic_id);
  1094. if(address==INVALID_VALUE)
  1095. puts("Warning, PC is invalid?");
  1096. else
  1097. SourceBrowserAsm_set_pc(sbaw, address);
  1098. }
  1099. void SourceBrowserAsm_new_processor(SourceBrowserAsm_Window *sbaw, GUI_Processor *gp)
  1100. {
  1101. assert(sbaw&&gp);
  1102. if(sbaw == NULL || gp == NULL)
  1103. return;
  1104. SourceBrowserAsm_close_source(sbaw, gp);
  1105. }
  1106. static gint configure_event(GtkWidget *widget, GdkEventConfigure *e, gpointer data)
  1107. {
  1108. if(widget->window==NULL)
  1109. return 0;
  1110. gdk_window_get_root_origin(widget->window,&dlg_x,&dlg_y);
  1111. return 0; // what should be returned?, FIXME
  1112. }
  1113. static gboolean
  1114. message_close_cb(GtkWidget *widget, gpointer d)
  1115. {
  1116. gtk_widget_hide(GTK_WIDGET(d));
  1117. return FALSE;
  1118. }
  1119. static int gui_message(char *message)
  1120. {
  1121. static GtkWidget *dialog=NULL;
  1122. static GtkWidget *label;
  1123. GtkWidget *button;
  1124. GtkWidget *hbox;
  1125. assert(message);
  1126. if(dialog==NULL)
  1127. {
  1128. dialog = gtk_dialog_new();
  1129. gtk_signal_connect(GTK_OBJECT(dialog),
  1130. "configure_event",GTK_SIGNAL_FUNC(configure_event),0);
  1131. gtk_signal_connect_object(GTK_OBJECT(dialog),
  1132. "delete_event",GTK_SIGNAL_FUNC(gtk_widget_hide),(gpointer)dialog);
  1133. hbox = gtk_hbox_new(0,0);
  1134. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox,FALSE,FALSE,20);
  1135. button = gtk_button_new_with_label("OK");
  1136. gtk_widget_show(button);
  1137. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button,
  1138. FALSE,FALSE,10);
  1139. gtk_signal_connect(GTK_OBJECT(button),"clicked",
  1140. GTK_SIGNAL_FUNC(message_close_cb),(gpointer)dialog);
  1141. GTK_WIDGET_SET_FLAGS(button,GTK_CAN_DEFAULT);
  1142. gtk_widget_grab_default(button);
  1143. label=gtk_label_new(message);
  1144. gtk_box_pack_start(GTK_BOX(hbox), label,
  1145. FALSE,FALSE, 20);
  1146. gtk_widget_show(hbox);
  1147. gtk_widget_show(label);
  1148. }
  1149. else
  1150. {
  1151. gtk_label_set_text(GTK_LABEL(label),message);
  1152. }
  1153. gtk_widget_set_uposition(GTK_WIDGET(dialog),dlg_x,dlg_y);
  1154. gtk_widget_show_now(dialog);
  1155. return 0;
  1156. }
  1157. static void a_cb(GtkWidget *w, gpointer user_data)
  1158. {
  1159. *(int*)user_data=TRUE;
  1160. gtk_main_quit();
  1161. }
  1162. static void b_cb(GtkWidget *w, gpointer user_data)
  1163. {
  1164. *(int*)user_data=FALSE;
  1165. gtk_main_quit();
  1166. }
  1167. // modal dialog, asking a yes/no question
  1168. static int gui_question(char *question, char *a, char *b)
  1169. {
  1170. static GtkWidget *dialog=NULL;
  1171. static GtkWidget *label;
  1172. GtkWidget *button;
  1173. GtkWidget *hbox;
  1174. static int retval;
  1175. if(dialog==NULL)
  1176. {
  1177. dialog = gtk_dialog_new();
  1178. gtk_signal_connect(GTK_OBJECT(dialog),
  1179. "configure_event",GTK_SIGNAL_FUNC(configure_event),0);
  1180. gtk_signal_connect_object(GTK_OBJECT(dialog),
  1181. "delete_event",GTK_SIGNAL_FUNC(gtk_widget_hide),(gpointer)dialog);
  1182. hbox = gtk_hbox_new(0,0);
  1183. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox,FALSE,FALSE,20);
  1184. button = gtk_button_new_with_label(a);
  1185. gtk_widget_show(button);
  1186. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button,
  1187. FALSE,FALSE,10);
  1188. gtk_signal_connect(GTK_OBJECT(button),"clicked",
  1189. GTK_SIGNAL_FUNC(a_cb),(gpointer)&retval);
  1190. GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
  1191. gtk_widget_grab_default(button);
  1192. button = gtk_button_new_with_label(b);
  1193. gtk_widget_show(button);
  1194. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area), button,
  1195. FALSE,FALSE,10);
  1196. gtk_signal_connect(GTK_OBJECT(button),"clicked",
  1197. GTK_SIGNAL_FUNC(b_cb),(gpointer)&retval);
  1198. label=gtk_label_new(question);
  1199. gtk_box_pack_start(GTK_BOX(hbox), label,
  1200. FALSE,FALSE, 20);
  1201. gtk_widget_show(hbox);
  1202. gtk_widget_show(label);
  1203. }
  1204. else
  1205. {
  1206. gtk_label_set_text(GTK_LABEL(label),question);
  1207. }
  1208. gtk_widget_set_uposition(GTK_WIDGET(dialog),dlg_x,dlg_y);
  1209. gtk_widget_show_now(dialog);
  1210. gtk_grab_add(dialog);
  1211. gtk_main();
  1212. gtk_grab_remove(dialog);
  1213. gtk_widget_hide(dialog);
  1214. // puts(retval==1?"Yes":"No");
  1215. return retval;
  1216. }
  1217. /*
  1218. A rather long function, simplify main loop. FIXME.
  1219. */
  1220. static void find_cb(GtkWidget *w, SourceBrowserAsm_Window *sbaw)
  1221. {
  1222. char *p;
  1223. GList *l;
  1224. int casesensitive;
  1225. int direction;
  1226. int last_matched=0;
  1227. int k=0;
  1228. int char1, char2;
  1229. int j; // index into search string
  1230. int tlen;
  1231. int id;
  1232. if(!sbaw->source_loaded) return;
  1233. id = gtk_notebook_get_current_page(GTK_NOTEBOOK(sbaw->notebook));
  1234. if(id != search.lastid)
  1235. { // Changed notebook tab since last search. reset search.
  1236. search.lastid=id;
  1237. search.found=0;
  1238. search.looped=0;
  1239. search.start=0;
  1240. search.lastfound=0;
  1241. search.i=0;
  1242. }
  1243. if(GTK_TOGGLE_BUTTON(search.case_button)->active)
  1244. casesensitive=TRUE;
  1245. else
  1246. casesensitive=FALSE;
  1247. if(GTK_TOGGLE_BUTTON(search.backwards_button)->active)
  1248. direction=-1;
  1249. else
  1250. direction=1;
  1251. p=gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(search.entry)->entry));
  1252. if(*p=='\0')
  1253. return;
  1254. if(search.string==NULL || strcmp(search.string,p))
  1255. { // not same string as last time
  1256. // search list to prevent duplicates
  1257. l=search.combo_strings;
  1258. while(l)
  1259. {
  1260. if(!strcmp((char*)l->data,p))
  1261. {
  1262. // the string p already is in list
  1263. // move it first?, FIXME
  1264. search.string = (char*)l->data;
  1265. break;
  1266. }
  1267. l=l->next;
  1268. }
  1269. if(l == NULL)
  1270. { // we didn't find string in history, create a new one
  1271. search.string=(char*)malloc(strlen(p)+1);
  1272. strcpy(search.string,p);
  1273. search.combo_strings = g_list_prepend(search.combo_strings,search.string);
  1274. gtk_combo_set_popdown_strings(GTK_COMBO(search.entry),search.combo_strings);
  1275. }
  1276. // initialize variables for a new search
  1277. search.found=0;
  1278. search.looped=0;
  1279. search.i = gui_pixel_to_entry(id,(int)GTK_TEXT(sbaw->source_text[id])->vadj->value)->index;
  1280. search.start = search.i; // remember where we started searching
  1281. }
  1282. tlen =gtk_text_get_length(GTK_TEXT(sbaw->source_text[id]));
  1283. j=0;
  1284. for(;search.i>=0 && search.i<tlen;search.i+=direction)
  1285. {
  1286. if(search.string[j]=='\0')
  1287. { // match! We found the string in text.
  1288. int start_i, end_i;
  1289. search.found++;
  1290. start_i = k+ (direction==-1); // comparing backwards means
  1291. end_i = search.i+ (direction==-1); // we have to add 1
  1292. if(start_i>end_i)
  1293. {
  1294. int temp=end_i; // swap, so that k is the smaller
  1295. end_i=start_i;
  1296. start_i=temp;
  1297. }
  1298. assert(start_i<end_i);
  1299. if(start_i==search.lastfound)
  1300. { // we found the same position as last time
  1301. // happens when searching backwards
  1302. j=0;
  1303. if(direction==1)
  1304. search.i++; // skip this match
  1305. else
  1306. search.i--; // skip this match
  1307. last_matched=0;
  1308. }
  1309. else
  1310. {
  1311. int pixel;
  1312. float inc;
  1313. search.lastfound=start_i;
  1314. pixel = gui_index_to_entry(id,start_i)->pixel;
  1315. inc = GTK_ADJUSTMENT(GTK_TEXT(sbaw->source_text[id])->vadj)->page_increment;
  1316. gtk_adjustment_set_value(GTK_ADJUSTMENT( GTK_TEXT( sbaw->source_text[id])->vadj),
  1317. pixel-inc/2);
  1318. gtk_editable_select_region(GTK_EDITABLE(sbaw->source_text[id]),start_i,end_i);
  1319. return;
  1320. }
  1321. }
  1322. if(search.looped && (search.start == search.i))
  1323. {
  1324. if(search.found==0)
  1325. {
  1326. gui_message("Not found");
  1327. return;
  1328. }
  1329. else if(search.found==1)
  1330. {
  1331. gui_message("Just a single occurance in text");
  1332. // so that the next next call marks text too, we do:
  1333. search.found=0;
  1334. search.looped=0;
  1335. search.lastfound=-1;
  1336. return;
  1337. }
  1338. }
  1339. // get another character
  1340. char1=GTK_TEXT_INDEX(GTK_TEXT(sbaw->source_text[id]),(unsigned)search.i);
  1341. if(direction==1)
  1342. char2=search.string[j];
  1343. else
  1344. char2=search.string[strlen(search.string)-1-j];
  1345. //FIXME, many calls to strlen
  1346. if(casesensitive==FALSE)
  1347. {
  1348. char1=toupper(char1); // FIXME, what about native letters?
  1349. char2=toupper(char2);
  1350. }
  1351. if(char1!=char2)
  1352. { // if these characters don't match
  1353. j=0; // set search index for string back to zero
  1354. last_matched=0; // char in this loop didn't match
  1355. }
  1356. else
  1357. {
  1358. if(!last_matched)
  1359. {
  1360. k=search.i; // remember first matching index for later
  1361. last_matched=1; // char in this loop matched
  1362. }
  1363. j++; // forward string index to compare next char
  1364. }
  1365. }
  1366. // the string was not found in text between index 'search_start' and
  1367. // one end of text (index '0' or index 'tlen')
  1368. // We ask user it he want to search from other end of file
  1369. if(direction==1)
  1370. {
  1371. if(gui_question("I reached end of file\ncontinue from start?","Yes","No")==TRUE)
  1372. {
  1373. search.i=0;
  1374. search.looped=1;
  1375. find_cb(w,sbaw); // tail recursive, FIXME
  1376. return;
  1377. }
  1378. else
  1379. search.i=tlen-1;
  1380. }
  1381. else
  1382. {
  1383. if(gui_question("I reached top of file\ncontinue from end?","Yes", "No")==TRUE)
  1384. {
  1385. search.i=tlen-1;
  1386. search.looped=1;
  1387. find_cb(w,sbaw); // tail recursive, FIXME
  1388. return;
  1389. }
  1390. else
  1391. search.i=0;
  1392. }
  1393. }
  1394. static void find_clear_cb(GtkWidget *w, SourceBrowserAsm_Window *sbaw)
  1395. {
  1396. gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(search.entry)->entry),"");
  1397. }
  1398. void BuildSourceBrowserAsmWindow(SourceBrowserAsm_Window *sbaw)
  1399. {
  1400. GtkWidget *hbox;
  1401. GtkWidget *button;
  1402. GtkWidget *label;
  1403. GdkColor text_fg;
  1404. GdkColor text_bg;
  1405. int x,y,width,height;
  1406. CreateSBW((SourceBrowser_Window*)sbaw);
  1407. gtk_window_set_title (GTK_WINDOW (sbaw->sbw.gui_obj.window), "Source Browser");
  1408. width=((GUI_Object*)sbaw)->width;
  1409. height=((GUI_Object*)sbaw)->height;
  1410. x=((GUI_Object*)sbaw)->x;
  1411. y=((GUI_Object*)sbaw)->y;
  1412. gtk_window_set_default_size(GTK_WINDOW(sbaw->sbw.gui_obj.window), width,height);
  1413. gtk_widget_set_uposition(GTK_WIDGET(sbaw->sbw.gui_obj.window),x,y);
  1414. sbaw->notebook = gtk_notebook_new();
  1415. gtk_widget_show(sbaw->notebook);
  1416. sbaw->popup_menu=build_menu(sbaw->notebook,sbaw);
  1417. gtk_box_pack_start (GTK_BOX (sbaw->sbw.vbox), sbaw->notebook, TRUE, TRUE, 0);
  1418. gdk_color_parse("black", &text_fg);
  1419. gdk_color_parse("white", &text_bg);
  1420. sbaw->default_text_style.base[GTK_STATE_NORMAL] = text_bg;
  1421. sbaw->default_text_style.fg[GTK_STATE_NORMAL] = text_fg;
  1422. gdk_color_parse("dark green", &text_fg);
  1423. gdk_color_parse("white", &text_bg);
  1424. sbaw->symbol_text_style.base[GTK_STATE_NORMAL] = text_bg;
  1425. sbaw->symbol_text_style.fg[GTK_STATE_NORMAL] = text_fg;
  1426. gdk_color_parse("orange", &text_fg);
  1427. gdk_color_parse("white", &text_bg);
  1428. sbaw->label_text_style.base[GTK_STATE_NORMAL] = text_bg;
  1429. sbaw->label_text_style.fg[GTK_STATE_NORMAL] = text_fg;
  1430. gdk_color_parse("red", &text_fg);
  1431. gdk_color_parse("white", &text_bg);
  1432. sbaw->instruction_text_style.base[GTK_STATE_NORMAL] = text_bg;
  1433. sbaw->instruction_text_style.fg[GTK_STATE_NORMAL] = text_fg;
  1434. gdk_color_parse("blue", &text_fg);
  1435. gdk_color_parse("white", &text_bg);
  1436. sbaw->number_text_style.base[GTK_STATE_NORMAL] = text_bg;
  1437. sbaw->number_text_style.fg[GTK_STATE_NORMAL] = text_fg;
  1438. gdk_color_parse("black", &text_fg);
  1439. gdk_color_parse("gray", &text_bg);
  1440. sbaw->comment_text_style.base[GTK_STATE_NORMAL] = text_bg;
  1441. sbaw->comment_text_style.fg[GTK_STATE_NORMAL] = text_fg;
  1442. sbaw->comment_text_style.font=
  1443. gdk_font_load("-adobe-courier-bold-o-*-*-*-120-*-*-*-*-*-*");
  1444. sbaw->default_text_style.font=
  1445. sbaw->label_text_style.font=
  1446. sbaw->symbol_text_style.font=
  1447. sbaw->instruction_text_style.font=
  1448. sbaw->number_text_style.font=
  1449. gdk_font_load("-adobe-courier-bold-r-*-*-*-120-*-*-*-*-*-*");
  1450. search.lastid=-1; // will reset search
  1451. search.window = gtk_dialog_new();
  1452. gtk_signal_connect(GTK_OBJECT(search.window),
  1453. "configure_event",GTK_SIGNAL_FUNC(configure_event),0);
  1454. gtk_signal_connect_object(GTK_OBJECT(search.window),
  1455. "delete_event",GTK_SIGNAL_FUNC(gtk_widget_hide),(gpointer)search.window);
  1456. gtk_window_set_title(GTK_WINDOW(search.window),"Find");
  1457. hbox = gtk_hbox_new(FALSE,15);
  1458. gtk_widget_show(hbox);
  1459. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(search.window)->vbox),hbox,
  1460. FALSE,TRUE,5);
  1461. label = gtk_label_new("Find:");
  1462. gtk_widget_show(label);
  1463. gtk_box_pack_start(GTK_BOX(hbox),label,
  1464. FALSE,FALSE,5);
  1465. search.entry = gtk_combo_new();
  1466. gtk_widget_show(search.entry);
  1467. gtk_box_pack_start(GTK_BOX(hbox),search.entry,
  1468. TRUE,TRUE,5);
  1469. gtk_combo_disable_activate(GTK_COMBO(search.entry));
  1470. gtk_signal_connect(GTK_OBJECT(GTK_COMBO(search.entry)->entry),"activate",
  1471. GTK_SIGNAL_FUNC(find_cb),sbaw);
  1472. hbox = gtk_hbox_new(FALSE,15);
  1473. gtk_box_pack_start(GTK_BOX(GTK_DIALOG(search.window)->vbox),hbox,
  1474. FALSE,TRUE,5);
  1475. gtk_

Large files files are truncated, but you can click here to view the full file