Subversion Repositories wimsdev

Rev

Rev 8193 | Rev 8224 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. void add_drag_code(FILE *js_include_file,int canvas_cnt,int canvas_root_id);
  2. void add_trace_js_mouse(FILE *js_include_file,int canvas_cnt,int canvas_root_id,char *stroke_color,char *jsmath,int font_size,double stroke_opacity,int line_width,int crosshair_size);
  3. void add_setlimits(FILE *js_include_file, int canvas_root_id);
  4. void add_safe_eval(FILE *js_include_file);
  5. void add_to_js_math(FILE *js_include_file);
  6. void add_calc_y(FILE *js_include_file,int canvas_root_id,char *jsmath);
  7. void add_jsplot(FILE *js_include_file,int canvas_root_id);
  8. void add_slider(FILE *js_include_file, int canvas_root_id,double v1,double v2,int width,int height,int type,char *label,int slider_cnt,char *stroke_color,char *fill_color,int line_width,double opacity,char *font_family,char *font_color,int use_slider_display);
  9. void add_slider_display(FILE *js_include_file, int canvas_root_id,int precision,int font_size,char *font_color,double stroke_opacity);
  10. void add_xyslider(FILE *js_include_file, int canvas_root_id,double v1,double v2,int width,int height,int type,char *label,int slider_cnt,char *stroke_color,char *fill_color,int line_width,double opacity,char *font_family,char *font_color,int use_slider_display);
  11. void *my_newmem(size_t size);
  12. void canvas_error(char *msg);
  13. char *eval(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int xsteps,int precision);
  14. char *eval_parametric(int xsize,int ysize,char *fun1,char* fun2,double xmin,double xmax,double ymin,double ymax, double tmin,double tmax,int plotsteps,int precision);
  15. char *eval_levelcurve(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int plotsteps,int precision,double level);
  16. char *data2js_array(int data[],int len);
  17. char *xy2js_array(int xy[],int len);
  18. char *double_xy2js_array(double xy[],int len,int decimals);
  19. int find_number_of_digits(int i);
  20. int x2px(double x);
  21. int y2px(double y);
  22. void add_clear_button(FILE *js_include_file,int canvas_root_id,char *input_style,char *button_text);
  23. void add_js_inputs(FILE *js_include_file,int canvas_root_id,int num,int input_cnt,char *input_style,int line_width);
  24. void add_js_mouse(FILE *js_include_file,int canvas_cnt,int canvas_root_id,int precision,char *stroke_color,int font_size,double stroke_opacity,int type);
  25. void add_js_points(FILE *js_include_file,int num,char *draw_type,int line_width, int radius ,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1);
  26. void add_js_circles(FILE *js_include_file,int num,char *draw_type, int line_width, int radius , char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1);
  27. void add_js_segments(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1);
  28. void add_js_polyline(FILE *js_include_file,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1);
  29. void add_js_lines(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1);
  30. void add_js_hlines(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1);
  31. void add_js_arrows(FILE *js_include_file,int num,char *draw_type,int line_width,int type, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1,int arrow_head);
  32. void add_js_crosshairs(FILE *js_include_file,int num,char *draw_type,int line_width, int crosshair_size ,char *stroke_color,double stroke_opacity);
  33. void add_js_paths(FILE *js_include_file,int num,char *draw_type,int line_width, int closed_path,char *stroke_color,double stroke_opacity,int use_filled, char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1);
  34. void add_js_poly(FILE *js_include_file,int num,char *draw_type,int line_width,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1);
  35. void add_js_rect(FILE *js_include_file,int num,int roundrect,char *draw_type,int line_width,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1);
  36. void add_js_floodfill(FILE *js_include_file,int canvas_root_id);
  37. void add_js_filltoborder(FILE *js_include_file,int canvas_root_id);
  38. void add_js_arc(FILE *js_include_file,int canvas_root_id,int num,int line_width,char *stroke_color,double stroke_opacity,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1);
  39. void add_js_text(FILE *js_include_file,int canvas_root_id,int font_size,char *font_family,char *font_color,double stroke_opacity);
  40. void add_input_circle(FILE *js_include_file,int type,int num);
  41. void add_input_segment(FILE *js_include_file,int num);
  42. void add_input_line(FILE *js_include_file,int num);
  43. void add_input_polyline(FILE *js_include_file);
  44. void add_textarea_polygon(FILE *js_include_file);
  45. void add_input_crosshair(FILE *js_include_file,int num);
  46. void add_input_arrow(FILE *js_include_file,int num);
  47. void add_input_xy(FILE *js_include_file, int canvas_root_id);
  48. void add_input_xyr(FILE *js_include_file, int canvas_root_id);
  49. void add_input_x1y1x2y2(FILE *js_include_file, int canvas_root_id);
  50. void add_textarea_xy(FILE *js_include_file, int canvas_root_id);
  51. void add_zoom_buttons(FILE *js_include_file,int canvas_root_id,char *stroke_color,double stroke_opacity);
  52. void add_js_tooltip(int canvas_root_id,char *tooltip_text,char *bgcolor,int xsize,int ysize);
  53. void add_input_jsfunction(FILE *js_include_file, int canvas_root_id,int num,char *input_style,int input_cnt,char *stroke_color,float stroke_opacity,int line_width,int use_dashed,int dashtype0,int dashtype1);
  54.  
  55.  
  56.  
  57. void add_js_inputs(FILE *js_include_file,int canvas_root_id,int num,int input_cnt,char *input_style,int line_width){
  58. fprintf(js_include_file,"\n<!-- user draw inputfields -->\n\
  59. var canvas_rect;\
  60. var input_cnt = %d;\
  61. var start_input_cnt = input_cnt;\
  62. function user_drag(evt){return;}\
  63. function user_draw(evt){\
  64. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  65. var x = evt.clientX - canvas_rect.left;\
  66. var y = evt.clientY - canvas_rect.top;\
  67. if( x_use_snap_to_grid == 1 ){\
  68.  x = snap_to_x(x);\
  69. };\
  70. if( y_use_snap_to_grid == 1 ){\
  71.  y = snap_to_y(y);\
  72. };\
  73. var num = %d;var inputs;\
  74. if(evt.which == 1){\
  75.  var inputs;var xi;var yi;var wi;var hi;\
  76.  var found = 0;\
  77.  if( start_input_cnt < input_cnt){\
  78.   for(var p = start_input_cnt ; p < input_cnt ; p++ ){\
  79.    inputs = document.getElementById(\"canvas_input\"+p);\
  80.    xi = findPosX(inputs) - canvas_rect.left;\
  81.    yi = findPosY(inputs) - canvas_rect.top;\
  82.    wi = 4 + inputs.clientWidth;\
  83.    hi = 4 + inputs.clientHeight;\
  84.    if( x > xi - wi && x < xi + wi && y > yi - hi && y < yi + hi ){\
  85.     found = 1;\
  86.    };\
  87.   };\
  88.  };\
  89.  if( found == 0 ){\
  90.   if( num == 1 ){\
  91.    inputs = document.getElementById(\"canvas_input\"+start_input_cnt);\
  92.    try{canvas_div.removeChild(inputs);}catch(e){};\
  93.    input_cnt = 0;\
  94.   };\
  95.   userdraw_x.push(x);userdraw_y.push(y);\
  96.   draw_inputs(%d,input_cnt,x,y,%d,1,\"%s\",\"?\");\
  97.   input_cnt++;\
  98.  };\
  99. }\
  100. else\
  101. {\
  102.  for(var p = start_input_cnt ; p < input_cnt; p++){\
  103.   inputs = document.getElementById(\"canvas_input\"+p);\
  104.   try{canvas_div.removeChild(inputs);}catch(e){};\
  105.  };\
  106.  userdraw_x = [];userdraw_y = [];\
  107.  input_cnt = start_input_cnt;\
  108. };\
  109. };",input_cnt,num,canvas_root_id,line_width,input_style);
  110. }
  111.  
  112. void add_zoom_buttons(FILE *js_include_file,int canvas_root_id,char *stroke_color,double stroke_opacity){
  113. fprintf(js_include_file,"\n<!-- draw zoom buttons -->\n\
  114. var draw_zoom_buttons = function(){\
  115. var obj;var canvas_type =%d;\
  116. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){\
  117.  obj = document.getElementById(\"wims_canvas%d\"+canvas_type);\
  118. }\
  119. else\
  120. {\
  121.  obj = create_canvas%d(canvas_type,xsize,ysize);\
  122. };\
  123. var ctx = obj.getContext(\"2d\");\
  124. ctx.font =\"18px Ariel\";\
  125. ctx.textAlign = \"right\";\
  126. ctx.fillStyle=\"rgba(\"+%s+\",\"+%f+\")\";\
  127. ctx.fillText(\"+\",xsize,ysize);\
  128. ctx.fillText(\"\\u2212\",xsize - 15,ysize);\
  129. ctx.fillText(\"\\u2192\",xsize - 30,ysize-2);\
  130. ctx.fillText(\"\\u2190\",xsize - 45,ysize-2);\
  131. ctx.fillText(\"\\u2191\",xsize - 60,ysize-2);\
  132. ctx.fillText(\"\\u2193\",xsize - 75,ysize-2);\
  133. ctx.fillText(\"\\u00D7\",xsize - 90,ysize-2);\
  134. ctx.stroke();\
  135. };\ndraw_zoom_buttons();",BG_CANVAS,canvas_root_id,canvas_root_id,canvas_root_id,stroke_color,stroke_opacity);    
  136. }
  137.  
  138. void add_js_circles(FILE *js_include_file,int num,char *draw_type,int line_width, int radius ,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  139. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  140. var num = %d;\
  141. userdraw_radius[0] = %d;\
  142. var line_width = %d;\
  143. var stroke_color = \"%s\";\
  144. var stroke_opacity = %f;\
  145. var use_filled = %d;\
  146. var fill_color = \"%s\";\
  147. var fill_opacity = %f;\
  148. var use_dashed = %d;\
  149. var dashtype1 = %d;\
  150. var dashtype0 = %d;\
  151. var click_cnt = 0;\
  152. var x0,y0,x1,y1;\
  153. var canvas_rect;\
  154. function user_draw(evt){\
  155. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  156. y0 = evt.clientY - canvas_rect.top;\
  157. if(y0 < ysize + 1){\
  158.  x0 = evt.clientX - canvas_rect.left;\
  159.  if( x_use_snap_to_grid == 1 ){\
  160.   x0 = snap_to_x(x0);\
  161.  };\
  162.  if( y_use_snap_to_grid == 1 ){\
  163.   y0 = snap_to_y(y0);\
  164.  };\
  165.  if(evt.which == 1){\
  166.   if( click_cnt == 0 ){\
  167.    userdraw_x[xy_cnt] = x0;\
  168.    userdraw_y[xy_cnt] = y0;\
  169.    userdraw_radius[xy_cnt] = line_width;\
  170.    click_cnt = 1;\
  171.    draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  172.   }\
  173.   else\
  174.   {\
  175.    click_cnt = 0;\
  176.    if( num != 1 ){ xy_cnt++; }\
  177.   }\
  178.  }\
  179.  else\
  180.  {\
  181.    canvas_remove(x0,y0);\
  182.  }\
  183. }\
  184. };\
  185. function user_drag(evt){\
  186. if( click_cnt == 1 ){\
  187.    canvas_rect = canvas_userdraw.getBoundingClientRect();\
  188.    y1 = evt.clientY - canvas_rect.top;\
  189.    x1 = evt.clientX - canvas_rect.left;\
  190.    if( x_use_snap_to_grid == 1 ){\
  191.     x0 = snap_to_x(x0);\
  192.    };\
  193.    if( y_use_snap_to_grid == 1 ){\
  194.     y0 = snap_to_y(y0);\
  195.    };\
  196.    userdraw_radius[xy_cnt] = parseInt(Math.sqrt( (x1-x0)*(x1-x0) + (y1-y0)*(y1-y0) ));\
  197.    userdraw_x[xy_cnt] = x0;\
  198.    userdraw_y[xy_cnt] = y0;\
  199.    context_userdraw.clearRect(0,0,xsize,ysize);\
  200.    draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  201.  }\
  202. };\
  203. function canvas_remove(x,y){\
  204. var marge = 10*line_width;\
  205. var diff1;var diff2;\
  206. for(var p = 0;p < userdraw_x.length ; p++){\
  207.  diff1 = (x-userdraw_x[p])*(x - userdraw_x[p]) + (y - userdraw_y[p])*(y - userdraw_y[p]) - userdraw_radius[p]*userdraw_radius[p];\
  208.  diff2 = (x-userdraw_x[p])*(x - userdraw_x[p]) + (y - userdraw_y[p])*(y - userdraw_y[p]) - (userdraw_radius[p] - marge)*(userdraw_radius[p] - marge);\
  209.  if( diff1 < 0 && diff2 > 0 ){\
  210.   if(confirm(\"remove circle ?\")){\
  211.    if( num == 1 ){ userdraw_x = [];userdraw_y = []; userdraw_radius = [];xy_cnt = 0;context_userdraw.clearRect(0,0,xsize,ysize); return;}\
  212.    else\
  213.    {\
  214.     userdraw_x.splice(p,1);\
  215.     userdraw_y.splice(p,1);\
  216.     userdraw_radius.splice(p,1);\
  217.     xy_cnt--;\
  218.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  219.     draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  220.    };\
  221.   };\
  222.   return;\
  223.  }\
  224. }\
  225. };",draw_type,num,radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);
  226. }
  227.  
  228. void add_js_crosshairs(FILE *js_include_file,int num,char *draw_type,int line_width, int crosshair_size ,char *stroke_color,double stroke_opacity){
  229. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on currect active canvas -->\n\
  230. var num = %d;\
  231. var crosshair_size = parseInt(0.5*%d);\
  232. var canvas_rect;\
  233. var line_width = %d;\
  234. var stroke_color = \"%s\";\
  235. var stroke_opacity = %f;\
  236. context_userdraw.lineWidth = line_width;\
  237. context_userdraw.strokeStyle=\"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  238. function user_drag(evt){return;}\
  239. function user_draw(evt){\
  240. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  241. var x = evt.clientX - canvas_rect.left;\
  242. var y = evt.clientY - canvas_rect.top;\
  243. if( x_use_snap_to_grid == 1 ){\
  244.  x = snap_to_x(x);\
  245. };\
  246. if( y_use_snap_to_grid == 1 ){\
  247.  y = snap_to_y(y);\
  248. };\
  249. var x1,y1,x2,y2;\
  250. if(evt.which == 1){\
  251.   userdraw_x[xy_cnt] = x;\
  252.   userdraw_y[xy_cnt] = y;\
  253.   x1 = x - crosshair_size;\
  254.   x2 = x + crosshair_size;\
  255.   y1 = y - crosshair_size;\
  256.   y2 = y + crosshair_size;\
  257.   if( num != 1 ){ xy_cnt++;\
  258.    for(var p = 0; p < xy_cnt - 1 ;p++){\
  259.     if(x1 < userdraw_x[p] && x2 > userdraw_x[p]){\
  260.      if(y1 < userdraw_y[p] && y2 > userdraw_y[p]){\
  261.       canvas_remove(x,y);\
  262.       context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");\
  263.      }\
  264.     }\
  265.    }\
  266.   };\
  267.   context_userdraw.beginPath();\
  268.   context_userdraw.moveTo(x1,y1);\
  269.   context_userdraw.lineTo(x2,y2);\
  270.   context_userdraw.closePath();\
  271.   context_userdraw.stroke();\
  272.   context_userdraw.beginPath();\
  273.   context_userdraw.moveTo(x2,y1);\
  274.   context_userdraw.lineTo(x1,y2);\
  275.   context_userdraw.closePath();\
  276.   context_userdraw.stroke();\
  277.   context_userdraw.clearRect(0,0,xsize,ysize);\
  278.   draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  279. }\
  280. else\
  281. {\
  282. canvas_remove(x,y);\
  283. }\
  284. }\
  285. function canvas_remove(x,y){\
  286. var marge = 2*crosshair_size;\
  287. for(var p = 0;p < userdraw_x.length ; p++){\
  288.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  289.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  290.    userdraw_x.splice(p,1);userdraw_y.splice(p,1);\
  291.    context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);xy_cnt--;\
  292.    draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  293.    return;\
  294.   }\
  295.  }\
  296. }\
  297. };",draw_type,num,crosshair_size,line_width,stroke_color,stroke_opacity);
  298. }
  299.  
  300. void add_js_rect(FILE *js_include_file,int num,int roundrect,char *draw_type,int line_width,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  301. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on currect active canvas -->\n\
  302. var canvas_rect;\
  303. var roundrect = %d;\
  304. var line_width = %d;\
  305. var stroke_color = \"%s\";\
  306. var stroke_opacity = %f;\
  307. var use_filled = %d;\
  308. var fill_color = \"%s\";\
  309. var fill_opacity = %f;\
  310. var use_dashed = %d;\
  311. var dashtype0 = %d;\
  312. var dashtype1 = %d;\
  313. var num = %d;\
  314. var use_rotate = 0;\
  315. var angle = 0;\
  316. var closed_path = 1;\
  317. var clickcnt = 0;\
  318. xy_cnt = 0;\
  319. var x0,y0,x1,y1;\
  320. var marge = 10*line_width;\
  321. function user_draw(evt){\
  322. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  323. y0 = evt.clientY - canvas_rect.top;\
  324. if( y0  < ysize + 1 ){\
  325.  x0 = evt.clientX - canvas_rect.left;\
  326.  if( x_use_snap_to_grid == 1 ){\
  327.   x0 = snap_to_x(x0);\
  328.  };\
  329.  if( y_use_snap_to_grid == 1 ){\
  330.   y0 = snap_to_y(y0);\
  331.  };\
  332.  if( evt.which == 1 ){\
  333.   if(clickcnt == 0 ){\
  334.    clickcnt = 1;\
  335.    userdraw_x[xy_cnt] = x0;userdraw_y[xy_cnt] = y0;xy_cnt++;\
  336.   }\
  337.   else\
  338.   {\
  339.    clickcnt = 0;\
  340.    if(roundrect == 0 ){\
  341.     draw_rects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  342.    }\
  343.    else\
  344.    {\
  345.     draw_roundrects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  346.    }\
  347.    if( num != 1 ){ xy_cnt++; }else{xy_cnt--;}\
  348.   }\
  349.  }\
  350.  else\
  351.  {\
  352.   canvas_remove(x0,y0);\
  353.  };\
  354. };\
  355. };\
  356. function user_drag(evt){\
  357. if( clickcnt == 1 ){\
  358.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  359.  y1 = evt.clientY - canvas_rect.top;\
  360.  x1 = evt.clientX - canvas_rect.left;\
  361.  if( x_use_snap_to_grid == 1 ){\
  362.  x1 = snap_to_x(x1);\
  363.  };\
  364.  if( y_use_snap_to_grid == 1 ){\
  365.  y1 = snap_to_y(y1);\
  366.  };\
  367.  userdraw_x[xy_cnt] = x1;\
  368.  userdraw_y[xy_cnt] = y1;\
  369.  context_userdraw.clearRect(0,0,xsize,ysize);\
  370.  if( roundrect == 0 ){\
  371.   draw_rects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  372.  }\
  373.  else\
  374.  {\
  375.   draw_roundrects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  376.  };\
  377. };\
  378. };\
  379. function canvas_remove(x,y){\
  380. for(var p = 0;p < userdraw_x.length ; p++){\
  381.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  382.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  383.    if( confirm(\"remove rectangle ?\" )){\
  384.     if( p%%2 == 0 ){\
  385.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  386.     }\
  387.     else\
  388.     {\
  389.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  390.     }\
  391.     xy_cnt--;\
  392.     context_userdraw.clearRect(0,0,xsize,ysize);\
  393.     if(xy_cnt < 2){xy_cnt = 0;click_cnt = 0;userdraw_x = [];userdraw_y = [];return;};\
  394.     if( roundrect == 0 ){\
  395.      draw_rects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  396.     }\
  397.     else\
  398.     {\
  399.      draw_roundrects(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  400.     }\
  401.     return;\
  402.    };\
  403.   };\
  404.  };\
  405. };\
  406. };",draw_type,roundrect,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,num);
  407. }
  408.  
  409. void add_js_poly(FILE *js_include_file,int num,char *draw_type,int line_width,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  410. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on currect active canvas -->\n\
  411. var canvas_rect;\
  412. var num = %d;\
  413. var line_width = %d;\
  414. var stroke_color = \"%s\";\
  415. var stroke_opacity = %f;\
  416. var use_filled = %d;\
  417. var fill_color = \"%s\";\
  418. var fill_opacity = %f;\
  419. var use_dashed = %d;\
  420. var dashtype0 = %d;\
  421. var dashtype1 = %d;\
  422. var use_rotate = 0;\
  423. var angle = 0;\
  424. var use_translate = 0;\
  425. var vector=[0,0];\
  426. var closed_path = 1;\
  427. var done = 1;\
  428. var x,y;\
  429. var marge = 10*line_width;\
  430. function user_draw(evt){\
  431. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  432. y = evt.clientY - canvas_rect.top;\
  433. if( y < ysize + 1 ){\
  434.  x = evt.clientX - canvas_rect.left;\
  435.  if( x_use_snap_to_grid == 1 ){\
  436.   x = snap_to_x(x);\
  437.  };\
  438.  if( y_use_snap_to_grid == 1 ){\
  439.   y = snap_to_y(y);\
  440.  };\
  441.  if( evt.which == 1){\
  442.   if( num == -1 && xy_cnt > 2 ){\
  443.    if( x - marge < userdraw_x[0] && x + marge > userdraw_x[0]){\
  444.     if( y - marge < userdraw_y[0] && y + marge > userdraw_y[0]){\
  445.      userdraw_x.splice(xy_cnt,1);userdraw_y.splice(xy_cnt,1);\
  446.      draw_paths(context_userdraw,userdraw_x,userdraw_y,line_width,closed_path,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  447.      done = 1;return;\
  448.     };\
  449.    };\
  450.   }\
  451.   else\
  452.   {\
  453.    if( xy_cnt == num - 1){\
  454.     draw_paths(context_userdraw,userdraw_x,userdraw_y,line_width,closed_path,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  455.     done = 1;return;\
  456.    };\
  457.   };\
  458.   done = 0;\
  459.   userdraw_x[xy_cnt] = x;userdraw_y[xy_cnt] = y;xy_cnt++;\
  460.   user_drag(evt);\
  461.  }\
  462.  else\
  463.  {\
  464.   canvas_remove(x,y);\
  465.   return;\
  466.  }\
  467. };\
  468. };\
  469. function user_drag(evt){\
  470. if( done == 0 ){\
  471.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  472.  x = evt.clientX - canvas_rect.left;\
  473.  y = evt.clientY - canvas_rect.top;\
  474.  if( x_use_snap_to_grid == 1 ){\
  475.   x = snap_to_x(x);\
  476.  };\
  477.  if( y_use_snap_to_grid == 1 ){\
  478.   y = snap_to_y(y);\
  479.  };\
  480.  context_userdraw.clearRect(0,0,xsize,ysize);\
  481.  userdraw_x[xy_cnt] = x;userdraw_y[xy_cnt] = y;\
  482.  draw_paths(context_userdraw,userdraw_x,userdraw_y,line_width,closed_path,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,use_rotate,angle,0,[1,0,0,1,0,0]);\
  483. }\
  484. }\
  485. function canvas_remove(x,y){\
  486. for(var p = 0;p < userdraw_x.length ; p++){\
  487.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  488.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  489.    if( confirm(\"remove polygone ?\" )){\
  490.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  491.     xy_cnt = 0;userdraw_x = [];userdraw_y = [];done = 1;\
  492.    }\
  493.    return;\
  494.   }\
  495.  }\
  496. }\
  497. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);
  498. }
  499.  
  500. /*  function draw_circles(ctx,x_points,y_points,radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);*/
  501. void add_js_points(FILE *js_include_file,int num,char *draw_type,int line_width, int radius ,char *stroke_color,double stroke_opacity,int use_filled,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  502. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  503. var num = %d;\
  504. var canvas_rect;\
  505. userdraw_radius[0] = %d;\
  506. var line_width = %d;\
  507. var stroke_color = \"%s\";\
  508. var stroke_opacity = %f;\
  509. var use_filled = %d;\
  510. var fill_color = \"%s\";\
  511. var fill_opacity = %f;\
  512. var use_dashed = %d;\
  513. var dashtype0 = %d;\
  514. var dashtype1 = %d;\
  515. function user_drag(evt){return;};\
  516. function user_draw(evt){\
  517. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  518. var y = evt.clientY - canvas_rect.top;\
  519. if( y < ysize + 1 ){\
  520.  var lu = userdraw_x.length;\
  521.  var x = evt.clientX - canvas_rect.left;\
  522.  if( x_use_snap_to_grid == 1 ){\
  523.   x = snap_to_x(x);\
  524.  };\
  525.  if( y_use_snap_to_grid == 1 ){\
  526.   y = snap_to_y(y);\
  527.  };\
  528.  if(evt.which == 1){\
  529.   if( num == 1 ){\
  530.   userdraw_x[0] = x;\
  531.   userdraw_y[0] = y;\
  532.   }\
  533.   else\
  534.   {\
  535.   userdraw_x[lu] = x;\
  536.   userdraw_y[lu] = y;\
  537.   userdraw_radius[lu] = userdraw_radius[0];\
  538.   };\
  539.   context_userdraw.clearRect(0,0,xsize,ysize);\
  540.   draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  541.  }\
  542.  else\
  543.  {\
  544.  canvas_remove(x,y);\
  545.  }\
  546. }\
  547. };\
  548. function canvas_remove(x,y){\
  549. var marge = 4*line_width;\
  550. for(var p = 0;p < userdraw_x.length ; p++){\
  551.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  552.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  553.    userdraw_x.splice(p,1);userdraw_y.splice(p,1);\
  554.    context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  555.    draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  556.    return;\
  557.   }\
  558.  }\
  559. }\
  560. };",draw_type,num,radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);
  561.  
  562. }
  563. void add_js_polyline(FILE *js_include_file,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1){
  564. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  565. var canvas_rect;\
  566. var cnt = 0;\
  567. var line_width = %d;\
  568. var stroke_color = \"%s\";\
  569. var stroke_opacity = %f;\
  570. var use_dashed = %d;\
  571. var dashtype0 = %d;\
  572. var dashtype1 = %d;\
  573. function user_draw(evt){\
  574. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  575. var x = evt.clientX - canvas_rect.left;\
  576. var y = evt.clientY - canvas_rect.top;\
  577. var lu = userdraw_x.length;\
  578. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  579. if( x_use_snap_to_grid == 1 ){\
  580.  x = snap_to_x(x);\
  581. };\
  582. if( y_use_snap_to_grid == 1 ){\
  583.  y = snap_to_y(y);\
  584. };\
  585. if( evt.which == 1 ){\
  586.  userdraw_x[lu] = x;userdraw_y[lu] = y;\
  587.  if( cnt == 0 ){\
  588.   user_drag(evt);\
  589.   cnt = 1;\
  590.  }\
  591.  else\
  592.  {\
  593.    cnt = 0;\
  594.    draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  595.  }\
  596. }\
  597. else\
  598. {\
  599.  canvas_remove(x,y);\
  600. }\
  601. };\
  602. function user_drag(evt){\
  603. if( cnt == 0){\
  604.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  605.  var x = evt.clientX - canvas_rect.left;\
  606.  var y = evt.clientY - canvas_rect.top;\
  607.  if( x_use_snap_to_grid == 1 ){\
  608.   x = snap_to_x(x);\
  609.  };\
  610.  if( y_use_snap_to_grid == 1 ){\
  611.   y = snap_to_y(y);\
  612.  };\
  613.  var lu = userdraw_x.length;\
  614.  if( lu > 0 ){\
  615.   userdraw_x[lu - 1] = x; userdraw_y[lu - 1] = y;\
  616.   draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  617.  };\
  618. }\
  619. };\
  620. function canvas_remove(x,y){\
  621. if( confirm(\"remove line ?\" )){\
  622.  context_userdraw.clearRect(0,0,xsize,ysize);\
  623.  userdraw_x = [];userdraw_y = [];cnt = 1;\
  624.  return;\
  625. }\
  626. };",draw_type,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  627. }
  628.  
  629. void add_js_segments(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1){
  630. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  631. var canvas_rect;\
  632. var num = %d;\
  633. var line_width = %d;\
  634. var stroke_color = \"%s\";\
  635. var stroke_opacity = %f;\
  636. var use_dashed = %d;\
  637. var dashtype0 = %d;\
  638. var dashtype1 = %d;\
  639. var x0,y0;\
  640. function user_draw(evt){\
  641. var lu = userdraw_x.length;\
  642. if( lu != 0 && lu%%2 == 0){\
  643.  draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  644. }\
  645. var y = evt.clientY - canvas_rect.top;\
  646. if( y < ysize + 1){\
  647.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  648.  var x = evt.clientX - canvas_rect.left;\
  649.  if( x_use_snap_to_grid == 1 ){\
  650.   x = snap_to_x(x);\
  651.  };\
  652.  if( y_use_snap_to_grid == 1 ){\
  653.   y = snap_to_y(y);\
  654.  };\
  655.  if( evt.which == 1 ){\
  656.   if( lu%%2 == 0){\
  657.    x0 = x;y0 = y;\
  658.    if(num == 1){ userdraw_x = [];userdraw_y = [];userdraw_x[0] = x0;userdraw_y[0] = y0;} else {userdraw_x[lu] = x0;userdraw_y[lu] = y0;}\
  659.    draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  660.    user_drag(evt);\
  661.   }\
  662.   else\
  663.   {\
  664.    if( num == 1 ){ userdraw_x[1] = x;userdraw_y[1] = y;} else {userdraw_x[lu] = x;userdraw_y[lu] = y;};\
  665.    draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  666.   }\
  667.  }\
  668.  else\
  669.  {\
  670.   canvas_remove(x,y);\
  671.  }\
  672. }\
  673. };\
  674. function user_drag(evt){\
  675. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  676. var x = evt.clientX - canvas_rect.left;\
  677. var y = evt.clientY - canvas_rect.top;\
  678. var lu = userdraw_x.length;\
  679. if( x_use_snap_to_grid == 1 ){\
  680.   x = snap_to_x(x);\
  681. };\
  682. if( y_use_snap_to_grid == 1 ){\
  683.   y = snap_to_y(y);\
  684. };\
  685. if( lu%%2 != 0 ){\
  686.  context_userdraw.clearRect(0,0,xsize,ysize);\
  687.  draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  688.  draw_circles(context_userdraw,[x],[y],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  689.  draw_segments(context_userdraw,[x0,x],[y0,y],line_width,stroke_color,stroke_opacity);\
  690.  if( lu > 0){\
  691.   draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  692.  }\
  693. }\
  694. };\
  695. function canvas_remove(x,y){\
  696. var marge = 10*line_width;\
  697. for(var p = 0;p < userdraw_x.length ; p++){\
  698.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  699.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  700.    if( confirm(\"remove line ?\" )){\
  701.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  702.     if( p%%2 == 0 ){\
  703.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  704.     }\
  705.     else\
  706.     {\
  707.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  708.     }\
  709.     if(userdraw_x.length < 2){ userdraw_x = [];userdraw_y = [];return;};\
  710.     draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  711.    }\
  712.    return;\
  713.   }\
  714.  }\
  715. }\
  716. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  717. }
  718.  
  719. /*
  720. num=1 single horizontal line
  721. num=2 multiple horizontal lines
  722. num=3 single vertical line
  723. num=4 multiple vertical lines
  724. */
  725. void add_js_hlines(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1){
  726. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  727. var canvas_rect;\
  728. var num = %d;\
  729. var line_width = %d;\
  730. var stroke_color = \"%s\";\
  731. var stroke_opacity = %f;\
  732. var use_dashed = %d;\
  733. var dashtype0 = %d;\
  734. var dashtype1 = %d;\
  735. var x0,y0;\
  736. function user_draw(evt){\
  737. if( evt.which == 1 ){\
  738.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  739.  var y = evt.clientY - canvas_rect.top;\
  740.  var x = evt.clientX - canvas_rect.left;\
  741.  if( x_use_snap_to_grid == 1 ){\
  742.   x = snap_to_x(x);\
  743.  };\
  744.  if( y_use_snap_to_grid == 1 ){\
  745.   y = snap_to_y(y);\
  746.  };\
  747.  var lu = userdraw_x.length;\
  748.  switch(num){\
  749.   case 1: userdraw_x[0] = x;userdraw_x[1] = xmax;userdraw_y[0] = y; userdraw_y[1] = y;break;\
  750.   case 2: userdraw_x[lu] = x;userdraw_x[lu+1] = xmax;userdraw_y[lu] = y;userdraw_y[lu+1] = y;break;\
  751.   case 3: userdraw_x[0] = x;userdraw_x[1] = x;userdraw_y[0] = y; userdraw_y[1] = ymax;break;\
  752.   case 4: userdraw_x[lu] = x;userdraw_x[lu+1] = x;userdraw_y[lu] = y;userdraw_y[lu+1] = ymax;break;\
  753.  };\
  754.  context_userdraw.clearRect(0,0,xsize,ysize);\
  755.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  756. }\
  757. else\
  758. {\
  759.  userdraw_x = [];userdraw_y = [];context_userdraw.clearRect(0,0,xsize,ysize);return;\
  760. };\
  761. };\
  762. function user_drag(evt){ return evt; };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  763. }
  764.  
  765.  
  766. void add_js_lines(FILE *js_include_file,int num,char *draw_type,int line_width, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1){
  767. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  768. var canvas_rect;\
  769. var num = %d;\
  770. var line_width = %d;\
  771. var stroke_color = \"%s\";\
  772. var stroke_opacity = %f;\
  773. var use_dashed = %d;\
  774. var dashtype0 = %d;\
  775. var dashtype1 = %d;\
  776. var x0,y0;\
  777. function user_draw(evt){\
  778. var lu = userdraw_x.length;\
  779. if( lu != 0 && lu%%2 == 0){\
  780.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  781. }\
  782. var y = evt.clientY - canvas_rect.top;\
  783. if( y < ysize + 1){\
  784.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  785.  var x = evt.clientX - canvas_rect.left;\
  786.  if( x_use_snap_to_grid == 1 ){\
  787.   x = snap_to_x(x);\
  788.  };\
  789.  if( y_use_snap_to_grid == 1 ){\
  790.   y = snap_to_y(y);\
  791.  };\
  792.  if( evt.which == 1 ){\
  793.   if( lu%%2 == 0){\
  794.    x0 = x;y0 = y;\
  795.    if(num == 1){ userdraw_x = [];userdraw_y = [];userdraw_x[0] = x0;userdraw_y[0] = y0;} else {userdraw_x[lu] = x0;userdraw_y[lu] = y0;}\
  796.    draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  797.    user_drag(evt);\
  798.   }\
  799.   else\
  800.   {\
  801.    if( num == 1 ){ userdraw_x[1] = x;userdraw_y[1] = y;} else {userdraw_x[lu] = x;userdraw_y[lu] = y;};\
  802.    draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  803.   };\
  804.  }\
  805.  else\
  806.  {\
  807.   canvas_remove(x,y);\
  808.  };\
  809. };\
  810. };\
  811. function user_drag(evt){\
  812. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  813. var x = evt.clientX - canvas_rect.left;\
  814. var y = evt.clientY - canvas_rect.top;\
  815. var lu = userdraw_x.length;\
  816. if( x_use_snap_to_grid == 1 ){\
  817.   x = snap_to_x(x);\
  818. };\
  819. if( y_use_snap_to_grid == 1 ){\
  820.   y = snap_to_y(y);\
  821. };\
  822. if( lu%%2 != 0 ){\
  823.  context_userdraw.clearRect(0,0,xsize,ysize);\
  824.  draw_circles(context_userdraw,[x0],[y0],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  825.  draw_circles(context_userdraw,[x],[y],[line_width],line_width,stroke_color,stroke_opacity,1,stroke_color,stroke_opacity,0,1,1);\
  826.  draw_lines(context_userdraw,[x0,x],[y0,y],line_width,stroke_color,stroke_opacity);\
  827.  if( lu > 0){\
  828.   draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  829.  }\
  830. }\
  831. };\
  832. function canvas_remove(x,y){\
  833. var marge = 10*line_width;\
  834. for(var p = 0;p < userdraw_x.length ; p++){\
  835.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  836.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  837.    if( confirm(\"remove line ?\" )){\
  838.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  839.     if( p%%2 == 0 ){\
  840.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  841.     }\
  842.     else\
  843.     {\
  844.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  845.     }\
  846.     if(userdraw_x.length < 2){ userdraw_x = [];userdraw_y = [];return;};\
  847.     draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  848.    }\
  849.    return;\
  850.   }\
  851.  }\
  852. }\
  853. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  854. }
  855.  
  856. void add_js_arrows(FILE *js_include_file,int num,char *draw_type,int line_width,int type, char *stroke_color,double stroke_opacity,int use_dashed,int dashtype0,int dashtype1,int arrow_head){
  857. /*
  858. constants in draw_arrows() ... for this moment: ;var use_rotate = 0;var angle = 0;var use_translate = 0 ;var vector = [0,0];\
  859.  
  860. */
  861. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  862. var canvas_rect;\
  863. var num = %d;\
  864. var line_width = %d;\
  865. var stroke_color = \"%s\";\
  866. var stroke_opacity = %f;\
  867. var use_dashed = %d;\
  868. var dashtype0 = %d;\
  869. var dashtype1 = %d;\
  870. var arrow_head = %d;\
  871. var x0,y0;\
  872. var type = %d;\
  873. var use_rotate = 0;var angle = 0;var use_translate = 0 ;var vector = [0,0];\
  874. function user_draw(evt){\
  875. var lu = userdraw_x.length;\
  876. if( lu != 0 && lu%%2 == 0){\
  877.  draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,0,[1,0,0,1,0,0]);\
  878. }\
  879. var y = evt.clientY - canvas_rect.top;\
  880. if( y < ysize + 1){\
  881.  canvas_rect = canvas_userdraw.getBoundingClientRect();\
  882.  var x = evt.clientX - canvas_rect.left;\
  883.  if( x_use_snap_to_grid == 1 ){\
  884.   x = snap_to_x(x);\
  885.  };\
  886.  if( y_use_snap_to_grid == 1 ){\
  887.   y = snap_to_y(y);\
  888.  };\
  889.  if( evt.which == 1 ){\
  890.   if( lu%%2 == 0){\
  891.    x0 = x;y0 = y;\
  892.    if(num == 1){ userdraw_x = [];userdraw_y = [];userdraw_x[0] = x0;userdraw_y[0] = y0;} else {userdraw_x[lu] = x0;userdraw_y[lu] = y0;}\
  893.    user_drag(evt);\
  894.   }\
  895.   else\
  896.   {\
  897.    if( num == 1 ){ userdraw_x[1] = x;userdraw_y[1] = y;} else {userdraw_x[lu] = x;userdraw_y[lu] = y;};\
  898.    draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,0,[1,0,0,1,0,0]);\
  899.   }\
  900.  }\
  901.  else\
  902.  {\
  903.   canvas_remove(x,y);\
  904.  }\
  905. }\
  906. };\
  907. function user_drag(evt){\
  908. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  909. var x = evt.clientX - canvas_rect.left;\
  910. var y = evt.clientY - canvas_rect.top;\
  911. var lu = userdraw_x.length;\
  912. if( x_use_snap_to_grid == 1 ){\
  913.   x = snap_to_x(x);\
  914. };\
  915. if( y_use_snap_to_grid == 1 ){\
  916.   y = snap_to_y(y);\
  917. };\
  918. if( lu%%2 != 0 ){\
  919.  context_userdraw.clearRect(0,0,xsize,ysize);\
  920.  draw_arrows(context_userdraw,[x0,x],[y0,y],arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,0,[1,0,0,1,0,0]);\
  921.  if( lu > 0){\
  922.    draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,0,[1,0,0,1,0,0]);\
  923.  }\
  924. }\
  925. };\
  926. function canvas_remove(x,y){\
  927. var marge = 10*line_width;\
  928. for(var p = 0;p < userdraw_x.length ; p++){\
  929.  if(userdraw_x[p] < x + marge && userdraw_x[p] > x - marge ){\
  930.   if(userdraw_y[p] < y + marge && userdraw_y[p] > y - marge ){\
  931.    if( confirm(\"remove line ?\" )){\
  932.     context_userdraw = null;context_userdraw = canvas_userdraw.getContext(\"2d\");context_userdraw.clearRect(0,0,xsize,ysize);\
  933.     if( p%%2 == 0 ){\
  934.      userdraw_x.splice(p,2);userdraw_y.splice(p,2);\
  935.     }\
  936.     else\
  937.     {\
  938.      userdraw_x.splice(p-1,2);userdraw_y.splice(p-1,2);\
  939.     }\
  940.     if(userdraw_x.length < 2){ userdraw_x = [];userdraw_y = [];return;};\
  941.     draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,0,[1,0,0,1,0,0],type,use_rotate,angle,0,[1,0,0,1,0,0]);\
  942.    }\
  943.    return;\
  944.   }\
  945.  }\
  946. }\
  947. };",draw_type,num,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,arrow_head,type);
  948.  
  949. }
  950.  
  951. void add_js_paths(FILE *js_include_file,int num,char *draw_type,int line_width, int closed_path,char *stroke_color,double stroke_opacity,int use_filled, char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  952. fprintf(js_include_file,"\n<!-- begin userdraw \"%s\" on final canvas -->\n\
  953. var path_cnt = 0;\
  954. temp_x = [];\
  955. temp_y = [];\
  956. var num = %d;\
  957. xy_cnt=0;\
  958. var line_width = %d;\
  959. var stroke_color = \"%s\";\
  960. var stroke_opacity = %f;\
  961. var fill_color = \"%s\";\
  962. var fill_opacity = %f;\
  963. var use_filled = %d;\
  964. var use_dashed = %d;\
  965. var dashtype0 = %d;\
  966. var dashtype1 = %d;\
  967. var closed_path = 0;\
  968. var click_cnt=0;\
  969. var x0,y0;\
  970. canvas_rect = canvas_userdraw.getBoundingClientRect();\
  971. function user_draw(evt){\
  972. if(evt.which == 1 ){\
  973.  if( click_cnt == 0 ){\
  974.   click_cnt = 1;\
  975.   user_drag(evt);\
  976.  }\
  977.  else\
  978.  {\
  979.   userdraw_x[path_cnt] = new Array();\
  980.   userdraw_y[path_cnt] = new Array();\
  981.   userdraw_x[path_cnt] = temp_x;\
  982.   userdraw_y[path_cnt] = temp_y;\
  983.   path_cnt++;\
  984.   temp_x = [];\
  985.   temp_y = [];\
  986.   click_cnt = 0;\
  987.   xy_cnt = 0;\
  988.  };\
  989. }\
  990. else\
  991. {\
  992.   canvas_remove(evt.clientX - canvas_rect.left,evt.clientY - canvas_rect.top);\
  993. };\
  994. context_userdraw.clearRect(0,0,xsize,ysize);\
  995. for(var p=0; p < path_cnt; p++){\
  996.  if(userdraw_x[p] != null){\
  997.   draw_paths(context_userdraw,userdraw_x[p],userdraw_y[p],line_width,0,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  998.  };\
  999. };\
  1000. };\
  1001. function user_drag(evt){\
  1002. if(click_cnt == 1 ){\
  1003.  temp_y[xy_cnt] = evt.clientY - canvas_rect.top;\
  1004.  if( temp_y[xy_cnt] < ysize + 1){\
  1005.   temp_x[xy_cnt] = evt.clientX - canvas_rect.left;\
  1006.   if( x_use_snap_to_grid == 1 ){\
  1007.    temp_x[xy_cnt] = snap_to_x(temp_x[xy_cnt]);\
  1008.   };\
  1009.   if( y_use_snap_to_grid == 1 ){\
  1010.    temp_y[xy_cnt] = snap_to_y(temp_y[xy_cnt]);\
  1011.   };\
  1012.   xy_cnt++;\
  1013.   draw_paths(context_userdraw,temp_x,temp_y,line_width,0,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  1014.  };\
  1015. };\
  1016. };\
  1017. function canvas_remove(x,y){\
  1018. var marge = 4*line_width;\
  1019. var tmpx = [];\
  1020. var tmpy = [];\
  1021. for(var i = 0 ; i < path_cnt; i++){\
  1022.  tmpx = userdraw_x[i];\
  1023.  if(tmpx != null){\
  1024.   tmpy = userdraw_y[i];\
  1025.   for(var p = 0;p<tmpx.length;p++){\
  1026.    if( x + marge > tmpx[p] &&  x - marge < tmpx[p] ){\
  1027.     if( y + marge > tmpy[p] &&  y - marge < tmpy[p] ){\
  1028.      if(confirm(\"Remove this drawing ?\")){\
  1029.       userdraw_x[i] = null;\
  1030.       userdraw_y[i] = null;\
  1031.       xy_cnt = 0;click_cnt = 0;\
  1032.       return;\
  1033.      };\
  1034.     };\
  1035.    };\
  1036.   };\
  1037.  };\
  1038. };\
  1039. };",draw_type,num,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1);
  1040. }
  1041.  
  1042. void add_js_tooltip(int canvas_root_id,char *tooltip_text,char *bgcolor,int xsize,int ysize){
  1043. fprintf(stdout,"\n<!-- begin command intooltip %d -->\n\
  1044. <script type=\"text/javascript\">\n\
  1045. var xsize = %d;\
  1046. var ysize = %d;\
  1047. var tooltip%d_obj_x = 0;\
  1048. var tooltip%d_obj_y = 0;\
  1049. var tooltip%d_flipflop = 0;\
  1050. var tooltip%d_obj = document.getElementById(\"canvas_div%d\");\
  1051. tooltip%d_obj.style.display=\"none\";\
  1052. tooltip%d_obj.style.position=\"absolute\";\
  1053. var tooltip%d_link = document.createElement(\"a\");\
  1054. tooltip%d_link.addEventListener(\"mousemove\",tooltip%d_drag,false);\
  1055. tooltip%d_link.setAttribute(\"onclick\",\"tooltip%d_show()\");\
  1056. tooltip%d_link.innerHTML  = \"%s\";\
  1057. var tooltip_placeholder = document.getElementById(\"tooltip_placeholder%d\");\
  1058. tooltip_placeholder.style.display=\"block\";\
  1059. tooltip_placeholder.style.position=\"absolute\";\
  1060. tooltip_placeholder.style.backgroundColor=\"%s\";\
  1061. tooltip_placeholder.appendChild(tooltip%d_link);\
  1062. function tooltip%d_drag(action){\
  1063. if(!action){ action = event; }\
  1064. if(action.clientX){\
  1065.  tooltip%d_obj.style.left = (tooltip%d_mouseX(action) + 10) +\"px\";\
  1066.  var ytop = tooltip%d_mouseY(action);\
  1067.  if(ytop + ysize < window.innerHeight){\
  1068.   tooltip%d_obj.style.top = (ytop - 10) +\"px\";\
  1069.  }\
  1070.  else\
  1071.  {\
  1072.   tooltip%d_obj.style.top = parseInt(ytop - 0.8*ysize) +\"px\";\
  1073.  }\
  1074. }\
  1075. else\
  1076. {\
  1077.  return null;\
  1078. }\
  1079. }\
  1080. function tooltip%d_mouseX(action){\
  1081. if(action.pageX){\
  1082.  return action.pageX;\
  1083. }\
  1084. else\
  1085. {\
  1086.  if(action.clientX){\
  1087.   return action.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);\
  1088.  }\
  1089.  else\
  1090.  {\
  1091.   return null;\
  1092.  }\
  1093. }\
  1094. }\
  1095. function tooltip%d_mouseY(action){\
  1096. if(action.pageY){\
  1097.  return action.pageY;\
  1098. }\
  1099. else\
  1100. {\
  1101.  if(action.clientY){\
  1102.   return action.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop :document.body.scrollTop);\
  1103.  }\
  1104.  else\
  1105.  {\
  1106.   return null;\
  1107.  }\
  1108. }\
  1109. }\
  1110. function tooltip%d_show(){\
  1111. if(tooltip%d_flipflop == 0){\
  1112.  tooltip%d_obj.style.display = \"block\";\
  1113.  tooltip%d_flipflop = 1;\
  1114. }\
  1115. else\
  1116. {\
  1117.  tooltip%d_flipflop = 0;\
  1118.  tooltip%d_obj.style.display = \"none\";\
  1119. }\
  1120. };\n</script>\n<!-- end command intooltip %d -->\n",canvas_root_id,xsize,ysize,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,tooltip_text,canvas_root_id,bgcolor,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id,canvas_root_id);
  1121.  
  1122. }
  1123.  
  1124. void add_js_arc(FILE *js_include_file,int canvas_root_id,int num,int line_width,char *stroke_color,double stroke_opacity,char *fill_color,double fill_opacity,int use_dashed,int dashtype0,int dashtype1){
  1125. fprintf(js_include_file,"\n<!-- begin userdraw \"arc\" on final canvas -->\n\
  1126. var canvas_rect = canvas_userdraw.getBoundingClientRect();\n\
  1127. function user_draw(evt){\
  1128. var num = %d;\
  1129. var x,xc,x1,x2,y,yc,y1,y2;var lu = userdraw_x.length;\
  1130. if( num == 1 && lu == 3 ){ userdraw_x = [];userdraw_y = [];userdraw_radius = [];};\
  1131. if(evt.which == 1){\
  1132.  x = evt.clientX - canvas_rect.left;\
  1133.  y = evt.clientY - canvas_rect.top;\
  1134.  if( x_use_snap_to_grid == 1 ){x = snap_to_x(x);};\
  1135.  if( y_use_snap_to_grid == 1 ){y = snap_to_y(y);};\
  1136.  if(num == 1 && lu == 3){userdraw_x = [];userdraw_y = [];userdraw_radius = [];};\
  1137.  lu = userdraw_x.push(x);userdraw_y.push(y);\
  1138.  if( lu != 0 && lu%%3 == 0){\
  1139.   context_userdraw.clearRect(0,0,xsize,ysize);\
  1140.   userdraw_radius = [];\
  1141.   for(var p = 0 ; p < lu; p = p + 3){\
  1142.     xc = userdraw_x[p];\
  1143.     yc = userdraw_y[p];\
  1144.     x1 = userdraw_x[p+1];\
  1145.     x2 = userdraw_x[p+2];\
  1146.     y1 = userdraw_y[p+1];\
  1147.     y2 = userdraw_y[p+2];\
  1148.     draw_userarc(context_userdraw,xc,yc,x1,y1,x2,y2,%d,\"%s\",%.2f,\"%s\",%.2f,%d,%d,%d);\
  1149.   };\
  1150.  };\
  1151. }\
  1152. else\
  1153. {\
  1154.  if( confirm(\"remove drawing ?\") ){\
  1155.   context_userdraw.clearRect(0,0,xsize,ysize);userdraw_x = [];userdraw_y = [];userdraw_radius = [];return;\
  1156.  };\
  1157. };\
  1158. };\
  1159. function user_drag(evt){ \
  1160. var lu = userdraw_x.length;\
  1161. if( (lu+1)%%3 == 0) {\
  1162.  var x2 = evt.clientX - canvas_rect.left;\
  1163.  var y2 = evt.clientY - canvas_rect.top;\
  1164.  var xc = userdraw_x[lu-2];\
  1165.  var yc = userdraw_y[lu-2];\
  1166.  var x1 = userdraw_x[lu-1];\
  1167.  var y1 = userdraw_y[lu-1];\
  1168.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1169.  draw_userarc(context_userdraw,xc,yc,x1,y1,x2,y2,1,\"255,0,0\",0.6,\"255,255,0\",0.4,0,2,2);\
  1170. };\
  1171. return;\
  1172. };\
  1173. var draw_userarc = function(ctx,xc,yc,x1,y1,x2,y2,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1){\
  1174. ctx.save();\
  1175. if( use_dashed == 1){if(ctx.setLineDash){ctx.setLineDash([dashtype0,dashtype1]);}else{if(ctx.mozDash){ ctx.mozDash = [dashtype0,dashtype1];};};};\
  1176. ctx.lineWidth = line_width;\
  1177. ctx.strokeStyle =  \"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\";\
  1178. ctx.fillStyle = \"rgba(\"+fill_color+\",\"+fill_opacity+\")\";\
  1179. var alpha = find_angle(xc,yc,x1,y1,x2,y2);\
  1180. if( %d == 1 ){userdraw_radius[0] = alpha;ctx.clearRect(0,0,xsize,ysize);}else{userdraw_radius.push(alpha);};\
  1181. var r = Math.sqrt(Math.pow(xc-x2,2)+Math.pow(yc-y2,2));\
  1182. var start;var tmp;var beta;\
  1183. if( x1 > x2 ){\
  1184.  tmp = x2; x2 = x1 ; x1 = tmp;\
  1185.  tmp = y2; y2 = y1 ; y1 = tmp;\
  1186. };\
  1187. if( y1 < yc ){\
  1188.  beta = find_angle(xc,yc,x1,yc,x1,y1);\
  1189.   if( x1 < xc ){\
  1190.    start = Math.PI + beta;\
  1191.   }\
  1192.   else\
  1193.   {\
  1194.    start = 2*Math.PI - beta;\
  1195.   }\
  1196. }\
  1197. else\
  1198. {\
  1199.  beta = find_angle(xc,yc,x2,yc,x2,y2);\
  1200.  if(x2 > xc){\
  1201.   start = beta;\
  1202.  }\
  1203.  else\
  1204.  {\
  1205.   start = Math.PI - beta;\
  1206.  }\
  1207. };\
  1208. ctx.translate(xc,yc);\
  1209. ctx.rotate(start);\
  1210. ctx.beginPath();\
  1211. ctx.arc(0,0,r,0,alpha,false);\
  1212. ctx.lineTo(0,0);\
  1213. ctx.closePath();\
  1214. ctx.fill();\
  1215. ctx.stroke();\
  1216. ctx.restore();\
  1217. };\
  1218. function find_angle(xc,yc,x1,y1,x2,y2){\
  1219. var a = Math.sqrt(Math.pow(xc-x1,2)+Math.pow(yc-y1,2));\
  1220. var b = Math.sqrt(Math.pow(xc-x2,2)+Math.pow(yc-y2,2));\
  1221. var c = Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2));\
  1222. return Math.acos((b*b+a*a-c*c)/(2*b*a));\
  1223. };",num,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1,num);
  1224. }
  1225.  
  1226. void add_js_text(FILE *js_include_file,int canvas_root_id,int font_size,char *font_family,char *font_color,double stroke_opacity){
  1227. fprintf(js_include_file,"\n<!-- begin command userdraw text -->\n\
  1228. canvas_div.addEventListener(\"keydown\",user_text,false);\
  1229. var context_userdraw = canvas_userdraw.getContext(\"2d\");\
  1230. var font_color = \"%s\";\
  1231. var font_opacity = %f;\
  1232. var font_size = %d;\
  1233. var font_family = \"%s\";\
  1234. context_userdraw.fillStyle = \"rgba(\"+font_color+\",\"+font_opacity+\")\";\
  1235. context_userdraw.font = font_family;\
  1236. var userdraw_text = new Array();\
  1237. var txt_cnt = 0;\
  1238. var txt=\"\";\
  1239. var x_txt = 0;\
  1240. var y_txt = 0;\
  1241. var w_txt = 0;\
  1242. var typing = 0;\
  1243. var canvas_rect = canvas_userdraw.getBoundingClientRect();\
  1244. function user_draw(evt){\
  1245. y_txt = evt.clientY - canvas_rect.top;\
  1246. x_txt = evt.clientX - canvas_rect.left;\
  1247. if( x_use_snap_to_grid == 1 ){\
  1248.   x_txt = snap_to_x(x_txt);\
  1249. };\
  1250. if( y_use_snap_to_grid == 1 ){\
  1251.   y_txt = snap_to_y(y_txt);\
  1252. };\
  1253. return;\
  1254. };\
  1255. function user_drag(evt){\
  1256. return;\
  1257. };\
  1258. function user_text(evt){\
  1259. var kc = evt.keyCode;var w;\
  1260. if( kc== 8 || kc == 27 || kc == 46 ){\
  1261.  if(typing == 1 ){\
  1262.    w = context_userdraw.measureText(txt).width;\
  1263.    context_userdraw.clearRect(x_txt-2,y_txt-font_size-2,w+2,font_size+2);\
  1264.    txt = \"\";\
  1265.  }\
  1266.  else\
  1267.  {\
  1268.   for( var p=0 ; p < txt_cnt; p++){\
  1269.    var tmp = (userdraw_text[p]).split(\":\");\
  1270.    w = context_userdraw.measureText(tmp[0]).width;\
  1271.    var y1 = y_txt - font_size;\
  1272.    var y2 = y_txt + font_size;\
  1273.    if( tmp[1] < y2 && tmp[1] > y1){\
  1274.     var x1 = x_txt - font_size;\
  1275.     var x2 = x_txt + w;\
  1276.     if( tmp[0] < x2 && tmp[0] > x1){\
  1277.      if (confirm(\"delete this text : \"+tmp[2]+\"?\")){\
  1278.       context_userdraw.clearRect(x1,y1,x2,y2);\
  1279.       userdraw_text.splice(p,1);\
  1280.       txt_cnt--;\
  1281.       return;\
  1282.      };\
  1283.     };\
  1284.    };\
  1285.   };\
  1286.  };\
  1287. }\
  1288. else\
  1289. {\
  1290.  if( kc < 126 && kc > 40 ){\
  1291.   typing = 1;\
  1292.   txt=txt+String.fromCharCode(kc);\
  1293.   w = context_userdraw.measureText(txt).width;\
  1294.   context_userdraw.save();\
  1295.   context_userdraw.fillStyle = \"lightblue\";\
  1296.   context_userdraw.beginPath();\
  1297.   context_userdraw.rect(x_txt,y_txt-font_size,w,font_size);\
  1298.   context_userdraw.closePath();\
  1299.   context_userdraw.fill();\
  1300.   context_userdraw.restore();\
  1301.   context_userdraw.fillText(txt,x_txt,y_txt);\
  1302.  }\
  1303.  else\
  1304.  {\
  1305.   if(kc == 13 ){\
  1306.    w = context_userdraw.measureText(txt).width;\
  1307.    if(w < 1){alert(\"nothing typed...try again\");return;};\
  1308.    context_userdraw.clearRect(x_txt,y_txt-font_size,w,font_size);\
  1309.    context_userdraw.fillText(txt,x_txt,y_txt);\
  1310.    userdraw_text[txt_cnt] = Math.round(x_txt)+\":\"+Math.round(y_txt)+\":\"+txt;\
  1311.    txt=\"\";\
  1312.    w = 0;\
  1313.    txt_cnt++;\
  1314.    typing = 0;\
  1315.    return;\
  1316.   };\
  1317.  };\
  1318. };\
  1319. };",font_color,stroke_opacity,font_size,font_family);
  1320.  
  1321. }
  1322.  
  1323. /*
  1324.  
  1325. type = 0 : x-values only [command mousex]
  1326. type = 1 : y-values only [command mousey]
  1327. type = 2 : (x:y)         [command mouse]
  1328. type = 3 : degrees       [command mouse_degree]
  1329. */
  1330. void add_js_mouse(FILE *js_include_file,int canvas_cnt,int canvas_root_id,int precision,char *stroke_color,int font_size,double stroke_opacity,int type){
  1331. fprintf(js_include_file,"\n<!-- begin command mouse on current canvas -->\n\
  1332. function use_mouse_coordinates(){\
  1333. var type = %d;\
  1334. var current_canvas = create_canvas%d(%d,xsize,ysize);\
  1335. var current_context = current_canvas.getContext(\"2d\");\
  1336. current_context.clearRect(0,0,xsize,ysize);\
  1337. current_canvas.addEventListener(\"mousemove\",show_coordinate%d,false);\
  1338. current_canvas.addEventListener(\"touchmove\",show_coordinate%d,false);\
  1339. var prec = Math.log(%d)/(Math.log(10));\
  1340. function show_coordinate%d(evt){\
  1341.  var canvas_rect = (current_canvas).getBoundingClientRect();\
  1342.  var x = evt.clientX - canvas_rect.left;\
  1343.  var y = evt.clientY - canvas_rect.top;\
  1344.  var m_data = \"\";var l = userdraw_x.length;\
  1345.  switch(type){\
  1346.   case 0: m_data = \" \"+(px2x(x)).toFixed(prec)+\" \"+unit_x;break;\
  1347.   case 1: m_data = \" \"+(px2y(y)).toFixed(prec)+\" \"+unit_y;break;\
  1348.   case 2: m_data = \"(\"+(px2x(x)).toFixed(prec)+\":\"+(px2y(y)).toFixed(prec)+\")\";break;\
  1349.   case 3: m_data = \" \"+( ( Math.atan( ((xmax - xmin)*(px2y(y))) / ((ymax - ymin)*(px2x(x))) ) )/(Math.PI/180) ).toFixed(prec)+\" \\u00B0 \";break;\
  1350.   case 4: if( l > 0 ){ m_data = \" R = \"+((xmax - xmin)*(distance(x,y,userdraw_x[l-1],userdraw_y[l-1]))/xsize).toFixed(prec)+\" \"+unit_x;};break;\
  1351.   default:break;\
  1352.  };\
  1353.  var s = parseInt(0.8*%d*(m_data.toString()).length);\
  1354.  current_context.font = \"%dpx Ariel\";\
  1355.  current_context.fillStyle = \"rgba(%s,%f)\";\
  1356.  current_context.clearRect(0,0,s,1.2*%d);\
  1357.  current_context.fillText(m_data,0,%d);\
  1358. };\
  1359. };",type,canvas_root_id,MOUSE_CANVAS,canvas_root_id,canvas_root_id,precision,canvas_root_id,font_size,font_size,stroke_color,stroke_opacity,font_size,font_size);
  1360. }
  1361. /* to avoid easy js-code injection...but is it a real problem ? */
  1362. void add_safe_eval(FILE *js_include_file){
  1363. fprintf(js_include_file," \nfunction safe_eval(exp){\
  1364. if(exp.indexOf('^') != -1){\
  1365.  exp = exp.replace(/[a-zA-Z]/g,' ');\
  1366.  exp = exp.replace(/\\*10\\^-/g,'e-');\
  1367.  exp = exp.replace(/\\*10\\^/g,'e+');\
  1368.  exp = exp.replace(/10\\^-/g,'1e-');exp = exp.replace(/10\\^/g,'1e+');\
  1369.  exp = eval(exp);\
  1370.  if(isNaN(exp)){alert(\"invalid input\\ntry just a real number \\ne.g. no calculations...\");return null;}\
  1371.  return exp;\
  1372. };\
  1373. var reg = /(?:[a-z$_][a-z0-9$_]*)|(?:[;={}\\[\\]\"'!&<>^\\\\?:])/ig;\
  1374. var valid = true;\
  1375. exp = exp.replace(reg,function($0){\
  1376.  if(Math.hasOwnProperty($0)){\
  1377.   return \"Math.\"+$0;\
  1378.  }\
  1379.  else\
  1380.  {\
  1381.   valid = false;\
  1382.  }\
  1383. }\
  1384. );\
  1385. if( !valid ){\
  1386.  alert(\"hmmm \"+exp+\" ?\"); exp = null;\
  1387. }\
  1388. else\
  1389. {\
  1390.  try{ exp = eval(exp); } catch(e){alert(\"Invalid arithmetic expression\"); exp = null;};\
  1391. };\
  1392. return exp;\
  1393. };");
  1394. }
  1395.  
  1396. /*
  1397. add display of slider value in mouse context
  1398. use_slider_display = 1 : x or x/y
  1399. use_slider_display = 2 : angle in degrees
  1400. use_slider_display = 3 : angle in radians
  1401. */
  1402. void add_slider_display(FILE *js_include_file,int canvas_root_id,int precision,int font_size,char *font_color,double stroke_opacity){
  1403. fprintf(js_include_file,"<!-- begin add_slider_display -->\n\
  1404. function show_slider_value(value,use_slider_display){\
  1405. var current_canvas = create_canvas%d(%d,xsize,ysize);\
  1406. var current_context = current_canvas.getContext(\"2d\");\
  1407. current_context.clearRect(0,0,xsize,ysize);\
  1408. var prec = Math.log(%d)/(Math.log(10));\
  1409. var string;\
  1410. if(value.length == 2){\
  1411.  string = \" \"+value[0].toFixed(prec)+\" \"+unit_x+\":\"+value[1].toFixed(prec)+\" \"+unit_y;\
  1412. }else{\
  1413.  if(use_slider_display == 2){\
  1414.   value[0] = value[0]*180/Math.PI;\
  1415.   string = \" \"+value[0].toFixed(prec)+\"\\u00B0\";\
  1416.  }else{\
  1417.   if(use_slider_display == 3){\
  1418.    string = \" \"+value[0].toFixed(prec)+\"\\u03C0 rad\";\
  1419.   };\
  1420.  };\
  1421. };\
  1422. var s = parseInt(1.2*%d*(string).length);\
  1423. current_context.font = \"%dpx Ariel\";\
  1424. current_context.strokeStyle = \"rgba(%s,%.2f)\";\
  1425. current_context.clearRect(0,0,s,1.2*%d);\
  1426. current_context.fillText(string,0,%d);\
  1427. };\n",canvas_root_id,MOUSE_CANVAS,precision,font_size,font_size,font_color,stroke_opacity,font_size,font_size);
  1428. }
  1429. /*
  1430. add slider
  1431. return value is array : value[0] is the actual value between value_1 and value_2
  1432. */
  1433. void add_slider(FILE *js_include_file,int canvas_root_id,double v1,double v2,int width,int height,int type,char *label,int slider_cnt,char *stroke_color,char *fill_color,int line_width,double opacity,char *font_family,char *font_color,int use_slider_display){
  1434. fprintf(js_include_file,"\n<!-- begin add_slider no. %d -->\n\
  1435. function add_slider_%d(){\
  1436. if( wims_status == \"done\" ){return;};\
  1437. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1438. var slider_type = %d;\
  1439. var span = document.createElement(\"span\");\
  1440. span.style= \"font:%s;color:%s\";\
  1441. var title = document.createTextNode(\" %s \");\
  1442. var br = document.createElement(\"br\");\
  1443. span.appendChild(title);\
  1444. span.appendChild(br);\
  1445. tooltip_div.appendChild(span);\
  1446. var slider_fillcolor = \"%s\";\
  1447. var slider_strokecolor = \"%s\";\
  1448. var slider_linewidth = \"%d\";\
  1449. var slider_canvas = document.createElement(\"canvas\");\
  1450. slider_canvas.id = \"slider_canvas%d\";\
  1451. tooltip_div.appendChild(slider_canvas);\
  1452. br = document.createElement(\"br\");\
  1453. tooltip_div.appendChild(br);\
  1454. var slider_width = %d;\
  1455. var slider_height = %d;\
  1456. var slider_center = %d;\
  1457. var slider_radius = 4*slider_linewidth;\
  1458. var slider_opacity = %f;\
  1459. slider_canvas.width = slider_width;\
  1460. slider_canvas.height = slider_height;\
  1461. var canvas_rect = (slider_canvas).getBoundingClientRect();\
  1462. var slider_ctx = slider_canvas.getContext(\"2d\");\
  1463. slider_ctx.font = \"%s\";\
  1464. slider_ctx.strokeStyle = \"rgba(\"+slider_strokecolor+\",\"+slider_opacity+\")\";\
  1465. slider_ctx.fillStyle = \"rgba(\"+slider_fillcolor+\",\"+slider_opacity+\")\";\
  1466. slider_ctx.lineWidth = slider_linewidth;\
  1467. slider_ctx.beginPath();\
  1468. slider_ctx.arc(10,slider_center,slider_radius,0,2*Math.PI,false);\
  1469. slider_ctx.moveTo(10,slider_center);\
  1470. slider_ctx.lineTo(slider_width-10,slider_center);\
  1471. slider_ctx.rect(0,0,slider_width,slider_height);\
  1472. slider_ctx.closePath();\
  1473. slider_ctx.fill();\
  1474. slider_ctx.stroke();\
  1475. slider_canvas.addEventListener(\"mousemove\",slider_%d,false);\
  1476. function slider_%d(evt){\
  1477. var value_1 = %f;\
  1478. var value_2 = %f;\
  1479. slider_ctx.clearRect(0,0,slider_width,slider_height);\
  1480. var x = evt.clientX - canvas_rect.left;\
  1481. var value = x*(value_2 - value_1)/slider_width + value_1;\
  1482. slider_ctx.beginPath();\
  1483. slider_ctx.arc(x,slider_center,slider_radius,0,2*Math.PI,false);\
  1484. slider_ctx.moveTo(10,slider_center);\
  1485. slider_ctx.lineTo(slider_width-10,slider_center);\
  1486. slider_ctx.rect(0,0,slider_width,slider_height);\
  1487. slider_ctx.closePath();\
  1488. slider_ctx.fill();\
  1489. slider_ctx.stroke();\
  1490. dragstuff.Slide( [value] , %d );\
  1491. if(%d != 0 ){show_slider_value([value],%d);}\
  1492. return;\
  1493. };\
  1494. };\
  1495. add_slider_%d();",slider_cnt,slider_cnt,canvas_root_id,type,font_family,font_color,label,fill_color,stroke_color,line_width,slider_cnt,width,height,(int)(0.5*height),opacity,font_family,slider_cnt,slider_cnt,v1,v2,slider_cnt,use_slider_display,use_slider_display,slider_cnt);
  1496. }
  1497.  
  1498.  
  1499. /*
  1500. add xyslider
  1501.  return value is array : value[0] is the actual x-value between value_1 and value_2, value[1] is y-value between value_1 and value_2
  1502. */
  1503. void add_xyslider(FILE *js_include_file, int canvas_root_id,double v1,double v2,int width,int height,int type,char *label,int slider_cnt,char *stroke_color,char *fill_color,int line_width,double opacity,char *font_family,char *font_color,int use_slider_display){
  1504. fprintf(js_include_file,"\n<!-- begin add_slider no. %d -->\n\
  1505. function add_slider_%d(){\
  1506. if( wims_status == \"done\" ){return;};\
  1507. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1508. var slider_type = %d;\
  1509. var span = document.createElement(\"span\");\
  1510. span.style= \"font:%s;color:%s\";\
  1511. var title = document.createTextNode(\" %s \");\
  1512. var br = document.createElement(\"br\");\
  1513. span.appendChild(title);\
  1514. span.appendChild(br);\
  1515. tooltip_div.appendChild(span);\
  1516. var slider_fillcolor = \"%s\";\
  1517. var slider_click = 0;\
  1518. var slider_strokecolor = \"%s\";\
  1519. var slider_linewidth = \"%d\";\
  1520. var slider_canvas = document.createElement(\"canvas\");\
  1521. slider_canvas.id = \"slider_canvas%d\";\
  1522. tooltip_div.appendChild(slider_canvas);\
  1523. br = document.createElement(\"br\");\
  1524. tooltip_div.appendChild(br);\
  1525. var slider_width = %d;\
  1526. var slider_height = %d;\
  1527. var slider_center = %d;\
  1528. var slider_radius = 4*slider_linewidth;\
  1529. var slider_opacity = %f;\
  1530. slider_canvas.width = slider_width;\
  1531. slider_canvas.height = slider_height;\
  1532. var canvas_rect = (slider_canvas).getBoundingClientRect();\
  1533. var slider_ctx = slider_canvas.getContext(\"2d\");\
  1534. slider_ctx.font = \"%s\";\
  1535. slider_ctx.strokeStyle = \"rgba(\"+slider_strokecolor+\",\"+slider_opacity+\")\";\
  1536. slider_ctx.fillStyle = \"rgba(\"+slider_fillcolor+\",\"+slider_opacity+\")\";\
  1537. slider_ctx.lineWidth = slider_linewidth;\
  1538. slider_ctx.beginPath();\
  1539. slider_ctx.arc(10,slider_center,slider_radius,0,2*Math.PI,false);\
  1540. slider_ctx.fill();\
  1541. slider_ctx.closePath();\
  1542. slider_ctx.rect(0,0,slider_width,slider_height);\
  1543. slider_ctx.stroke();\
  1544. slider_canvas.addEventListener(\"mousemove\",sliderdrag_%d,false);\
  1545. slider_canvas.addEventListener(\"mousedown\",sliderclick_%d,false);\
  1546. function sliderdrag_%d(evt){\
  1547. if(slider_click == 1){\
  1548.  var value_1 = %f;\
  1549.  var value_2 = %f;\
  1550.  var canvas_rect = (slider_canvas).getBoundingClientRect();\
  1551.  slider_ctx.clearRect(0,0,slider_width,slider_height);\
  1552.  var x = evt.clientX - canvas_rect.left;\
  1553.  var y = evt.clientY - canvas_rect.top;\
  1554.  var value_x = x*(value_2 - value_1)/slider_width + value_1;\
  1555.  var value_y = y*(value_2 - value_1)/slider_height + value_1;\
  1556.  slider_ctx.beginPath();\
  1557.  slider_ctx.arc(x,y,slider_radius,0,2*Math.PI,false);\
  1558.  slider_ctx.fill();\
  1559.  slider_ctx.rect(0,0,slider_width,slider_height);\
  1560.  slider_ctx.closePath();\
  1561.  slider_ctx.stroke();\
  1562.  dragstuff.Slide( [value_x,1-1*value_y] , %d );\
  1563.  if(%d != 0 ){show_slider_value([value_x,value_y],%d);}\
  1564. };\
  1565. };\
  1566. function sliderclick_%d(evt){\
  1567.  if(slider_click == 1){slider_click = 0;}else{slider_click = 1;};\
  1568. };\
  1569. };\
  1570. add_slider_%d();",slider_cnt,slider_cnt,canvas_root_id,type,font_family,font_color,label,fill_color,stroke_color,line_width,slider_cnt,width,height,(int)(0.5*height),opacity,font_family,slider_cnt,slider_cnt,slider_cnt,v1,v2,slider_cnt,use_slider_display,use_slider_display,slider_cnt,slider_cnt);
  1571. }
  1572.  
  1573.  
  1574. /*
  1575. adds inputfield for x-value: returns the js-calculated y-value after click on 'OK' button
  1576. draws a non-configurable crosshair on this calculated location
  1577. */
  1578. void add_calc_y(FILE *js_include_file,int canvas_root_id,char *jsmath){
  1579. fprintf(js_include_file,"\n<!-- begin add_calc_y -->\n\
  1580. use_jsmath=1;\
  1581. function add_calc_y(){\
  1582. if( wims_status == \"done\" ){return;};\
  1583. var fun = to_js_math(\"%s\");if(fun == null){return;};\
  1584. function eval_jsmath(x){return parseFloat(eval(fun));};\
  1585. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1586. var calc_div = document.createElement('div');\
  1587. calc_div.id = \"calc_div\";\
  1588. tooltip_div.appendChild(calc_div);\
  1589. var label_x = \"x\";var label_y = \"y\";\
  1590. if( typeof xaxislabel !== 'undefined' ){label_x = xaxislabel;}\
  1591. if( typeof yaxislabel !== 'undefined' ){label_y = yaxislabel;}\
  1592. calc_div.innerHTML=\"<br /><span style='font-style:italic;font-size:10px'>\"+label_x+\" : <input type='text' size='4' value='' id='calc_input_x' style='text-align:center;color:blue;background-color:orange;' />&nbsp;\"+ label_y+\" : <input type='text' size='6' value='' id='calc_output_y' style='text-align:center;color:blue;background-color:lightgreen;' readonly' /><input id='calc_button' type='button' value='OK' onclick=''  style='color:red;background-color:lightblue;' /></span> \";\
  1593. var calc_button = document.getElementById(\"calc_button\");\
  1594. calc_button.addEventListener(\"mousedown\",function(e){var x_value=document.getElementById(\"calc_input_x\").value;\
  1595. var y_value = eval_jsmath(x_value);\
  1596. document.getElementById(\"calc_output_y\").value = y_value;\
  1597. if(isNaN(y_value)){return;};\
  1598. var canvas = create_canvas%d(123,xsize,ysize);\
  1599. var ctx = canvas.getContext(\"2d\");\
  1600. draw_crosshairs(ctx,[x2px(x_value)],[y2px(y_value)],1,5,\"#000000\",1,0,0,0,[0,0]);return;},false);\
  1601. };add_calc_y();",jsmath,canvas_root_id,canvas_root_id);
  1602. }
  1603. /*
  1604.  x-value of the mouse will be used to calculate via javascript the corresponding y-value using the verbatim js-math function
  1605.  a configurable crosshair and vertical/horizontal crosshair lines will be drawn
  1606.  function is called "use_mouse_coordinates() and thus can not be combined with command 'mouse'
  1607. */
  1608. void add_trace_js_mouse(FILE *js_include_file,int canvas_cnt,int canvas_root_id,char *stroke_color,char *jsmath,int font_size,double stroke_opacity,int line_width,int crosshair_size){
  1609. fprintf(js_include_file,"\n<!-- begin command add_trace_jsmath  trace_canvas -->\n\
  1610. use_jsmath=1;\
  1611. function use_trace_jsmath(){\
  1612. if( wims_status == \"done\" ){return;};\
  1613. var label_x = \"x\";var label_y = \"y\";\
  1614. if( typeof xaxislabel !== 'undefined' ){label_x = xaxislabel;}\
  1615. if( typeof yaxislabel !== 'undefined' ){label_y = yaxislabel;}\
  1616. var trace_canvas = create_canvas%d(%d,xsize,ysize);\
  1617. var trace_context = trace_canvas.getContext(\"2d\");\
  1618. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1619. var trace_div = document.createElement('div');\
  1620. trace_div.id = \"trace_div\";\
  1621. tooltip_div.appendChild(trace_div);\
  1622. trace_div.innerHTML = \"<br /><span style='font-style:italic;font-size:10px'>\"+label_x+\" : <input type='text' size='4' value='' id='trace_input_x' style='text-align:center;color:blue;background-color:lightgreen;' />\"+label_y+\" : <input type='text' size='6' value='' id='trace_input_y' style='text-align:center;color:blue;background-color:lightgreen;' readonly' /></span> \";\
  1623. canvas_div.addEventListener(\"mousemove\",trace,false);\
  1624. canvas_div.addEventListener(\"touchmove\",trace,false);\
  1625. var fun = to_js_math(\"%s\");if(fun == null){return;};\
  1626. function eval_jsmath(x){return parseFloat(eval(fun));};\
  1627. function trace(evt){\
  1628.  var canvas_rect = (trace_canvas).getBoundingClientRect();\
  1629.  var x_px = evt.clientX - canvas_rect.left;\
  1630.  var x = px2x(x_px);\
  1631.  var y = eval_jsmath(x);\
  1632.  if(isNaN(y)){return;};\
  1633.  var y_px = y2px(y);\
  1634.  trace_context.clearRect(0,0,xsize,ysize);\
  1635.  draw_crosshairs(trace_context,[x_px],[y_px],%d,%d,\"%s\",%f,0,0,0,[0,0]);\
  1636.  document.getElementById(\"trace_input_x\").value = x;\
  1637.  document.getElementById(\"trace_input_y\").value = y;\
  1638. };\
  1639. return;\
  1640. };use_trace_jsmath();",canvas_root_id,canvas_cnt,canvas_root_id,jsmath,line_width,crosshair_size,stroke_color,stroke_opacity);
  1641. }
  1642.  
  1643. /*
  1644. add a table with 2 textarea's labeled 'x' 'y' ( or 'xlabel' 'ylabel' if defined)
  1645. add two buttons: OK and NOK (OK draws; NOK will delete last item pair from userdraw_x / userdraw_y array's
  1646. */
  1647. void add_textarea_xy(FILE *js_include_file, int canvas_root_id){
  1648. fprintf(js_include_file,"\n<!-- begin add_textarea_xy -->\n\
  1649. function add_textarea_xy(){\
  1650. if( wims_status == \"done\" ){return;};\
  1651. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1652. var textarea_div = document.createElement('div');\
  1653. textarea_div.id = \"textarea_div\";\
  1654. tooltip_div.appendChild(textarea_div);\
  1655. var label_x = \"x\";var label_y = \"y\";\
  1656. if( typeof xaxislabel !== 'undefined' ){label_x = xaxislabel;}\
  1657. if( typeof yaxislabel !== 'undefined' ){label_y = yaxislabel;}\
  1658. textarea_div.innerHTML=\"\
  1659. <table style=\'border:1px solid black;background-color:#ffffa0\' >\
  1660. <tr>\
  1661. <td><input id='textarea_ok_button' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;'/></td>\
  1662. <td><input id='textarea_nok_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'/></td>\
  1663. </tr>\
  1664. <tr>\
  1665. <td><em>\"+label_x+\"</em></td>\
  1666. <td><em>\"+label_y+\"</em></td>\
  1667. </tr>\
  1668. <tr>\
  1669. <td><textarea rows='5' cols='2' id='userinput_x' style='text-align:center;color:blue;background-color:orange;' ></textarea></td>\
  1670. <td><textarea rows='5' cols='2' id='userinput_y' style='text-align:center;color:blue;background-color:orange;' ></textarea></td>\
  1671. </tr>\
  1672. </table>\";\
  1673. var textarea_ok_button = document.getElementById(\"textarea_ok_button\");\
  1674. var textarea_nok_button = document.getElementById(\"textarea_nok_button\");\
  1675. textarea_ok_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  1676. textarea_nok_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);\
  1677. return;\
  1678. };add_textarea_xy();",canvas_root_id);
  1679. }
  1680.  
  1681. /*
  1682.  
  1683. */
  1684. void add_setlimits(FILE *js_include_file, int canvas_root_id){
  1685. fprintf(js_include_file,"\n<!-- begin add_setlimits -->\n\
  1686. use_pan_and_zoom = 1;\
  1687. function use_setlimits(){\
  1688. if( wims_status == \"done\" ){return;};\
  1689. var label_x = \"x\";var label_y = \"y\";\
  1690. if( typeof xaxislabel !== 'undefined' ){label_x = xaxislabel;}\
  1691. if( typeof yaxislabel !== 'undefined' ){label_y = yaxislabel;}\
  1692. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1693. var setlim_div = document.createElement('div');\
  1694. setlim_div.id = \"setlim_div\";\
  1695. tooltip_div.appendChild(setlim_div);\
  1696. setlim_div.innerHTML=\"<br /><span style='font-style:italic;font-size:10px'>\"+label_x+\"min = <input type='text' size='4' value='\"+xmin+\"' id='userinput_xmin' style='text-align:center;color:blue;background-color:orange;' /> \"+label_x+\"max = <input type='text' size='4' value='\"+xmax+\"' id='userinput_xmax' style='text-align:center;color:blue;background-color:orange;' /><br />\"+label_y+\"min = <input type='text' size='4' value='\"+ymin+\"' id='userinput_ymin' style='text-align:center;color:blue;background-color:orange;' /> \"+label_y+\"max = <input type='text' size='4' value='\"+ymax+\"' id='userinput_ymax' style='text-align:center;color:blue;background-color:orange;' /><br /><input id='set_limits' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;' />\";\
  1697. var setlimit_button = document.getElementById(\"set_limits\");\
  1698. function set_limits(e){\
  1699. xmin = safe_eval(document.getElementById('userinput_xmin').value);\
  1700. xmax = safe_eval(document.getElementById('userinput_xmax').value);\
  1701. ymin = safe_eval(document.getElementById('userinput_ymin').value);\
  1702. ymax = safe_eval(document.getElementById('userinput_ymax').value);\
  1703. if(xmin > xmax || ymin > ymax){alert(\"your limits are not correct...\");return;}\
  1704. try{start_canvas%d(1234)}catch(e){};try{dragstuff.Zoom(xmin,xmax,ymin,ymax)}catch(e){};return;};\
  1705. setlimit_button.addEventListener(\"mousedown\",function(e){set_limits();},false);\
  1706. };use_setlimits();",canvas_root_id,canvas_root_id);
  1707. }
  1708.  
  1709. void add_input_jsfunction(FILE *js_include_file, int canvas_root_id,int num,char *input_style,int input_cnt,char *stroke_color,float stroke_opacity,int line_width,int use_dashed,int dashtype0,int dashtype1){
  1710. fprintf(js_include_file,"\n<!-- begin add_input_jsfunction -->\n\
  1711. function clear_jsfunction(id){\
  1712. try{\
  1713.  var canvas_plot = document.getElementById(\"wims_canvas%d\"+id);\n\
  1714.  var canvas_plot_ctx = canvas_plot.getContext(\"2d\");\n\
  1715.  if( confirm(\"clear function plot?\") ){\
  1716.   canvas_plot_ctx.clearRect(0,0,xsize,ysize);\n\
  1717.   document.getElementById('canvas_input%d').value = \"\";\n\
  1718.  };\n\
  1719.  return;\n\
  1720. }catch(e){alert(\"nothing to remove...\");};\n\
  1721. return;\n\
  1722. };\n\
  1723. function add_input_jsfunction(){\
  1724. var num = %d;\n\
  1725. var canvas_plot_id = %d;\n\
  1726. if( wims_status == \"done\" ){return;};\n\
  1727. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\n\
  1728. var input_jsfunction_div = document.createElement('div');\n\
  1729. input_jsfunction_div.id = \"input_jsfunction_div\";\n\
  1730. tooltip_div.appendChild(input_jsfunction_div);\n\
  1731. if( typeof xaxislabel == 'undefined' ){var xaxislabel = \"function\";}\
  1732. input_jsfunction_div.innerHTML=\"<br /><span style='font-style:italic;font-size:10px'><b>\"+xaxislabel+\" : <input type='text' size='16' value='' id='canvas_input%d' style='%s' /></b><input id='update_button' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;'/><input id='delete_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'/></span> \";\n\
  1733. var update_button = document.getElementById(\"update_button\");\n\
  1734. var delete_button = document.getElementById(\"delete_button\");\n\
  1735. update_button.addEventListener(\"mousedown\",function(e){jsplot(canvas_plot_id,document.getElementById('canvas_input%d').value,%d,'%s',%.2f,%d,%d,%d);return;},false);\
  1736. delete_button.addEventListener(\"mousedown\",function(e){clear_jsfunction(canvas_plot_id);return;},false);\n\
  1737. };add_input_jsfunction();",canvas_root_id,input_cnt,num,USERDRAW_JSPLOT,canvas_root_id,input_cnt,input_style,input_cnt,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);
  1738. }
  1739.  
  1740.  
  1741. /*
  1742. adds 2 inputfields (x:y) and 'ok' | 'nok' button
  1743. these are used for user drawing with inputfields...
  1744. */
  1745.  
  1746. void add_input_xy(FILE *js_include_file, int canvas_root_id){
  1747. fprintf(js_include_file,"\n<!-- begin add_input_xy -->\n\
  1748. function add_input_xy(){\
  1749. if( wims_status == \"done\" ){return;};\
  1750. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1751. var input_xy_div = document.createElement('div');\
  1752. input_xy_div.id = \"input_xy_div\";\
  1753. tooltip_div.appendChild(input_xy_div);\
  1754. var label_x = \"x\";var label_y = \"y\";\
  1755. input_xy_div.innerHTML=\"<br /><span style='font-style:italic;font-size:10px'><b>( <input type='text' size='6' value='' id='userinput_x' style='text-align:center;color:blue;background-color:orange;' /> : <input type='text' size='6' value='' id='userinput_y' style='text-align:center;color:blue;background-color:orange;' /> )</b><input id='update_button' type='button' value='OK' onclick=''  style='color:red;background-color:lightblue;'/><input id='delete_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'/></span> \";\
  1756. var update_button = document.getElementById(\"update_button\");\
  1757. var delete_button = document.getElementById(\"delete_button\");\
  1758. update_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  1759. delete_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);\
  1760. };add_input_xy();",canvas_root_id);
  1761. }
  1762.  
  1763. /* adds 4 inputfields (x1:y1) --- (x2:y2) and 'ok' + 'nok' button */
  1764. void add_input_x1y1x2y2(FILE *js_include_file, int canvas_root_id){
  1765. fprintf(js_include_file,"\n<!-- begin add_input_x1y1x2y2 -->\n\
  1766. function add_input_x1y1x2y2(){\
  1767. if( wims_status == \"done\" ){return;};\
  1768. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1769. var input_x1y1x2y2_div = document.createElement('div');\
  1770. input_x1y1x2y2_div.id = \"input_x1y1x2y2_div\";\
  1771. tooltip_div.appendChild(input_x1y1x2y2_div);\
  1772. input_x1y1x2y2_div.innerHTML=\"<br /><span><b>( <input type='text' size='6' value='' id='userinput_x1' style='text-align:center;color:blue;background-color:orange;' /> : <input type='text' size='6' value='' id='userinput_y1' style='text-align:center;color:blue;background-color:orange;' /> ) ----- ( <input type='text' size='6' value='' id='userinput_x2' style='text-align:center;color:blue;background-color:orange;' /> : <input type='text' size='6' value='' id='userinput_y2' style='text-align:center;color:blue;background-color:orange;'/> )</b><input id='update_button' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;'/><input id='delete_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;' /></span> \";\
  1773. var update_button = document.getElementById(\"update_button\");\
  1774. var delete_button = document.getElementById(\"delete_button\");\
  1775. update_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  1776. delete_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);\
  1777. };add_input_x1y1x2y2();",canvas_root_id);
  1778. }
  1779.  
  1780. /* adds 3 inputfields Center (x:y) Radius r and 'ok'+'nok' buttons */
  1781. void add_input_xyr(FILE *js_include_file, int canvas_root_id){
  1782. fprintf(js_include_file,"\n<!-- begin add_input_xyr -->\n\
  1783. function add_input_xyr(){\
  1784. if( wims_status == \"done\" ){return;};\
  1785. var tooltip_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  1786. var input_xyr_div = document.createElement('div');\
  1787. input_xyr_div.id = \"input_xyr_div\";\
  1788. tooltip_div.appendChild(input_xyr_div);\
  1789. input_xyr_div.innerHTML=\"<br /><span style='font-style:italic;font-size:10px'><b>Center : ( <input type='text' size='6' value='' id='userinput_x' style='text-align:center;color:blue;background-color:orange;' /> : <input type='text' size='6' value='' id='userinput_y' style='text-align:center;color:blue;background-color:orange;' /> ) Radius : <input type='text' size='6' value='' id='userinput_r' style='text-align:center;color:blue;background-color:orange;' /></b><input id='update_button' type='button' value='OK' onclick='' style='color:red;background-color:lightblue;'/><input id='delete_button' type='button' value='NOK' onclick='' style='color:blue;background-color:red;'/></span> \";\
  1790. var update_button = document.getElementById(\"update_button\");\
  1791. var delete_button = document.getElementById(\"delete_button\");\
  1792. update_button.addEventListener(\"mousedown\",function(e){user_redraw(1);return;},false);\
  1793. delete_button.addEventListener(\"mousedown\",function(e){user_redraw(-1);return;},false);\
  1794. };add_input_xyr();",canvas_root_id);
  1795. }
  1796.  
  1797. /* THESE JS-FUNCTIONS COULD BE MADE LESS COPY & PASTE "PROGRAMMING" */
  1798.  
  1799. /* draw circle(s) / point(s) via 3 inputfields */
  1800. void add_input_circle(FILE *js_include_file,int type,int num){
  1801. /*
  1802. type = 0 : a point ...radius is fixed
  1803. type = 1 : a circle ... read inputfield userinput_r
  1804. num = 1 : a single point / circle
  1805. num = 2 : multiple points / circles
  1806. */
  1807. fprintf(js_include_file,"\n<!-- begin add_input_circle -->\n\
  1808. function user_redraw(t){\
  1809. var type = %d;\
  1810. var num = %d;\
  1811. var lu = userdraw_x.length;\
  1812. if( t == -1 && lu > 0){\
  1813.  userdraw_x.splice(lu-1,1);\
  1814.  userdraw_y.splice(lu-1,1);\
  1815.  if(type == 1){\
  1816.    userdraw_radius.splice(lu-1,1);\
  1817.  };\
  1818.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1819.  draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  1820.  return;\
  1821. };\
  1822. var add_x = safe_eval( document.getElementById(\"userinput_x\").value );\
  1823. var add_y = safe_eval( document.getElementById(\"userinput_y\").value );\
  1824. if( add_x != null && add_y != null ){\
  1825.  if( type == 2 ){\
  1826.   var add_r = safe_eval( document.getElementById(\"userinput_r\").value );if( add_r == null ){alert(\"illegal radius input \");return;}\
  1827.   if( num == 1 ){\
  1828.    userdraw_radius[0] = parseInt(Math.abs(xsize*(add_r)/(xmax - xmin)));\
  1829.   }\
  1830.   else\
  1831.   {\
  1832.    userdraw_radius[lu] = parseInt(Math.abs(xsize*(add_r)/(xmax - xmin)));\
  1833.   };\
  1834.  }\
  1835.  else\
  1836.  {\
  1837.    userdraw_radius[lu] = userdraw_radius[0];\
  1838.  };\
  1839.  if( num == 1 ){\
  1840.  userdraw_x[0] = x2px(add_x);\
  1841.  userdraw_y[0] = y2px(add_y);\
  1842.  }\
  1843.  else\
  1844.  {\
  1845.    userdraw_x[lu] = x2px(add_x);\
  1846.    userdraw_y[lu] = y2px(add_y);\
  1847.    xy_cnt++;\
  1848.  };\
  1849.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1850.  draw_circles(context_userdraw,userdraw_x,userdraw_y,userdraw_radius,line_width,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,dashtype1);\
  1851. };\
  1852. return;\
  1853. };",type,num);
  1854. }
  1855. /* draw crosshairs via inputfields x/y */
  1856. void add_input_crosshair(FILE *js_include_file,int num){
  1857. fprintf(js_include_file,"\n<!-- begin add_input_crosshair -->\n\
  1858. function user_redraw(t){\
  1859. var lu = userdraw_x.length;\
  1860. if( t == -1 && lu > 0){\
  1861.  userdraw_x.splice(lu-1,1);\
  1862.  userdraw_y.splice(lu-1,1);\
  1863.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1864.  draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  1865.  return;\
  1866. };\
  1867. var add_x = safe_eval( document.getElementById(\"userinput_x\").value );\
  1868. var add_y = safe_eval( document.getElementById(\"userinput_y\").value );\
  1869. if( add_x != null && add_y != null ){\
  1870.  if( %d == 1 ){\
  1871.   userdraw_x[0] = x2px(add_x);\
  1872.   userdraw_y[0] = y2px(add_y);\
  1873.  }\
  1874.  else\
  1875.  {\
  1876.    userdraw_x[lu] = x2px(add_x);\
  1877.    userdraw_y[lu] = y2px(add_y);\
  1878.    xy_cnt++;\
  1879.  };\
  1880.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1881.  draw_crosshairs(context_userdraw,userdraw_x,userdraw_y,line_width,crosshair_size,stroke_color,stroke_opacity,0,0,0,[0,0]);\
  1882. };\
  1883. return;\
  1884. };",num);
  1885. }
  1886.  
  1887. /* draw arrows via inputfields x/y */
  1888. void add_input_arrow(FILE *js_include_file,int num){
  1889. fprintf(js_include_file,"\n<!-- begin add_input_arrow -->\n\
  1890. function user_redraw(t){\
  1891. var lu = userdraw_x.length;\
  1892. if( t == -1 && lu > 1 ){\
  1893.  userdraw_x.splice(lu-2,2);\
  1894.  userdraw_y.splice(lu-2,2);\
  1895.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1896.  draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,0,[1,0,0,1,0,0]);\
  1897.  return;\
  1898. };\
  1899. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  1900. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  1901. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  1902. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  1903. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  1904.  if( %d == 2 ){\
  1905.    var s = userdraw_x.length;\
  1906.    userdraw_x[lu] = x2px(add_x1);\
  1907.    userdraw_y[lu] = y2px(add_y1);\
  1908.    userdraw_x[lu+1] = x2px(add_x2);\
  1909.    userdraw_y[lu+1] = y2px(add_y2);\
  1910.  }\
  1911.  else\
  1912.  {\
  1913.   userdraw_x[0] = x2px(add_x1);\
  1914.   userdraw_y[0] = y2px(add_y1);\
  1915.   userdraw_x[1] = x2px(add_x2);\
  1916.   userdraw_y[1] = y2px(add_y2);\
  1917.  };\
  1918.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1919.  draw_arrows(context_userdraw,userdraw_x,userdraw_y,arrow_head,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,type,use_rotate,angle,0,[1,0,0,1,0,0]);\
  1920. };\
  1921. return;\
  1922. };",num);
  1923. }
  1924.  
  1925. /* draw line via inputfields x/y */
  1926. void add_input_line(FILE *js_include_file,int num){
  1927. fprintf(js_include_file,"\n<!-- begin line via inputfields  -->\n\
  1928. function user_redraw(t){\
  1929. var lu = userdraw_x.length;\
  1930. if( t == -1 && lu > 1){\
  1931.  userdraw_x.splice(lu-2,2);\
  1932.  userdraw_y.splice(lu-2,2);\
  1933.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1934.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,1,0,0);\
  1935.  return;\
  1936. };\
  1937. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  1938. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  1939. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  1940. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  1941. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  1942.  if( %d == 2 ){\
  1943.    userdraw_x[lu] = x2px(add_x1);\
  1944.    userdraw_y[lu] = y2px(add_y1);\
  1945.    userdraw_x[lu+1] = x2px(add_x2);\
  1946.    userdraw_y[lu+1] = y2px(add_y2);\
  1947.  }\
  1948.  else\
  1949.  {\
  1950.   userdraw_x[0] = x2px(add_x1);\
  1951.   userdraw_y[0] = y2px(add_y1);\
  1952.   userdraw_x[1] = x2px(add_x2);\
  1953.   userdraw_y[1] = y2px(add_y2);\
  1954.  };\
  1955.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1956.  draw_lines(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1,1,0,0);\
  1957. };\
  1958. return;\
  1959. };",num);
  1960. }
  1961.  
  1962.  
  1963. /* draw polyline via inputfields x/y */
  1964. void add_input_polyline(FILE *js_include_file){
  1965. fprintf(js_include_file,"\n<!-- begin polyline_segment via inputfields -->\n\
  1966. function user_redraw(t){\
  1967. var lu = userdraw_x.length;\
  1968. cnt = 1;\
  1969. if( t == -1 && lu > 0){\
  1970.  userdraw_x.splice(lu-1,1);\
  1971.  userdraw_y.splice(lu-1,1);\
  1972.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1973.  draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1974.  return;\
  1975. };\
  1976. var add_x = safe_eval( document.getElementById(\"userinput_x\").value );\
  1977. var add_y = safe_eval( document.getElementById(\"userinput_y\").value );\
  1978. if(add_x != null && add_y != null ){\
  1979.  userdraw_x.push(x2px(add_x));\
  1980.  userdraw_y.push(y2px(add_y));\
  1981.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1982.  draw_polyline(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1983. };\
  1984. return;\
  1985. };");
  1986. }
  1987. /* draw segment(s) via inputfields x/y */
  1988. void add_input_segment(FILE *js_include_file,int num){
  1989. fprintf(js_include_file,"\n<!-- begin add_input_segment -->\n\
  1990. function user_redraw(t){\
  1991. var lu = userdraw_x.length;\
  1992. if( t == -1 && lu > 1){\
  1993.  userdraw_x.splice(lu-2,2);\
  1994.  userdraw_y.splice(lu-2,2);\
  1995.  context_userdraw.clearRect(0,0,xsize,ysize);\
  1996.  draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  1997.  return;\
  1998. };\
  1999. var add_x1 = safe_eval( document.getElementById(\"userinput_x1\").value );\
  2000. var add_y1 = safe_eval( document.getElementById(\"userinput_y1\").value );\
  2001. var add_x2 = safe_eval( document.getElementById(\"userinput_x2\").value );\
  2002. var add_y2 = safe_eval( document.getElementById(\"userinput_y2\").value );\
  2003. if( add_x1 != null && add_y1 != null && add_x2 != null && add_y2 != null ){\
  2004.  if( %d == 2 ){\
  2005.    var s = userdraw_x.length;\
  2006.    userdraw_x[s] = x2px(add_x1);\
  2007.    userdraw_y[s] = y2px(add_y1);\
  2008.    userdraw_x[s+1] = x2px(add_x2);\
  2009.    userdraw_y[s+1] = y2px(add_y2);\
  2010.  }\
  2011.  else\
  2012.  {\
  2013.   userdraw_x[0] = x2px(add_x1);\
  2014.   userdraw_y[0] = y2px(add_y1);\
  2015.   userdraw_x[1] = x2px(add_x2);\
  2016.   userdraw_y[1] = y2px(add_y2);\
  2017.  };\
  2018.  context_userdraw.clearRect(0,0,xsize,ysize);\
  2019.  draw_segments(context_userdraw,userdraw_x,userdraw_y,line_width,stroke_color,stroke_opacity,use_dashed,dashtype0,dashtype1);\
  2020. };\
  2021. return;\
  2022. };",num);
  2023. }
  2024.  
  2025. /* draw polygon via 2 textarea's x/y : split into lines ! */
  2026. void add_textarea_polygon(FILE *js_include_file){
  2027. fprintf(js_include_file,"\n<!-- begin polygon via 2 textareas x / y -->\n\
  2028. function user_redraw(t){\
  2029. var lu = userdraw_x.length;\
  2030. if( t == -1 && lu > 0){\
  2031.  if( lu < 3 ){\
  2032.   userdraw_x = [];\
  2033.   userdraw_y = [];\
  2034.  }\
  2035.  else\
  2036.  {\
  2037.  userdraw_x.splice(lu-1,1);\
  2038.  userdraw_y.splice(lu-1,1);\
  2039.  };\
  2040.  context_userdraw.clearRect(0,0,xsize,ysize);\
  2041.  draw_paths(context_userdraw,userdraw_x,userdraw_y,line_width,closed_path,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,use_rotate,angle,0,[1,0,0,1,0,0]);\
  2042.  cnt = 1; return;\
  2043. };\
  2044. var add_x_values = (document.getElementById(\"userinput_x\").value).split('\\n');\
  2045. var add_y_values = (document.getElementById(\"userinput_y\").value).split('\\n');\
  2046. var lx = add_x_values.length;\
  2047. var ly = add_y_values.length;\
  2048. if( lx != ly){ if(lx > ly){alert(\'x/y mismatch\\ntoo few y-values\');return}else{alert(\'x/y mismatch\\ntoo many y-values\');return}};\
  2049. var add_x;var add_y;\
  2050. for(var p = 0 ; p < lx ; p++){\
  2051.  add_x = safe_eval( add_x_values[p] );\
  2052.  add_y = safe_eval( add_y_values[p] );\
  2053.  if( add_x == null || add_y == null ){return;};\
  2054.  userdraw_x[lu+p] = x2px(add_x);\
  2055.  userdraw_y[lu+p] = y2px(add_y);\
  2056.  if(p>100){alert(\"hmmmm\");return;};\
  2057. };\
  2058. draw_paths(context_userdraw,userdraw_x,userdraw_y,line_width,closed_path,stroke_color,stroke_opacity,use_filled,fill_color,fill_opacity,use_dashed,dashtype0,use_rotate,angle,0,[1,0,0,1,0,0]);\
  2059. cnt = 1;\
  2060. return;\
  2061. };");
  2062. }
  2063.  
  2064. void add_jsplot(FILE *js_include_file,int canvas_root_id){
  2065. fprintf(js_include_file,"\n<!-- begin jsplot() -->\n\
  2066. var jsplot = function(canvas_type,f,linewidth,color,opacity,use_dashed,dashtype0,dashtype1){\
  2067. var obj;\
  2068. if( document.getElementById(\"wims_canvas%d\"+canvas_type) ){\
  2069.  obj = document.getElementById(\"wims_canvas%d\"+canvas_type);\
  2070. }\
  2071. else\
  2072. {\
  2073.  obj = create_canvas%d(canvas_type,xsize,ysize);\
  2074. };\
  2075. var ctx = obj.getContext(\"2d\");\
  2076. ctx.clearRect(0,0,xsize,ysize);\
  2077. function eval_jsmath(x){return parseFloat(eval(fun));};\
  2078. var fun = to_js_math(f);if(fun == null){alert(\"hmmm...\"+f);return;};\
  2079. ctx.lineWidth = linewidth;\
  2080. ctx.strokeStyle=\"rgba(\"+color+\",\"+opacity+\")\";\
  2081. if(use_dashed == 1){if(ctx.setLineDash){ctx.setLineDash([dashtype0,dashtype1]);}else{ctx.mozDash =[dashtype0,dashtype1];}};\
  2082. var y1;var x1;var y2;var x2;\
  2083. ctx.beginPath();\
  2084. for(var p=0 ; p<xsize;p++){\
  2085.  x1 = px2x(p);\
  2086.  y1 = y2px(parseFloat(eval_jsmath(x1)));\
  2087.  x2 = px2x(p+1);\
  2088.  y2 = y2px(parseFloat(eval_jsmath(x2)));\
  2089.  if(Math.abs(y2-y1) < ysize ){\
  2090.    ctx.moveTo(p,y1);\
  2091.    ctx.lineTo(p+1,y2);\
  2092.  };\
  2093. };\
  2094. ctx.closePath();\
  2095. ctx.stroke();\
  2096. };",canvas_root_id,canvas_root_id,canvas_root_id);
  2097. }
  2098.  
  2099. void add_to_js_math(FILE *js_include_file){
  2100. fprintf(js_include_file,"\n<!-- begin to_js_math() -->\n\
  2101. var to_js_math = function(math_fun){\
  2102. var infun=[\"sqrt\",\"^\",\"asin\",\"acos\",\"atan\",\"log\",\"pi\",\"abs\",\"sin\",\"cos\",\"tan\",\"e\"];\
  2103. var outfun=[\"Math.sqrt\",\"Math.pow\",\"Math.asin\",\"Math.acos\",\"Math.atan\",\"Math.log\",\"(3.14159265358979)\",\"Math.abs\",\"Math.sin\",\"Math.cos\",\"Math.tan\",\"(2.718281828459045)\"];\
  2104. var len = infun.length;var in_fun;var In_Fun;var out_fun;var w_cnt;\
  2105. for(var p=0 ; p < len ; p++){\
  2106.  in_fun = infun[p];In_Fun = in_fun.toUpperCase();out_fun = outfun[p];w_cnt=0;\
  2107.  if(math_fun.indexOf(in_fun) != -1){\
  2108.   if(in_fun == \"^\"){\
  2109.    var tab = [];var small_trick = \"___small_trick___\";\
  2110.    while (math_fun.indexOf(\"(\") != -1){\
  2111.     math_fun = math_fun.replace(/(\\([^\\(\\)]*\\))/g, function(m, t){tab.push(t);return (small_trick + (tab.length - 1));});\
  2112.     w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  2113.    };\
  2114.    tab.push(math_fun);w_cnt = 0;math_fun = small_trick + (tab.length - 1);\
  2115.    while (math_fun.indexOf(small_trick) != -1){\
  2116.     math_fun = math_fun.replace(new RegExp(small_trick + \"(\\\\d+)\", \"g\"), function(m, d){return tab[d].replace(/(\\w*)\\^(\\w*)/g, out_fun+\"($1,$2)\");});\
  2117.     w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  2118.    };\
  2119.   }\
  2120.   else\
  2121.   {\
  2122.    while( math_fun.indexOf(in_fun) != -1 ){\
  2123.     math_fun = math_fun.replace(in_fun,out_fun);\
  2124.     math_fun = math_fun.replace(in_fun,In_Fun);\
  2125.     w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  2126.    };\
  2127.   };\
  2128.  };\
  2129. };\
  2130. for(var p=0 ; p < len ; p++){\
  2131.  in_fun = infun[p];In_Fun = in_fun.toUpperCase();w_cnt = 0;\
  2132.  if(math_fun.indexOf(In_Fun) != -1 ){\
  2133.   while(math_fun.indexOf(In_Fun) != -1){\
  2134.    math_fun = math_fun.replace(In_Fun,in_fun);\
  2135.    w_cnt++;if(w_cnt>1000){alert(\"hmmm \"+math_fun+\" ?\\nUse command plot for more complex math functions...\");return null;};\
  2136.   };\
  2137.  };\
  2138. };\
  2139. return math_fun;\
  2140. };\n");
  2141. }
  2142.  
  2143. void add_clear_button(FILE *js_include_file,int canvas_root_id,char *input_style,char *button_text){
  2144. fprintf(js_include_file,"\n<!-- add clear button -->\n\
  2145. clear_draw_area = function(){\
  2146. if(confirm(\"remove all drawings ? \")){\n\
  2147.  var canvas_userdraw = create_canvas%d(%d,xsize,ysize);\n\
  2148.  var context_userdraw = canvas_userdraw.getContext(\"2d\");\n\
  2149.  context_userdraw.clearRect(0,0,xsize,ysize);\n\
  2150.  userdraw_x = [];userdraw_y = [];userdraw_radius = [];\n\
  2151.  return;\n\
  2152. };\n\
  2153. };\n\
  2154. function add_clear_button(){\n\
  2155. var tooltip_placeholder_div = document.getElementById(\"tooltip_placeholder_div%d\");\
  2156. var button = document.createElement('input');\n\
  2157. button.type = \"button\";\n\
  2158. button.style = \"%s\";\n\
  2159. button.value = \"%s\";\n\
  2160. button.setAttribute(\"onclick\",\"clear_draw_area()\");\n\
  2161. tooltip_placeholder_div.appendChild(button);\n\
  2162. };\
  2163. add_clear_button();\n\
  2164. ",canvas_root_id,DRAW_CANVAS,canvas_root_id,input_style,button_text);
  2165. }
  2166.  
  2167.  
  2168. /* GNU libmatheval library for evaluating mathematical functions. */
  2169. char *eval(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int plotsteps,int precision){
  2170.     void *f;
  2171.     double x;
  2172.     double y;
  2173.     int xv;
  2174.     int i = 0;
  2175.     int xstep =(int)(xsize/plotsteps);
  2176.     if( xstep == 0 ){xstep = 1;}
  2177.     double a = (xmax - xmin)/xsize;
  2178.     f = eval_create(fun);
  2179.     assert (f);
  2180.     if( f == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;}
  2181.     /* we supply the true x/y values...draw_curve() will convert these (x:y) to pixels : used for pan/scale */
  2182.     double xydata[MAX_BUFFER+1];/* hmmm */
  2183.     int lim_ymin =(int)( ymin - 4*abs(ymin));
  2184.     int lim_ymax =(int)( ymax + 4*abs(ymax));
  2185.     for ( xv = 0 ;xv < xsize ; xv = xv+xstep ){
  2186.         x = (double) (xv*a + xmin);
  2187.         if( i < MAX_BUFFER - 2){
  2188.             y = eval_x(f, x);
  2189.             if(y < lim_ymax && y > lim_ymin ){
  2190.                 xydata[i++] = x;
  2191.                 xydata[i++] = y;
  2192.             }
  2193.         }
  2194.         else
  2195.         {
  2196.             canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps or some other means to reduce the amount of data... ");
  2197.         }
  2198.     }
  2199.     eval_destroy(f);
  2200.     return double_xy2js_array(xydata,i,find_number_of_digits(precision));
  2201. }
  2202. /* plot a very primitive (!) levelcurve : not to be compared with "flydraw levelcurve" */
  2203. char *eval_levelcurve(int xsize,int ysize,char *fun,double xmin,double xmax,double ymin,double ymax,int plotsteps,int precision,double level){
  2204.     void *f = eval_create(fun);
  2205.     assert (f);
  2206.     if( f == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;}
  2207.     double a = (double)((xmax - xmin)/plotsteps);
  2208.     double b = (double)((ymax - ymin)/plotsteps);
  2209.     double x;double y;double diff;
  2210.     double xydata[MAX_BUFFER+1];
  2211.     int i = 0;
  2212.     ymin = ymin - 1;
  2213.     xmin = xmin - 1;
  2214.     ymax = ymax + 1;
  2215.     xmax = xmax + 1;
  2216.     for( x = xmin ;x < xmax ; x = x + a ){
  2217.         for ( y = ymin ;y < ymax ; y = y + b ){
  2218.             if( i < MAX_BUFFER - 2){
  2219.                 diff = level - eval_x_y(f, x,y);
  2220.                 if(diff < 0.1 && diff > -0.1){
  2221.                     xydata[i++] = x;
  2222.                     xydata[i++] = y;
  2223.                 }
  2224.             }
  2225.             else
  2226.             {
  2227.                 canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps, decrease image size...\nor some other means to reduce the amount of data... ");
  2228.             }
  2229.         }
  2230.     }
  2231.     eval_destroy(f);
  2232.     return double_xy2js_array(xydata,i,find_number_of_digits(precision));
  2233. }
  2234.  
  2235. /* plot parametric function */
  2236. char *eval_parametric(int xsize,int ysize,char *fun1,char* fun2,double xmin,double xmax,double ymin,double ymax,        
  2237.  double tmin,double tmax,int plotsteps,int precision){
  2238.     void *fx;
  2239.     void *fy;
  2240.     double t;
  2241.     int i = 0;
  2242.     double tstep = (tmax-tmin)/plotsteps;
  2243.     if( tstep == 0 ){canvas_error("zero step for t variable : reduce plotsteps or inrease trange");}
  2244.     fx = eval_create(fun1);
  2245.     fy = eval_create(fun2);
  2246.     assert(fx);
  2247.     assert(fy);
  2248.     if( fx == NULL || fy == NULL ){canvas_error("I'm having trouble parsing your \"expression\" ") ;}
  2249.     /* we supply the true x/y values...draw_curve() will convert these (x:y) to pixels : used for pan/scale */
  2250.     double xydata[MAX_BUFFER+1];/* hmmm */
  2251.     double x; /* real x-values */
  2252.     double y; /* real y-values */
  2253.     int lim_ymin =(int)( ymin - 4*abs(ymin));
  2254.     int lim_ymax =(int)( ymax + 4*abs(ymax));
  2255.     for( t = tmin ;t <= tmax ; t = t + tstep ){
  2256.         if( i < MAX_BUFFER - 2 ){
  2257.             y = eval_t(fy, t);
  2258.             if(y > lim_ymin && y < lim_ymax){
  2259.                 x = eval_t(fx, t);
  2260.                 xydata[i++] = x;
  2261.                 xydata[i++] = y;
  2262.             }
  2263.         }
  2264.         else
  2265.         {
  2266.             canvas_error("\nYour curve plotting produces too many data \n Use less plotsteps or some other means to reduce the amount of data... ");
  2267.         }
  2268.     }
  2269.     eval_destroy(fx);
  2270.     eval_destroy(fy);
  2271.     return double_xy2js_array(xydata,i,find_number_of_digits(precision));
  2272. }
  2273.  
  2274. char *double_xy2js_array(double xy[],int len,int decimals){
  2275.  /*
  2276.     1,2,3,4,5,6,7,8 --> [1,3,5,7],[2,4,6,8]
  2277.     int xy[] is already checked for errors or overflow in "get_real()"
  2278.     just to be sure we double check the size of "temp"
  2279. */
  2280.     char temp[2*MAX_BUFFER], *string;
  2281.     char *tmp = my_newmem(16);/* <= 9999999999999999  */
  2282.     memset(temp,'\0',2*MAX_BUFFER);/* clear memory */
  2283.     int i;int space_left;
  2284.     temp[0] = '[';/* start js-array */
  2285.     for(i = 0; i < len;i = i + 2){ /*  x_points[] */
  2286.         if(i == len - 2){sprintf(tmp, "%.*f",decimals, xy[i]);}else{sprintf(tmp, "%.*f,",decimals,xy[i]);}
  2287.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  2288.         if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce your image size or plotsteps ");}
  2289.     }
  2290.     strncat(temp,"],[",3); /* close js x_values array and start new */
  2291.     for(i = 1; i < len;i = i + 2){ /* y_points */
  2292.         if(i == len - 1){ sprintf(tmp, "%.*f",decimals,xy[i]);}else{sprintf(tmp, "%.*f,",decimals,xy[i]);}
  2293.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  2294.         if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce your image size or plotsteps");}
  2295.     }
  2296.     strncat(temp,"]",1);
  2297.     string=(char *)my_newmem(sizeof(temp));
  2298.     snprintf(string,sizeof(temp),"%s",temp);
  2299.     return string;
  2300. }
  2301.  
  2302. char *xy2js_array(int xy[],int len){
  2303.  /*
  2304.     1,2,3,4,5,6,7,8 --> [1,3,5,7],[2,4,6,8]
  2305.     int xy[] is already checked for errors or overflow in "get_real()"
  2306.     just to be sure we double check the size of "temp"
  2307. */
  2308.     char temp[MAX_BUFFER], *string;
  2309.     char *tmp = my_newmem(16);/* <= 9999999999999999  */
  2310.     memset(temp,'\0',MAX_BUFFER);/* clear memory */
  2311.     int i;int space_left;
  2312.     temp[0] = '[';/* start js-array */
  2313.     for(i = 0; i < len;i = i + 2){ /*  x_points[] */
  2314.         if(i == len - 2){sprintf(tmp, "%d", xy[i]);}else{sprintf(tmp, "%d,", xy[i]);}
  2315.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  2316.         if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce image size or plotsteps ");}
  2317.     }
  2318.     strncat(temp,"],[",3); /* close js x_values array and start new */
  2319.     for(i = 1; i < len;i = i + 2){ /* y_points */
  2320.         if(i == len - 1){ sprintf(tmp, "%d", xy[i]);}else{sprintf(tmp, "%d,", xy[i]);}
  2321.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  2322.         if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data\nreduce image size or plotsteps \n");}
  2323.     }
  2324.     strncat(temp,"]",1);
  2325.     string=(char *)my_newmem(sizeof(temp));
  2326.     snprintf(string,sizeof(temp),"%s",temp);
  2327.     return string;
  2328. }
  2329.  
  2330. char *data2js_array(int data[],int len){
  2331.  /*
  2332.     1,2,3,4,5,6,7,8 --> [1,2,3,4,5,6,7,8]
  2333.     int data[] is already checked for errors or overflow in "get_real()"
  2334.     just to be sure we double check the size of "temp"
  2335. */
  2336.     char temp[MAX_BUFFER], *string;
  2337.     char *tmp = my_newmem(16);/* <= 9999999999999999  */
  2338.     memset(temp,'\0',MAX_BUFFER);/* clear memory */
  2339.     int i;int space_left;
  2340.     temp[0] = '[';/* start js-array */
  2341.     for(i = 0; i < len; i++){
  2342.         if(i == len - 1){sprintf(tmp, "%d", data[i]);}else{sprintf(tmp, "%d,", data[i]);}
  2343.         space_left = (int) (sizeof(temp) - strlen(temp) - strlen(tmp) - 1);
  2344.         if( space_left > 0 ){ strncat(temp,tmp,space_left - 1);}else{canvas_error("can not parse integer to js-array:\nYour curve plotting produces too many data \nreduce image size or plotsteps ");}
  2345.     }
  2346.     strncat(temp,"]",1);
  2347.     string=(char *)my_newmem(sizeof(temp));
  2348.     snprintf(string,sizeof(temp),"%s",temp);
  2349.     return string;
  2350. }
  2351.  
  2352.  
  2353. void *my_newmem(size_t size){
  2354.         void    *p;
  2355.         if ((p = malloc(size +1)) == NULL){canvas_error("canvasdraw: ran out of memory\n");}
  2356.         return p;
  2357. }
  2358.  
  2359. int find_number_of_digits(int i){
  2360.     if(i < 0 ){ i = -1*i;}
  2361.     int digits = 0;
  2362.     while ( i > 0){
  2363.         digits++;
  2364.         i = i/10;
  2365.     }
  2366.     return digits;
  2367. }
  2368. /* change this when colornames / numbers are added to struct */
  2369. #define NUMBER_OF_COLORNAMES    140
  2370. struct {
  2371.     char *hex;
  2372.     char *name;
  2373.     char *rgb;
  2374. } colors[]={
  2375.  {"#FF0000","red","255,0,0"},
  2376.  {"#00FF00","lime","0,255,0"},
  2377.  {"#0000FF","blue","0,0,255"},
  2378.  {"#FFA500","orange","255,165,0"},
  2379.  {"#E9967A","darksalmon","233,150,122"},
  2380.  {"#F0FFFF","azure","240,255,255"},
  2381.  {"#CD5C5C","indianred","205,92,92"},
  2382.  {"#E0FFFF","lightcyan","224,255,255"},
  2383.  {"#FFE4E1","mistyrose","255,228,225"},
  2384.  {"#DC143C","crimson","220,20,60"},
  2385.  {"#FFC0CB","pink","255,192,203"},
  2386.  {"#FFD700","gold","255,215,0"},
  2387.  {"#E6E6FA","lavender","230,230,250"},
  2388.  {"#808080","gray","128,128,128"},
  2389.  {"#F0F8FF","aliceblue","240,248,255"},
  2390.  {"#C71585","mediumvioletred","199,21,133"},
  2391.  {"#FFF0F5","lavenderblush","255,240,245"},
  2392.  {"#DAA520","goldenrod","218,165,32"},
  2393.  {"#FFB6C1","lightpink","255,182,193"},
  2394.  {"#00FFFF","aqua","0,255,255"},
  2395.  {"#FF69B4","hotpink","255,105,180"},
  2396.  {"#00FFFF","cyan","0,255,255"},
  2397.  {"#FF1493","deeppink","255,20,147"},
  2398.  {"#7FFFD4","aquamarine","127,255,212"},
  2399.  {"#FA8072","salmon","250,128,114"},
  2400.  {"#DEB887","burlywood","222,184,135"},
  2401.  {"#DB7093","palevioletred","219,112,147"},
  2402.  {"#D2B48C","tan","210,180,140"},
  2403.  {"#BDB76B","darkkhaki","189,183,107"},
  2404.  {"#B22222","firebrick","178,34,34"},
  2405.  {"#FF4500","orangered","255,69,0"},
  2406.  {"#8B4513","saddlebrown","139,69,19"},
  2407.  {"#FF8C00","darkorange","255,140,0"},
  2408.  {"#FFFFE0","lightyellow","255,255,224"},
  2409.  {"#FFFF00","yellow","255,255,0"},
  2410.  {"#FFFACD","lemonchiffon","255,250,205"},
  2411.  {"#F5F5DC","beige","245,245,220"},
  2412.  {"#FFEFD5","papayawhip","255,239,213"},
  2413.  {"#FAFAD2","lightgoldenrodyellow","250,250,210"},
  2414.  {"#FFE4B5","moccasin","255,228,181"},
  2415.  {"#B8860B","darkgoldenrod","184,134,11"},
  2416.  {"#FFF8DC","cornsilk","255,248,220"},
  2417.  {"#FFEBCD","blanchedalmond","255,235,205"},
  2418.  {"#FFE4C4","bisque","255,228,196"},
  2419.  {"#FFDEAD","navajowhite","255,222,173"},
  2420.  {"#F5DEB3","wheat","245,222,179"},
  2421.  {"#CD853F","peru","205,133,63"},
  2422.  {"#D2691E","chocolate","210,105,30"},
  2423.  {"#A0522D","sienna","160,82,45"},
  2424.  {"#A52A2A","brown","165,42,42"},
  2425.  {"#BC8F8F","rosybrown","188,143,143"},
  2426.  {"#F08080","lightcoral","240,128,128"},
  2427.  {"#FFA07A","lightsalmon","255,160,122"},
  2428.  {"#8B0000","darkred","139,0,0"},
  2429.  {"#800000","maroon","128,0,0"},
  2430.  {"#FAA460","sandybrown","250,164,96"},
  2431.  {"#FF7F50","coral","255,127,80"},
  2432.  {"#FF6347","tomato","255,99,71"},
  2433.  {"#FFDAB9","peachpuff","255,218,185"},
  2434.  {"#EEE8AA","palegoldenrod","238,232,170"},
  2435.  {"#F0E68C","khaki","240,230,140"},
  2436.  {"#D8BFD8","thistle","216,191,216"},
  2437.  {"#DDA0DD","plum","221,160,221"},
  2438.  {"#FF00FF","fuchsia","255,0,255"},
  2439.  {"#FF00FF","magenta","255,0,255"},
  2440.  {"#EE82EE","violet","238,130,238"},
  2441.  {"#DA70D6","orchid","218,112,214"},
  2442.  {"#BA55D3","mediumorchid","186,85,211"},
  2443.  {"#9370DB","mediumpurple","147,112,219"},
  2444.  {"#8A2BE2","blueviolet","138,43,226"},
  2445.  {"#9400D3","darkviolet","148,0,211"},
  2446.  {"#9932CC","darkorchid","153,50,204"},
  2447.  {"#8B008B","darkmagenta","139,0,139"},
  2448.  {"#800080","purple","128,0,128"},
  2449.  {"#4B0082","indigo","75,0,130"},
  2450.  {"#483D8B","darkslateblue","72,61,139"},
  2451.  {"#6A5ACD","slateblue","106,90,205"},
  2452.  {"#7B68EE","mediumslateblue","123,104,238"},
  2453.  {"#98FB98","palegreen","152,251,152"},
  2454.  {"#ADFF2F","greenyellow","173,255,47"},
  2455.  {"#7FFF00","chartreuse","127,255,0"},
  2456.  {"#7CFC00","lawngreen","124,252,0"},
  2457.  {"#00FF7F","springgreen","0,255,127"},
  2458.  {"#00FA9A","mediumspringgreen","0,250,154"},
  2459.  {"#90EE90","lightgreen","144,238,144"},
  2460.  {"#32CD32","limegreen","50,205,50"},
  2461.  {"#3CB371","mediumseagreen","60,179,113"},
  2462.  {"#2E8B57","seagreen","46,139,87"},
  2463.  {"#228B22","forestgreen","34,139,34"},
  2464.  {"#008000","green","0,128,0"},
  2465.  {"#006400","darkgreen","0,100,0"},
  2466.  {"#9ACD32","yellowgreen","154,205,50"},
  2467.  {"#6B8E23","olivedrab","107,142,35"},
  2468.  {"#808000","olive","128,128,0"},
  2469.  {"#556B2F","darkolivegreen","85,107,47"},
  2470.  {"#8FBC8F","darkseagreen","143,188,143"},
  2471.  {"#66CDAA","mediumaquamarine","102,205,170"},
  2472.  {"#20B2AA","lightseagreen","32,178,170"},
  2473.  {"#008B8B","darkcyan","0,139,139"},
  2474.  {"#008080","teal","0,128,128"},
  2475.  {"#AFEEEE","paleturquoise","175,238,238"},
  2476.  {"#40E0D0","turquoise","64,224,208"},
  2477.  {"#48D1CC","mediumturquoise","72,209,204"},
  2478.  {"#00CED1","darkturquoise","0,206,209"},
  2479.  {"#5F9EA0","cadetblue","95,158,160"},
  2480.  {"#4682B4","steelblue","70,130,180"},
  2481.  {"#B0C4DE","lightsteelblue","176,196,222"},
  2482.  {"#B0E0E6","powderblue","176,224,230"},
  2483.  {"#ADD8E6","lightblue","173,216,230"},
  2484.  {"#87CEEB","skyblue","135,206,235"},
  2485.  {"#87CEFA","lightskyblue","135,206,250"},
  2486.  {"#00BFFF","deepskyblue","0,191,255"},
  2487.  {"#1E90FF","dodgerblue","30,144,255"},
  2488.  {"#6495ED","cornflowerblue","100,149,237"},
  2489.  {"#4169E1","royalblue","65,105,225"},
  2490.  {"#0000CD","mediumblue","0,0,205"},
  2491.  {"#00008B","darkblue","0,0,139"},
  2492.  {"#000080","navy","0,0,128"},
  2493.  {"#191970","midnightblue","25,25,112"},
  2494.  {"#DCDCDC","gainsboro","220,220,220"},
  2495.  {"#D3D3D3","lightgrey","211,211,211"},
  2496.  {"#808080","grey","128,128,128"},
  2497.  {"#C0C0C0","silver","192,192,192"},
  2498.  {"#A9A9A9","darkgray","169,169,169"},
  2499.  {"#778899","lightslategray","119,136,153"},
  2500.  {"#708090","slategray","112,128,144"},
  2501.  {"#696969","dimgray","105,105,105"},
  2502.  {"#2F4F4F","darkslategray","47,79,79"},
  2503.  {"#000000","black","0,0,0"},
  2504.  {"#F5FFFA","mintcream","245,255,250"},
  2505.  {"#FFFFFF","white","255,255,255"},
  2506.  {"#F0FFF0","honeydew","240,255,240"},
  2507.  {"#F5F5F5","whitesmoke","245,245,245"},
  2508.  {"#F8F8FF","ghostwhite","248,248,255"},
  2509.  {"#FFFFF0","ivory","255,255,240"},
  2510.  {"#FFFAFA","snow","255,250,250"},
  2511.  {"#FFFAF0","floralwhite","255,250,240"},
  2512.  {"#FFF5EE","seashell","255,245,238"},
  2513.  {"#FDF5E6","oldlace","253,245,230"},
  2514.  {"#FAF0E6","linen","250,240,230"},
  2515.  {"#FAEBD7","antiquewhite","250,235,215"},
  2516.  };
  2517.  
  2518.  
  2519. void add_drag_code(FILE *js_include_file,int canvas_cnt,int canvas_root_id){
  2520. /* in drag& drop / onclick library:
  2521.     obj_type = 1 == rect
  2522.     obj_type = 2 == point / points (do not scale with zoom)
  2523.     obj_type = 3 == ellipse
  2524.     obj_type = 4 == polyline / segment /line / vline / hline
  2525.     obj_type = 5 == closed path (polygon)
  2526.     obj_type = 6 == roundrect
  2527.     obj_type = 7 == crosshair / crosshairs
  2528.     obj_type = 8 == arrow
  2529.     obj_type = 9 == curve
  2530.     obj_type = 10== arrow2
  2531.     obj_type = 11== parallel  (no drag or onclick)
  2532.     obj_type = 12== arc : radius is in pixels , so no zooming in/out
  2533.     obj_type = 13== circle (will scale on zoom)
  2534.     obj_type = 14== text (will not scale or pan on zoom)
  2535.     obj_type = 15== animated point on curve
  2536.     obj_type = 16== pixels
  2537.     obj_type = 17== new arc [command angle] :radius in x-range, so will scale on zooming in/out
  2538. */
  2539. fprintf(js_include_file,"\n<!-- begin drag_drop_onclick shape library -->\n\
  2540. if( typeof dragdrop_precision == 'undefined' ){var dragdrop_precision = 100;};\
  2541. function Shape(click_cnt,onclick,direction,type,x,y,w,h,line_width,stroke_color,stroke_opacity,fill_color,fill_opacity,use_filled,use_dashed,dashtype0,dashtype1,use_rotate,angle,text,font_size,font_family,use_affine,affine_matrix,slider,slider_cnt){\
  2542. this.slider = slider || 0;\
  2543. this.slider_cnt = slider_cnt || 0;\
  2544. this.text = text || 0;\
  2545. this.font_size = font_size || 12;\
  2546. if( font_family.indexOf('px') > 0 ){this.font_family = font_family;}else{this.font_family = this.font_size+'px Ariel';};\
  2547. this.use_rotate = use_rotate || 0;\
  2548. this.angle = angle*(Math.PI/180) || 0;\
  2549. this.use_affine = use_affine || 0;\
  2550. this.affine_matrix = affine_matrix || [1,0,0,1,0,0];\
  2551. this.click_cnt = click_cnt || 1;\
  2552. this.onclick = onclick || 0;\
  2553. this.direction = direction || 0;\
  2554. this.type = type || 1;\
  2555. this.xorg = x;\
  2556. this.yorg = y;\
  2557. this.x = [x.length];\
  2558. this.y = [x.length];\
  2559. this.w = [x.length];\
  2560. this.h = [x.length];\
  2561. for(var p=0;p<x.length;p++){\
  2562.  this.x[p] = x2px(x[p]-xstart);\
  2563.  this.y[p] = y2px(y[p]-ystart);\
  2564.  if( p > w.length){\
  2565.    this.w[p] = w[0];\
  2566.    this.h[p] = h[0];\
  2567.  }\
  2568.  else\
  2569.  {\
  2570.    this.w[p] = w[p];\
  2571.    this.h[p] = h[p];\
  2572.  }\
  2573. };\
  2574. this.line_width = line_width || 30;\
  2575. this.stroke_opacity = stroke_opacity || 1.0;\
  2576. this.stroke_color = \"rgba(\"+stroke_color+\",\"+stroke_opacity+\")\" || '#FF0000';\
  2577. this.fill_opacity = fill_opacity || 1.0;\
  2578. this.fill_color = \"rgba(\"+fill_color+\",\"+fill_opacity+\")\" || '#FF0000';\
  2579. this.use_filled = use_filled || 0;\
  2580. this.use_dashed = use_dashed || 0;\
  2581. this.dashtype0 = dashtype0 || 4;\
  2582. this.dashtype1 = dashtype1 || 4;\
  2583. };\
  2584. Shape.prototype.draw = function(ctx)\
  2585. {\
  2586. ctx.lineWidth = this.line_width;\
  2587. ctx.strokeStyle = this.stroke_color;\
  2588. ctx.fillStyle = this.fill_color;\
  2589. ctx.lineJoin = \"round\";\
  2590. ctx.save();\
  2591. if(this.use_rotate == 1){\
  2592.  var x_c = x2px(0);\
  2593.  var y_c = y2px(0);\
  2594.  ctx.translate(x_c,y_c);\
  2595.  ctx.rotate(this.angle);ctx.translate(-x_c,-y_c);\
  2596. };\
  2597. if( this.use_affine == 1 ){\
  2598.  ctx.setTransform(this.affine_matrix[0],this.affine_matrix[1],this.affine_matrix[2],this.affine_matrix[3],this.affine_matrix[4],this.affine_matrix[5]);\
  2599. };\
  2600. ctx.beginPath();\
  2601. switch(this.type){\
  2602.  case 1: ctx.rect(this.x[0], this.y[0], this.x[1]-this.x[0], this.y[2] - this.y[0]);break;\
  2603.  case 2: ctx.arc(this.x[0],this.y[0],this.w[0],0,2*Math.PI,false);break;\
  2604.  case 3: ctx.save();var w = 0.5*(scale_x_radius(this.w[0]));var h = 0.5*(scale_y_radius(this.h[0]));ctx.scale(1,h/w);ctx.beginPath();ctx.arc(this.x[0], w/h*this.y[0], w, 0, 2 * Math.PI);if(this.use_filled == 1){ ctx.fillStyle = this.fill_color; ctx.fill(); };ctx.closePath();ctx.stroke();ctx.restore();break;\
  2605.  case 4: for(var p = 0; p < this.x.length - 1;p++){ctx.moveTo(this.x[p], this.y[p]);ctx.lineTo(this.x[p+1],this.y[p+1]);};break;\
  2606.  case 5: ctx.moveTo(this.x[0], this.y[0]);for(var p = 1; p < this.x.length;p++){ctx.lineTo(this.x[p],this.y[p]);};ctx.lineTo(this.x[0],this.y[0]);break;\
  2607.  case 6: var w = this.x[1] - this.x[0];var h = this.y[1] - this.y[0];var r = this.w[0];ctx.beginPath();ctx.moveTo(this.x[0] + r, this.y[0]);ctx.lineTo(this.x[0] + w - r, this.y[0]);ctx.quadraticCurveTo(this.x[0] + w, this.y[0], this.x[0] + w, this.y[0] + r);ctx.lineTo(this.x[0] + w, this.y[0] + h - r);ctx.quadraticCurveTo(this.x[0] + w, this.y[0] + h, this.x[0] + w - r, this.y[0] + h);ctx.lineTo(this.x[0] + r, this.y[0] + h);ctx.quadraticCurveTo(this.x[0], this.y[0] + h, this.x[0], this.y[0] + h - r);ctx.lineTo(this.x[0], this.y[0] + r);ctx.quadraticCurveTo(this.x[0], this.y[0], this.x[0] + r, this.y[0]);ctx.closePath();break;\
  2608.  case 7: ctx.moveTo(this.x[0]-this.w[0],this.y[0]-this.h[0]);ctx.lineTo(this.x[0]+this.w[0],this.y[0]+this.h[0]);ctx.moveTo(this.x[0]-this.w[0],this.y[0]+this.h[0]);ctx.lineTo(this.x[0]+this.w[0],this.y[0]-this.h[0]);break;\
  2609.  case 8: var dx;var dy;var len;var arrow_head = this.w[0];for(var p = 0; p < this.x.length - 1;p++){ctx.save();if(this.use_dashed == 1 ){if( ctx.setLineDash ){ ctx.setLineDash([this.dashtype0,this.dashtype1]);}else{ ctx.mozDash = [this.dashtype0,this.dashtype1];};};dx = this.x[p+1] - this.x[p];dy = this.y[p+1] - this.y[p];len = Math.sqrt(dx*dx+dy*dy);ctx.translate(this.x[p+1],this.y[p+1]);ctx.rotate(Math.atan2(dy,dx));ctx.lineCap = \"round\";ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(-len,0);ctx.closePath();ctx.stroke();ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(-1*arrow_head,-0.5*arrow_head);ctx.lineTo(-1*arrow_head, 0.5*arrow_head);ctx.closePath();ctx.fill();};break;\
  2610.  case 9: ctx.moveTo(this.x[0], this.y[0]);for(var p = 1; p < this.x.length - 1;p++){if( Math.abs(this.y[p] - this.y[p-1]) < ysize && Math.abs(this.y[p+1] - this.y[p]) < ysize ){ctx.lineTo(this.x[p],this.y[p]);}else{ctx.moveTo(this.x[p],this.y[p]);};};break;\
  2611.  case 10: var dx;var dy;var len;ctx.save();if(this.use_dashed == 1 ){if( ctx.setLineDash ){ ctx.setLineDash([this.dashtype0,this.dashtype1]);}else{ ctx.mozDash = [this.dashtype0,this.dashtype1];};};dx = this.x[1] - this.x[0];dy = this.y[1] - this.y[0];len = Math.sqrt(dx*dx+dy*dy);ctx.translate(this.x[1],this.y[1]);ctx.rotate(Math.atan2(dy,dx));ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(-len,0);ctx.closePath();ctx.stroke();ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(-1*this.w[0],-1*this.w[0]);ctx.lineTo(-1*this.w[0],this.w[0]);ctx.closePath();ctx.lineCap = \"round\";ctx.fill();ctx.restore();ctx.save();ctx.translate(this.x[0],this.y[0]);ctx.rotate(Math.atan2(dy,dx));ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(this.w[0],-0.5*this.w[0]);ctx.lineTo(this.w[0], 0.5*this.w[0]);ctx.closePath();ctx.lineCap = \"round\";ctx.fill(); break;\
  2612.  case 11: var x1 = this.x[0];var y1 = this.y[0];var x2 = this.x[1];var y2 = this.y[1];var dx = this.x[2];var dy = this.y[2];var n  = this.w[0];for(var p = 0 ; p < n ; p++ ){ctx.beginPath();ctx.moveTo(x1,y1);ctx.lineTo(x2,y2);ctx.stroke();x1 = x1 + dx;y1 = y1 + dy;x2 = x2 + dx;y2 = y2 + dy;ctx.closePath();};break;\
  2613.  case 12: ctx.save();var start;var end;if(this.h[0] < this.h[1]){start = this.h[0];end = this.h[1]}else{start = this.h[1];end = this.h[0];};start=360-start;end=360-end;var r = this.w[0];ctx.arc(this.x[0], this.y[0], r, start*(Math.PI / 180), end*(Math.PI / 180),true);if(this.use_filled){ctx.lineTo(this.x[0],this.y[0]);ctx.fill();};ctx.restore();break;\
  2614.  case 13: ctx.arc(this.x[0],this.y[0],scale_x_radius(this.w[0]),0,2*Math.PI,false);break;\
  2615.  case 14: ctx.font = this.font_family ;ctx.fillText(this.text,this.x[0],this.y[0]);break;\
  2616.  case 15: break;\
  2617.  case 16: for(var p = 0; p < this.x.length;p++){ctx.fillRect( this.x[p], this.y[p],this.line_width,this.line_width );};break;\
  2618.  case 17: ctx.save();var start;var end;if(this.h[0] < this.h[1]){start = this.h[0];end = this.h[1]}else{start = this.h[1];end = this.h[0];};start=360-start;end=360-end;var r = scale_x_radius(this.w[0]);ctx.arc(this.x[0], this.y[0], r, start*(Math.PI / 180), end*(Math.PI / 180),true);if(this.use_filled){ctx.lineTo(this.x[0],this.y[0]);ctx.fill();};ctx.restore();break;\
  2619.  default: alert(\"draw primitive unknown\");break;\
  2620. };\
  2621. if(this.use_filled == 1){ ctx.fill();}\
  2622. if(this.use_dashed == 1 ){if( ctx.setLineDash ){ ctx.setLineDash([this.dashtype0,this.dashtype1]);}else{ ctx.mozDash = [this.dashtype0,this.dashtype1];};};\
  2623. ctx.stroke();\
  2624. ctx.restore();\
  2625. };\
  2626. Shape.prototype.contains = function(mx, my){\
  2627. var marge = 2*this.line_width;\
  2628. switch(this.type){\
  2629.  case 1: for(var p = 0 ; p < this.x.length; p++ ){if( mx < this.x[p] + marge &&  mx > this.x[p] - marge ){if( my < this.y[p]+marge && my > this.y[p] - marge ){return p;};};};break;\
  2630.  case 2: for(var p = 0 ; p < this.x.length; p++ ){if( Math.abs(distance(this.x[p],this.y[p],mx,my) ) < this.w[p] + marge ){return p;break;};};break;\
  2631.  case 3: for(var p = 0 ; p < this.x.length; p++ ){if( Math.abs(distance(this.x[p],this.y[p],mx,my) ) < scale_x_radius(this.w[p]) + marge ){return p;break;};};break;\
  2632.  case 4: var diff;var q;var r;for(var p = 0 ; p < this.x.length-1; p = p+2  ){if( ((this.x[p+1] - this.x[p]) != 0)  && ((this.y[p+1]-this.y[p]) != 0) ){r = (this.y[p+1]-this.y[p])/(this.x[p+1]-this.x[p]);q = this.y[p] - (r)*(this.x[p]);diff = distance_to_line(r,q,mx,my);}else{if( (this.y[p+1]-this.y[p]) != 0 ){diff = Math.abs(this.x[p] - mx);}else{diff = Math.abs(this.y[p] - my);};};if( diff  < marge ){ return p;};}; break;\
  2633.  case 6: for(var p = 0 ; p < this.x.length; p++ ){if( mx < this.x[p] + marge &&  mx > this.x[p] - marge ){if( my < this.y[p]+marge && my > this.y[p] - marge ){return p;};};};break;\
  2634.  case 7: for(var p = 0 ; p < this.x.length; p++ ){if( (this.x[p] - this.w[p] <= mx) && (this.x[p] + this.w[p] >= mx) &&  (this.y[p] - this.h[p] <= my) && (this.y[p] + this.h[p] >= my) ){return p;};};break;\
  2635.  case 8: var diff;var q;var r;for(var p = 0 ; p < this.x.length-1; p = p+2  ){if( ((this.x[p+1] - this.x[p]) != 0)  && ((this.y[p+1]-this.y[p]) != 0) ){r = (this.y[p+1]-this.y[p])/(this.x[p+1]-this.x[p]);q = this.y[p] - (r)*(this.x[p]);diff = distance_to_line(r,q,mx,my);}else{if( (this.y[p+1]-this.y[p]) != 0 ){diff = Math.abs(this.x[p] - mx);}else{diff = Math.abs(this.y[p] - my);};};if( diff  < marge ){ return p;};}; break;\
  2636.  case 9: for(var p = 0 ; p < this.x.length; p++ ){if( (this.x[p] - this.line_width <= mx) && (this.x[p] + this.w[p] + this.line_width >= mx) &&  (this.y[p] - this.line_width <= my) && (this.y[p] + this.h[p] +this.line_width  >= my) ){return p;};};break;\
  2637.  case 11: break;\
  2638.  case 12: break;\
  2639.  case 13: for(var p = 0 ; p < this.x.length; p++ ){if( Math.abs(distance(this.x[p],this.y[p],mx,my) ) < scale_x_radius(this.w[p]) + marge ){return p;break;};};break;\
  2640.  case 14: for(var p = 0 ; p < this.x.length; p++ ){if(this.y[p] < my + 0.5*(this.font_size) && this.y[p] > my - 0.5*(this.font_size)){var w = parseInt(0.8*(this.font_size)*((this.text).length));if(this.x[p] < mx + w && this.x[p] > mx - w ){ return p;break;};};};break;\
  2641.  default: for(var p = 0 ; p < this.x.length; p++ ){if( (this.x[p] - this.line_width <= mx) && (this.x[p] + this.w[p] + this.line_width >= mx) &&  (this.y[p] - this.line_width <= my) && (this.y[p] + this.h[p] +this.line_width  >= my) ){return p;};};break;\
  2642. };\
  2643. return -1;\
  2644. };\
  2645. var reply = [];\
  2646. function CanvasState(canvas,container_div){\
  2647. this.canvas = canvas;\
  2648. this.width = canvas.width;\
  2649. this.height = canvas.height;\
  2650. var ctx = canvas.getContext(\"2d\");\
  2651. this.ctx = ctx;\
  2652. this.valid = false;\
  2653. this.shapes = [];\
  2654. this.moved = [];\
  2655. this.dragging = false;\
  2656. this.selection = null;\
  2657. var myState = this;\
  2658. container_div.addEventListener( 'mouseup'    , mouseup,false);\
  2659. container_div.addEventListener( 'mousemove'  , mousemove,false);\
  2660. container_div.addEventListener( 'mousedown'  , mousedown,false);\
  2661. container_div.addEventListener( 'touchend'   , mouseup,false);\
  2662. container_div.addEventListener( 'selectstart', function(e) { e.preventDefault(); return false; }, false);\
  2663. container_div.addEventListener( 'touchstart' , mousedown,false);\
  2664. container_div.addEventListener( 'touchmove'  , mousemove,false);\
  2665. function mousedown(e){\
  2666.  var mouse = myState.getMouse(e);\
  2667.  var mx = mouse.x;\
  2668.  var my = mouse.y;\
  2669.  if( use_pan_and_zoom == 1 && my > ysize - 15){\
  2670.   check_zoom_or_pan(mx);\
  2671.  }\
  2672.  else\
  2673.  {\
  2674.   var shapes = myState.shapes;\
  2675.   var l = shapes.length;\
  2676.   var chk = -1;\
  2677.   for(var i=0;i<l;i++){\
  2678.    chk = shapes[i].contains(mx, my);\
  2679.    if ( chk != -1 ){\
  2680.     if( myState.moved[shapes[i].click_cnt] != 1){\
  2681.      myState.moved[shapes[i].click_cnt] = 1;\
  2682.      myState.x_start = shapes[i].x[chk];\
  2683.      myState.y_start = shapes[i].y[chk];\
  2684.     };\
  2685.     var org_line_width = shapes[i].line_width;\
  2686.     var org_font_family = shapes[i].font_family;\
  2687.     var org_stroke_opacity = shapes[i].stroke_opacity;\
  2688.     myState.chk = chk;\
  2689.     myState.selection = shapes[i];\
  2690.     myState.valid = false;\
  2691.     switch(shapes[i].onclick){\
  2692.      case 0: myState.dragging = false;break;\
  2693.      case 1: myState.selection.line_width = 3*org_line_width;myState.selection.font_family = \"bold italic \"+myState.selection.font_size+\"px Courier\";myState.dragging = false;myState.draw();reply[0] = myState.selection.click_cnt;myState.selection.line_width = org_line_width;myState.selection.font_family = org_font_family;break;\
  2694.      case 2: myState.dragging = true;break;\
  2695.      default:break;\
  2696.     };\
  2697.     return;\
  2698.    };\
  2699.   };\
  2700.  };\
  2701.  myState.selection = null;\
  2702.  myState.valid = true;\
  2703.  return;\
  2704. };\
  2705. function mouseup(e){;\
  2706.  if(myState.selection != null ){\
  2707.   if(myState.selection.onclick == 2 ){\
  2708.    if( x_use_snap_to_grid == 1 || y_use_snap_to_grid == 1){\
  2709.     var mouse = myState.getMouse(e);\
  2710.     var dx=mouse.x;\
  2711.     var dy=mouse.y;\
  2712.     if( x_use_snap_to_grid == 1 && y_use_snap_to_grid == 1 ){ \
  2713.      dx = snap_to_x(dx) - myState.selection.x[myState.chk];\
  2714.      dy = snap_to_y(dy) - myState.selection.y[myState.chk];\
  2715.     }else{\
  2716.      if( x_use_snap_to_grid == 1 ){ \
  2717.       dx = snap_to_x(dx) - myState.selection.x[myState.chk];\
  2718.       dy = 0;\
  2719.      }else{\
  2720.       dx = 0;\
  2721.       dy = snap_to_y(dy) - myState.selection.y[myState.chk];\
  2722.      };\
  2723.     };\
  2724.     switch(myState.selection.direction){\
  2725.      case 0: myState.selection = move(myState.selection,dx,dy);break;\
  2726.      case 1: myState.selection = move(myState.selection,dx,0);break;\
  2727.      case 2: myState.selection = move(myState.selection,0,dy); break;\
  2728.     };\
  2729.    };\
  2730.    reply[myState.selection.click_cnt] = myState.selection.click_cnt+\":\"+px2x(myState.x_start)+\":\"+px2y(myState.y_start)+\":\"+(Math.round(dragdrop_precision*(px2x(myState.selection.x[myState.chk]))))/dragdrop_precision+\":\"+(Math.round(dragdrop_precision*(px2y(myState.selection.y[myState.chk]))))/dragdrop_precision;\
  2731.   };\
  2732.   myState.valid = false;\
  2733.   myState.draw();\
  2734.   myState.valid = true;\
  2735.  };\
  2736.  myState.dragging = false;\
  2737. };\
  2738. function mousemove(e){\
  2739.  if(myState.dragging){\
  2740.   var mouse = myState.getMouse(e);\
  2741.   var dx=mouse.x - myState.selection.x[myState.chk];\
  2742.   var dy=mouse.y - myState.selection.y[myState.chk];\
  2743.   switch(myState.selection.direction){\
  2744.    case 0: myState.selection = move(myState.selection,dx,dy);break;\
  2745.    case 1: myState.selection = move(myState.selection,dx,0);break;\
  2746.    case 2: myState.selection = move(myState.selection,0,dy); break;\
  2747.    default:break;\
  2748.   };\
  2749.   myState.valid = false;\
  2750.  };\
  2751. };\
  2752. function check_zoom_or_pan(x){\
  2753.  var key = -1;\
  2754.  for(var p = 15 ; p < 106 ; p = p+15){\
  2755.    key++;\
  2756.    if(x > xsize - p){start_canvas%d(key);return;}\
  2757.  }\
  2758.  return;\
  2759. };\
  2760. this.interval = 30;\
  2761. setInterval(function() { myState.draw(); }, myState.interval);\
  2762. };\
  2763. CanvasState.prototype.addShape = function(shape){\
  2764. this.shapes.push(shape);\
  2765. this.valid = false;\
  2766. };\
  2767. CanvasState.prototype.clear = function(){\
  2768. this.ctx.clearRect(0, 0, this.width, this.height);\
  2769. };\
  2770. CanvasState.prototype.draw = function(){\
  2771. if(this.valid == false ){\
  2772.  var shapes = this.shapes;\
  2773.  this.clear();\
  2774.  var l = shapes.length;var shape;\
  2775.  for(var i = 0; i < l; i++){\
  2776.   shape = shapes[i];\
  2777.   shape.draw(this.ctx);\
  2778.  };\
  2779.  this.valid = true;\
  2780. }\
  2781. };\
  2782. CanvasState.prototype.Slide = function(slider_value,slider_count){\
  2783. this.ctx.clearRect(0,0,xsize,ysize);\
  2784. var what;var len = this.shapes.length;var shape;var lu;\
  2785. for(var i = 0; i < len ; i++){\
  2786.  if( this.shapes[i] ){\
  2787.   shape = this.shapes[i];\
  2788.   if( shape.slider != 0 ){\
  2789.    if(shape.slider_cnt == slider_count ){\
  2790.     what = shape.slider;\
  2791.     lu = shape.x.length;\
  2792.     reply[shape.click_cnt] = shape.click_cnt+\":\"+slider_value;\
  2793.     switch(what){\
  2794.      case 1: slide(shape,slider_value[0],0);break;\
  2795.      case 2: slide(shape,0,slider_value[0]);break;\
  2796.      case 3: if(shape.type == 12 || shape.type == 17){shape.h[1] = 180*slider_value[0]/Math.PI;}else{shape.use_rotate = 1;shape.angle = -1*slider_value[0];};break;\
  2797.      case 4: slide(shape,slider_value[0],slider_value[1]);break;\
  2798.      default:break;\
  2799.     };\
  2800.    };\
  2801.   };\
  2802.   this.valid = false;\
  2803.   shape.draw(this.ctx);\
  2804.  };\
  2805. };\
  2806. };\
  2807. CanvasState.prototype.Zoom = function(xmin,xmax,ymin,ymax){\
  2808. (this.ctx).clearRect(0,0,this.width,this.height);\
  2809. var len = this.shapes.length;var shape;\
  2810. for(var i = 0; i < len ; i++){\
  2811.  shape = this.shapes[i];\
  2812.  for(var p = 0 ; p < shape.x.length;p++){\
  2813.   shape.x[p] = x2px(shape.xorg[p]);\
  2814.   shape.y[p] = y2px(shape.yorg[p]);\
  2815.  }\
  2816.  this.valid = false;\
  2817.  shape.draw(this.ctx);\
  2818. };\
  2819. reply = new Array();\
  2820. };\
  2821. CanvasState.prototype.getMouse = function(e){\
  2822. var element = this.canvas, offsetX = 0,offsetY = 0;\
  2823. while( ( element = element.offsetParent) ){\
  2824. offsetX += element.offsetLeft;\
  2825. offsetY += element.offsetTop;\
  2826. }\
  2827. var mx = e.clientX - offsetX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);\
  2828. var my = e.clientY - offsetY + (document.documentElement.scrollTop ? document.documentElement.scrollTop :document.body.scrollTop);\
  2829. return {x: mx, y: my};\
  2830. };\
  2831. CanvasState.prototype.read_dragdrop = function(){\
  2832. var moved_objects = new Array();\
  2833. var c = 0;\
  2834. for(var p = 0 ; p < reply.length ; p++){\
  2835.  if( reply[p] != null ){\
  2836.   moved_objects[c] = reply[p];\
  2837.   c++;\
  2838.  };\
  2839. }\
  2840. return moved_objects;\
  2841. };\
  2842. var obj = create_canvas%d(%d,xsize,ysize);\
  2843. var container_div = document.getElementById(\"canvas_div%d\");\
  2844. var dragstuff = new CanvasState(obj,container_div);\
  2845. read_dragdrop = dragstuff.read_dragdrop;",canvas_root_id,canvas_root_id,DRAG_CANVAS,canvas_root_id);
  2846. }
  2847.  
  2848. /*
  2849. #define BG_CANVAS 0 may be used for floodfill
  2850. #define STATIC_CANVAS 1 may be used for floodfill
  2851. #define MOUSE_CANVAS 2 xx
  2852. #define GRID_CANVAS 3 may be used for floodfill
  2853. #define DRAG_CANVAS 4 default for floodfill
  2854. #define DRAW_CANVAS 5 may be used for floodfill
  2855.  
  2856. */
  2857.  
  2858.  
  2859. void add_js_floodfill(FILE *js_include_file,int canvas_root_id){
  2860. fprintf(js_include_file,"\n<!-- begin command floodfill -->\n\
  2861. var floodfill = function(interaction,xs,ys,color){\
  2862. var canvas = document.getElementById(\"wims_canvas%d%d\");\
  2863. if( ! canvas ){ return; };\
  2864. var ctx = canvas.getContext(\"2d\");\
  2865. ctx.save();\
  2866. if(interaction == 1 ){\
  2867.  if( ys > ysize - 15){return;}\
  2868. }\
  2869. else\
  2870. {\
  2871.  xs = x2px(xs);\
  2872.  ys = y2px(ys);\
  2873. };\
  2874. var image = ctx.getImageData(0, 0, xsize, ysize);\
  2875. var imageData = image.data;\
  2876. var pixelStack = [[xs, ys]];\
  2877. var px1;\
  2878. var newPos;\
  2879. var pixelPos;\
  2880. var found_left_border;\
  2881. var found_right_border;\
  2882. function _getPixel(pixelPos){\
  2883.  return {r:imageData[pixelPos], g:imageData[pixelPos+1], b:imageData[pixelPos+2], a:imageData[pixelPos+3]};\
  2884. };\
  2885. function _setPixel(pixelPos){\
  2886.  imageData[pixelPos] = color.r;\
  2887.  imageData[pixelPos+1] = color.g;\
  2888.  imageData[pixelPos+2] = color.b;\
  2889.  imageData[pixelPos+3] = color.a;\
  2890. };\
  2891. function _comparePixel(px2){\
  2892.  return (px1.r === px2.r && px1.g === px2.g && px1.b === px2.b && px1.a === px2.a);\
  2893. };\
  2894. px1 = _getPixel(((ys * xsize) + xs) * 4);\
  2895. color = {\
  2896.  r: parseInt(color[0], 10),\
  2897.  g: parseInt(color[1], 10),\
  2898.  b: parseInt(color[2], 10),\
  2899.  a: parseInt(color[3] || 255, 10)\
  2900. };\
  2901. if( _comparePixel(color) ) { return true; }\
  2902. while (pixelStack.length) {\
  2903.  newPos = pixelStack.pop();\
  2904.  xs = newPos[0];ys = newPos[1];\
  2905.  pixelPos = (ys*xsize + xs) * 4;\
  2906.  while(ys-- >= 0 && _comparePixel(_getPixel(pixelPos))){\
  2907.   pixelPos -= xsize * 4;\
  2908.  }\
  2909.  pixelPos += xsize * 4;\
  2910.  ++ys;\
  2911.  found_left_border = false;\
  2912.  found_right_border = false;\
  2913.  while( ys++ < ysize-1 && _comparePixel(_getPixel(pixelPos)) ){\
  2914.   _setPixel(pixelPos);\
  2915.   if( xs > 0 ){\
  2916.    if( _comparePixel(_getPixel(pixelPos - 4)) ){\
  2917.    if( !found_left_border ){\
  2918.     pixelStack.push( [xs - 1, ys] );\
  2919.     found_left_border = true;\
  2920.    }\
  2921.   }\
  2922.   else if( found_left_border ){\
  2923.     found_left_border = false;\
  2924.    }\
  2925.   }\
  2926.   if( xs < xsize-1 ){\
  2927.    if( _comparePixel(_getPixel(pixelPos + 4)) ){\
  2928.     if( !found_right_border){\
  2929.      pixelStack.push( [xs + 1, ys] );\
  2930.      found_right_border = true;\
  2931.     }\
  2932.    }\
  2933.    else if(found_right_border){\
  2934.      found_right_border = false;\
  2935.     }\
  2936.    }\
  2937.   pixelPos += xsize * 4;\
  2938.  }\
  2939. };\
  2940. ctx.putImageData(image, 0, 0);\
  2941. ctx.restore();\
  2942. };",canvas_root_id,DRAG_CANVAS);
  2943.  
  2944. }
  2945.  
  2946. void add_js_filltoborder(FILE *js_include_file,int canvas_root_id){
  2947. fprintf(js_include_file,"\n<!-- begin command filltoborder -->\n\
  2948. var filltoborder = function(xs,ys,bordercolor,color){\
  2949. var xs = x2px(xs);\
  2950. var ys = y2px(ys);\
  2951. var canvas = document.getElementById(\"wims_canvas%d\"+4);\
  2952. var ctx = canvas.getContext(\"2d\");ctx.save();\
  2953. var image = ctx.getImageData(0, 0, xsize, ysize);\
  2954. var imageData = image.data;\
  2955. var pixelStack = [[xs, ys]];\
  2956. var px1;\
  2957. var newPos;\
  2958. var pixelPos;\
  2959. var found_left_border;\
  2960. var found_right_border;\
  2961. function _getPixel(pixelPos){\
  2962.  return {r:imageData[pixelPos], g:imageData[pixelPos+1], b:imageData[pixelPos+2], a:imageData[pixelPos+3]};\
  2963. };\
  2964. function _setPixel(pixelPos){\
  2965.  imageData[pixelPos] = color.r;\
  2966.  imageData[pixelPos+1] = color.g;\
  2967.  imageData[pixelPos+2] = color.b;\
  2968.  imageData[pixelPos+3] = color.a;\
  2969. };\
  2970. function _comparePixel(px2){\
  2971.  return (px1.r === px2.r && px1.g === px2.g && px1.b === px2.b);\
  2972. };\
  2973. function _checkBorder(px2){\
  2974.  return (bordercolor.r === px2.r && bordercolor.g === px2.g && bordercolor.b === px2.b);\
  2975. };\
  2976. px1 = _getPixel(((ys * xsize) + xs) * 4);\
  2977. bordercolor = {\
  2978.  r: parseInt(bordercolor[0], 10),\
  2979.  g: parseInt(bordercolor[1], 10),\
  2980.  b: parseInt(bordercolor[2], 10),\
  2981.  a: parseInt(bordercolor[3] || 255, 10)\
  2982. };\
  2983. color = {\
  2984.  r: parseInt(color[0], 10),\
  2985.  g: parseInt(color[1], 10),\
  2986.  b: parseInt(color[2], 10),\
  2987.  a: parseInt(color[3] || 255, 10)\
  2988. };\
  2989. if( _comparePixel(color) ) { return true; }\
  2990. while (pixelStack.length) {\
  2991.  newPos = pixelStack.pop();\
  2992.  xs = newPos[0];ys = newPos[1];\
  2993.  pixelPos = (ys*xsize + xs) * 4;\
  2994.  while(ys-- >= 0 && _comparePixel(_getPixel(pixelPos)) ){\
  2995.   pixelPos -= xsize * 4;\
  2996.  }\
  2997.  pixelPos += xsize * 4;\
  2998.  ++ys;\
  2999.  found_left_border = false;\
  3000.  found_right_border = false;\
  3001.  while( ys++ < ysize-1 &&  _comparePixel(_getPixel(pixelPos)) && ! _checkBorder(_getPixel(pixelPos)) ){\
  3002.   _setPixel(pixelPos);\
  3003.   if( xs > 0 ){\
  3004.    if( _comparePixel(_getPixel(pixelPos - 4)) ){\
  3005.    if( !found_left_border ){\
  3006.     pixelStack.push( [xs - 1, ys] );\
  3007.     found_left_border = true;\
  3008.    }\
  3009.   }\
  3010.   else if( found_left_border ){\
  3011.     found_left_border = false;\
  3012.    }\
  3013.   }\
  3014.   if( xs < xsize-1 ){\
  3015.    if( _comparePixel(_getPixel(pixelPos + 4)) ){\
  3016.     if( !found_right_border){\
  3017.      pixelStack.push( [xs + 1, ys] );\
  3018.      found_right_border = true;\
  3019.     }\
  3020.    }\
  3021.    else if(found_right_border){\
  3022.      found_right_border = false;\
  3023.     }\
  3024.    }\
  3025.   pixelPos += xsize * 4;\
  3026.  }\
  3027. }\
  3028. ctx.putImageData(image, 0, 0);\
  3029. ctx.restore();\
  3030. };",canvas_root_id);
  3031.  
  3032. }
  3033.  
  3034.