12 #include "mppsout.h" /* for mp_edge_object */
14 #define MPLIB_METATABLE "MPlib"
15 #define MPLIB_FIG_METATABLE "MPlib.fig"
16 #define MPLIB_GR_METATABLE "MPlib.gr"
18 #define xfree(A) if (A!=NULL) free(A)
20 #define is_mp(L,b) (MP *)luaL_checkudata(L,b,MPLIB_METATABLE)
21 #define is_fig(L,b) (struct mp_edge_object **)luaL_checkudata(L,b,MPLIB_FIG_METATABLE)
22 #define is_gr_object(L,b) (struct mp_graphic_object **)luaL_checkudata(L,b,MPLIB_GR_METATABLE)
25 P__ZERO, P_ERROR_LINE, P_HALF_LINE, P_MAX_LINE, P_MAIN_MEMORY,
26 P_HASH_SIZE, P_HASH_PRIME, P_PARAM_SIZE, P_IN_OPEN, P_RANDOM_SEED,
27 P_INTERACTION, P_INI_VERSION, P_TROFF_MODE, P_PRINT_NAMES, P_COMMAND_LINE,
28 P_MEM_NAME, P_JOB_NAME, P_FIND_FILE, P_OPEN_FILE, P_CLOSE_FILE,
29 P_EOF_FILE, P_FLUSH_FILE, P_WRITE_ASCII, P_READ_ASCII, P_WRITE_BINARY,
30 P_READ_BINARY, P_RUN_EDITOR, P_RUN_MAKEMPX, P_SHIPOUT, P__SENTINEL,
34 const char *name; /* parameter name */
35 parm_idx idx; /* parameter index */
36 int class; /* parameter class */
39 const char *interaction_options[] =
40 { "unknownmode","batchmode","nonstopmode","scrollmode","errorstopmode", NULL};
42 /* the third field (type) is currently not used */
44 parm_struct img_parms[] = {
45 {NULL, P__ZERO, 0 }, /* dummy; lua indices run from 1 */
46 {"error_line", P_ERROR_LINE, 'i' },
47 {"half_error_line", P_HALF_LINE, 'i' },
48 {"max_print_line", P_MAX_LINE, 'i' },
49 {"main_memory", P_MAIN_MEMORY, 'i' },
50 {"hash_size", P_HASH_SIZE, 'i' },
51 {"hash_prime", P_HASH_PRIME, 'i' },
52 {"param_size", P_PARAM_SIZE, 'i' },
53 {"max_in_open", P_IN_OPEN, 'i' },
54 {"random_seed", P_RANDOM_SEED, 'i' },
55 {"interaction", P_INTERACTION, 'e' },
56 {"ini_version", P_INI_VERSION, 'b' },
57 {"troff_mode", P_TROFF_MODE, 'b' },
58 {"print_found_names", P_PRINT_NAMES, 'b' },
59 {"command_line", P_COMMAND_LINE,'s' },
60 {"mem_name", P_MEM_NAME, 's' },
61 {"job_name", P_JOB_NAME, 's' },
62 {"find_file", P_FIND_FILE, 'p' }, /* intercepted */
63 {NULL, P__SENTINEL, 0 }
66 typedef struct _FILE_ITEM {
70 typedef struct _FILE_ITEM File;
72 /* Start by defining all the callback routines for the library
73 * except |run_make_mpx| and |run_editor|.
76 char *mplib_filetype_names[] = {"term", "error", "mp", "log", "ps",
77 "mem", "tfm", "map", "pfb", "enc", NULL};
81 char *mplib_find_file (char *fname, char *fmode, int ftype) {
85 lua_getfield(L,LUA_REGISTRYINDEX,"mplib_file_finder");
86 if (lua_isfunction(L,-1)) {
87 char *s = NULL, *x = NULL;
88 lua_pushstring(L, fname);
89 lua_pushstring(L, fmode);
90 if (ftype >= mp_filetype_text) {
91 lua_pushnumber(L, ftype-mp_filetype_text);
93 lua_pushstring(L, mplib_filetype_names[ftype]);
95 if(lua_pcall(L,3,1,0) != 0) {
96 fprintf(stdout,"Error in mp.find_file: %s\n", (char *)lua_tostring(L,-1));
99 x = (char *)lua_tostring(L,-1);
102 lua_pop(L,1); /* pop the string */
108 if (fmode[0] != 'r' || (! access (fname,R_OK)) || ftype) {
109 return strdup(fname);
115 mplib_find_file_function (lua_State *L) {
116 if (lua_isfunction(L,-1)) {
118 } else if (lua_isnil(L,-1)) {
121 return 1; /* error */
123 lua_pushstring(L, "mplib_file_finder");
125 lua_rawset(L,LUA_REGISTRYINDEX);
129 void *term_file_ptr = NULL;
130 void *err_file_ptr = NULL;
131 void *log_file_ptr = NULL;
132 void *ps_file_ptr = NULL;
134 void *mplib_open_file(char *fname, char *fmode, int ftype) {
135 File *ff = malloc(sizeof (File));
138 if (ftype==mp_filetype_terminal) {
139 if (fmode[0] == 'r') {
142 xfree(term_file_ptr);
144 term_file_ptr = ff->f;
146 } else if (ftype==mp_filetype_error) {
149 err_file_ptr = ff->f;
150 } else if (ftype == mp_filetype_log) {
153 log_file_ptr = ff->f;
154 } else if (ftype == mp_filetype_postscript) {
160 if (fmode[0] == 'r') {
161 f = mplib_find_file(fname,fmode,ftype);
165 ff->f = fopen(f, fmode);
166 if ((fmode[0] == 'r') && (ff->f == NULL)) {
176 static char * input_data = NULL;
177 static char * input_data_ptr = NULL;
178 static size_t input_data_len = 0;
180 #define GET_CHAR() do { \
181 if (f==stdin && input_data != NULL) { \
182 if (input_data_len==0) { \
183 if (input_data_ptr!=NULL) \
184 input_data_ptr = NULL; \
190 c = *input_data_ptr++; \
197 #define UNGET_CHAR() do { \
198 if (f==stdin && input_data != NULL) { \
199 input_data_len++; input_data_ptr--; \
206 char *mplib_read_ascii_file (void *ff, size_t *size) {
208 size_t len = 0, lim = 128;
211 FILE *f = ((File *)ff)->f;
219 if (s==NULL) return NULL;
220 while (c!=EOF && c!='\n' && c!='\r') {
222 s =realloc(s, (lim+(lim>>2)));
223 if (s==NULL) return NULL;
231 if (c!=EOF && c!='\n')
240 static char *term_out = NULL;
241 static char *error_out = NULL;
242 static char *log_out = NULL;
243 static char *ps_out = NULL;
245 #define APPEND_STRING(a,b) do { \
249 a = realloc(a, strlen(a)+strlen(b)+1); \
250 strcpy(a+strlen(a),b); \
254 void mplib_write_ascii_file (void *ff, char *s) {
256 void *f = ((File *)ff)->f;
258 if (f==term_file_ptr) {
259 APPEND_STRING(term_out,s);
260 } else if (f==err_file_ptr) {
261 APPEND_STRING(error_out,s);
262 } else if (f==log_file_ptr) {
263 APPEND_STRING(log_out,s);
264 } else if (f==ps_file_ptr) {
265 APPEND_STRING(ps_out,s);
267 fprintf((FILE *)f,s);
273 void mplib_read_binary_file (void *ff, void **data, size_t *size) {
276 FILE *f = ((File *)ff)->f;
278 len = fread(*data,1,*size,f);
283 void mplib_write_binary_file (void *ff, void *s, size_t size) {
285 FILE *f = ((File *)ff)->f;
292 void mplib_close_file (void *ff) {
294 void *f = ((File *)ff)->f;
295 if (f != NULL && f != term_file_ptr && f != err_file_ptr
296 && f != log_file_ptr && f != ps_file_ptr) {
303 int mplib_eof_file (void *ff) {
305 FILE *f = ((File *)ff)->f;
308 if (f==stdin && input_data != NULL) {
309 return (input_data_len==0);
316 void mplib_flush_file (void *ff) {
320 static struct mp_edge_object *edges = NULL;
322 #define APPEND_TO_EDGES(a) do { \
326 struct mp_edge_object *p = edges; \
327 while (p->_next!=NULL) { p = p->_next; } \
332 void mplib_shipout_backend (MP mp, int h) {
333 struct mp_edge_object *hh;
334 hh = mp_gr_export(mp, h);
342 mplib_setup_file_ops(struct MP_options * options) {
343 options->find_file = mplib_find_file;
344 options->open_file = mplib_open_file;
345 options->close_file = mplib_close_file;
346 options->eof_file = mplib_eof_file;
347 options->flush_file = mplib_flush_file;
348 options->write_ascii_file = mplib_write_ascii_file;
349 options->read_ascii_file = mplib_read_ascii_file;
350 options->write_binary_file = mplib_write_binary_file;
351 options->read_binary_file = mplib_read_binary_file;
352 options->shipout_backend = mplib_shipout_backend;
356 mplib_new (lua_State *L) {
359 struct MP_options * options; /* instance options */
360 mp_ptr = lua_newuserdata(L, sizeof(MP *));
362 options = mp_options();
363 mplib_setup_file_ops(options);
364 options->noninteractive = 1; /* required ! */
365 options->print_found_names = 0;
366 if (lua_type(L,1)==LUA_TTABLE) {
367 for (i=1;img_parms[i].name!=NULL;i++) {
368 lua_getfield(L,1,img_parms[i].name);
369 if (lua_isnil(L,-1)) {
371 continue; /* skip unset */
373 switch(img_parms[i].idx) {
375 options->error_line = lua_tointeger(L,-1);
378 options->half_error_line = lua_tointeger(L,-1);
381 options->max_print_line = lua_tointeger(L,-1);
384 options->main_memory = lua_tointeger(L,-1);
387 options->hash_size = lua_tointeger(L,-1);
390 options->hash_prime = lua_tointeger(L,-1);
393 options->param_size = lua_tointeger(L,-1);
396 options->max_in_open = lua_tointeger(L,-1);
399 options->random_seed = lua_tointeger(L,-1);
402 options->interaction = luaL_checkoption(L,-1,"errorstopmode", interaction_options);
405 options->ini_version = lua_toboolean(L,-1);
408 options->troff_mode = lua_toboolean(L,-1);
411 options->print_found_names = lua_toboolean(L,-1);
414 options->command_line = strdup((char *)lua_tostring(L,-1));
417 options->mem_name = strdup((char *)lua_tostring(L,-1));
420 options->job_name = strdup((char *)lua_tostring(L,-1));
423 if(mplib_find_file_function(L)) { /* error here */
424 fprintf(stdout,"Invalid arguments to mp.new({find_file=...})\n");
433 *mp_ptr = mp_new(options);
434 xfree(options->command_line);
435 xfree(options->mem_name);
436 xfree(options->job_name);
439 h = mp_initialize(*mp_ptr);
441 luaL_getmetatable(L,MPLIB_METATABLE);
442 lua_setmetatable(L,-2);
452 mplib_collect (lua_State *L) {
453 MP *mp_ptr = is_mp(L,1);
462 mplib_tostring (lua_State *L) {
463 MP *mp_ptr = is_mp(L,1);
465 lua_pushfstring(L,"<MP %p>",*mp_ptr);
472 mplib_run (lua_State *L) {
473 MP *mp_ptr = is_mp(L,1);
475 int h = mp_run(*mp_ptr);
484 mplib_wrapresults(lua_State *L,int h) {
487 if (term_out != NULL) {
488 lua_pushstring(L,term_out);
489 lua_setfield(L,-2,"term");
490 free(term_out); term_out = NULL;
492 if (error_out != NULL) {
493 lua_pushstring(L,error_out);
494 lua_setfield(L,-2,"error");
495 free(error_out); error_out = NULL;
497 if (log_out != NULL ) {
498 lua_pushstring(L,log_out);
499 lua_setfield(L,-2,"log");
500 free(log_out); log_out = NULL;
502 if (edges != NULL ) {
503 struct mp_edge_object **v;
504 struct mp_edge_object *p = edges;
508 v = lua_newuserdata (L, sizeof(struct mp_edge_object *));
510 luaL_getmetatable(L,MPLIB_FIG_METATABLE);
511 lua_setmetatable(L,-2);
512 lua_rawseti(L,-2,i); i++;
515 lua_setfield(L,-2,"fig");
519 lua_setfield(L,-2,"status");
524 mplib_execute (lua_State *L) {
525 MP *mp_ptr = is_mp(L,1);
526 if (*mp_ptr!=NULL && lua_isstring(L,2)) {
527 if (input_data_len>0) { /* this should NOT happen */
528 fprintf(stderr,"Can't do concurrency yet!\n");
530 input_data = (char *)lua_tolstring(L,2, &input_data_len);
531 input_data_ptr = input_data;
532 int h = mp_execute(*mp_ptr);
533 return mplib_wrapresults(L, h);
543 mplib_finish (lua_State *L) {
544 MP *mp_ptr = is_mp(L,1);
546 int h = mp_finish(*mp_ptr);
547 return mplib_wrapresults(L, h);
557 mplib_fig_collect (lua_State *L) {
558 struct mp_edge_object **hh = is_fig(L,1);
560 mp_gr_toss_objects (*hh);
567 mplib_fig_body (lua_State *L) {
569 struct mp_graphic_object **v;
570 struct mp_graphic_object *p;
571 struct mp_edge_object **hh = is_fig(L,1);
575 v = lua_newuserdata (L, sizeof(struct mp_graphic_object *));
577 luaL_getmetatable(L,MPLIB_GR_METATABLE);
578 lua_setmetatable(L,-2);
579 lua_rawseti(L,-2,i); i++;
582 (*hh)->body = NULL; /* prevent double free */
588 mplib_fig_tostring (lua_State *L) {
589 struct mp_edge_object **hh = is_fig(L,1);
590 lua_pushfstring(L,"<figure %p>",*hh);
597 mp_wrapped_shipout (struct mp_edge_object *hh, int prologues, int procset) {
599 if (setjmp(mp->jump_buf)) {
602 mp_gr_ship_out(hh,prologues,procset);
607 mplib_fig_postscript (lua_State *L) {
608 struct mp_edge_object **hh = is_fig(L,1);
609 int prologues = luaL_optnumber(L,2,-1);
610 int procset = luaL_optnumber(L,3,-1);
611 if (ps_out == NULL) {
612 if (mp_wrapped_shipout(*hh,prologues, procset)) {
614 lua_pushstring(L, ps_out);
615 free(ps_out); ps_out = NULL;
622 lua_pushstring(L,log_out);
623 free(ps_out); ps_out = NULL;
632 mplib_fig_bb (lua_State *L) {
633 struct mp_edge_object **hh = is_fig(L,1);
635 lua_pushnumber(L, (double)(*hh)->_minx/65536.0);
637 lua_pushnumber(L, (double)(*hh)->_miny/65536.0);
639 lua_pushnumber(L, (double)(*hh)->_maxx/65536.0);
641 lua_pushnumber(L, (double)(*hh)->_maxy/65536.0);
649 mplib_gr_collect (lua_State *L) {
650 struct mp_graphic_object **hh = is_gr_object(L,1);
652 mp_gr_toss_object(*hh);
659 mplib_gr_tostring (lua_State *L) {
660 struct mp_graphic_object **hh = is_gr_object(L,1);
661 lua_pushfstring(L,"<object %p>",*hh);
666 char *knot_type_enum[] = {
667 "endpoint", "explicit", "given", "curl", "open", "end_cycle"
670 char *knot_originator_enum[] = { "program" ,"user" };
675 mplib_push_path (lua_State *L, struct mp_knot *h ) {
676 struct mp_knot *p; /* for scanning the path */
683 lua_pushstring(L,knot_originator_enum[p->originator_field]);
684 lua_setfield(L,-2,"originator");
685 lua_pushstring(L,knot_type_enum[p->left_type_field]);
686 lua_setfield(L,-2,"left_type");
687 lua_pushstring(L,knot_type_enum[p->right_type_field]);
688 lua_setfield(L,-2,"right_type");
689 lua_pushnumber(L,p->x_coord_field);
690 lua_setfield(L,-2,"x_coord");
691 lua_pushnumber(L,p->y_coord_field);
692 lua_setfield(L,-2,"y_coord");
693 lua_pushnumber(L,p->left_x_field);
694 lua_setfield(L,-2,"left_x");
695 lua_pushnumber(L,p->left_y_field);
696 lua_setfield(L,-2,"left_y");
697 lua_pushnumber(L,p->right_x_field);
698 lua_setfield(L,-2,"right_x");
699 lua_pushnumber(L,p->right_y_field);
700 lua_setfield(L,-2,"right_y");
701 lua_rawseti(L,-2,i); i++;
702 if ( p->right_type_field==mp_endpoint ) {
712 char *color_model_enum[] = { NULL, "none", NULL, "grey",
713 NULL, "rgb", NULL, "cmyk", NULL, "uninitialized" };
717 /* this is a bit silly, a better color model representation is needed */
719 mplib_push_color (lua_State *L, struct mp_graphic_object *h ) {
722 lua_pushstring(L,color_model_enum[h->color_model_field]);
723 lua_setfield(L,-2,"model");
725 if (h->color_model_field == mp_rgb_model ||
726 h->color_model_field == mp_uninitialized_model) {
728 lua_pushnumber(L,h->color_field.rgb._red_val);
730 lua_pushnumber(L,h->color_field.rgb._green_val);
732 lua_pushnumber(L,h->color_field.rgb._blue_val);
734 lua_setfield(L,-2,"rgb");
737 if (h->color_model_field == mp_cmyk_model ||
738 h->color_model_field == mp_uninitialized_model) {
740 lua_pushnumber(L,h->color_field.cmyk._cyan_val);
742 lua_pushnumber(L,h->color_field.cmyk._magenta_val);
744 lua_pushnumber(L,h->color_field.cmyk._yellow_val);
746 lua_pushnumber(L,h->color_field.cmyk._black_val);
748 lua_setfield(L,-2,"cmyk");
750 if (h->color_model_field == mp_grey_model ||
751 h->color_model_field == mp_uninitialized_model) {
753 lua_pushnumber(L,h->color_field.grey._grey_val);
755 lua_setfield(L,-2,"grey");
763 /* dashes are complicated, perhaps it would be better if the
764 object had a PS-compatible representation */
766 mplib_push_dash (lua_State *L, struct mp_graphic_object *h ) {
769 lua_pushnumber(L,h->dash_scale_field);
770 lua_setfield(L,-2,"scale");
772 lua_pushnumber(L,(int)h->dash_p_field);
773 lua_setfield(L,-2,"dashes");
780 mplib_push_transform (lua_State *L, struct mp_graphic_object *h ) {
784 lua_pushnumber(L,h->tx_field);
785 lua_rawseti(L,-2,i); i++;
786 lua_pushnumber(L,h->ty_field);
787 lua_rawseti(L,-2,i); i++;
788 lua_pushnumber(L,h->txx_field);
789 lua_rawseti(L,-2,i); i++;
790 lua_pushnumber(L,h->txy_field);
791 lua_rawseti(L,-2,i); i++;
792 lua_pushnumber(L,h->tyx_field);
793 lua_rawseti(L,-2,i); i++;
794 lua_pushnumber(L,h->tyy_field);
795 lua_rawseti(L,-2,i); i++;
801 static char *fill_fields[] = { "type", "path", "htap", "pen", "color", "ljoin", "miterlim", "prescript", "postscript", NULL };
803 #define FIELD(A) (strcmp(field,#A)==0)
806 mplib_fill_field (lua_State *L, struct mp_graphic_object *h, char *field) {
808 lua_pushstring(L,"fill");
809 } else if (FIELD(path)) {
810 mplib_push_path(L, h->path_p_field);
811 } else if (FIELD(htap)) {
812 mplib_push_path(L, h->htap_p_field);
813 } else if (FIELD(pen)) {
814 mplib_push_path(L, h->pen_p_field);
815 } else if (FIELD(color)) {
816 mplib_push_color(L, h);
817 } else if (FIELD(ljoin)) {
818 lua_pushnumber(L,h->ljoin_field);
819 } else if (FIELD(miterlim)) {
820 lua_pushnumber(L,h->miterlim_field);
821 } else if (FIELD(prescript)) {
822 lua_pushstring(L,h->pre_script_field);
823 } else if (FIELD(postscript)) {
824 lua_pushstring(L,h->post_script_field);
830 static char *stroked_fields[] = {"type", "path", "pen", "color", "ljoin", "miterlim", "lcap", "dash", "prescript", "postscript", NULL };
833 mplib_stroked_field (lua_State *L, struct mp_graphic_object *h, char *field) {
835 lua_pushstring(L,"stroked");
836 } else if (FIELD(path)) {
837 mplib_push_path(L, h->path_p_field);
838 } else if (FIELD(pen)) {
839 mplib_push_path(L, h->pen_p_field);
840 } else if (FIELD(color)) {
841 mplib_push_color(L, h);
842 } else if (FIELD(dash)) {
843 mplib_push_dash(L, h);
844 } else if (FIELD(lcap)) {
845 lua_pushnumber(L,h->lcap_field);
846 } else if (FIELD(ljoin)) {
847 lua_pushnumber(L,h->ljoin_field);
848 } else if (FIELD(miterlim)) {
849 lua_pushnumber(L,h->miterlim_field);
850 } else if (FIELD(prescript)) {
851 lua_pushstring(L,h->pre_script_field);
852 } else if (FIELD(postscript)) {
853 lua_pushstring(L,h->post_script_field);
859 static char *text_fields[] = { "type", "text", "nametype" "font", "color", "width", "height", "depth", "transform", "prescript", "postscript", NULL };
861 /* todo: name_type and font_n do not make sense */
864 mplib_text_field (lua_State *L, struct mp_graphic_object *h, char *field) {
866 lua_pushstring(L,"text");
867 } else if (FIELD(text)) {
868 lua_pushstring(L,h->text_p_field);
869 } else if (FIELD(nametype)) {
870 lua_pushnumber(L,h->name_type_field);
871 } else if (FIELD(font)) {
872 lua_pushnumber(L,h->font_n_field);
873 } else if (FIELD(color)) {
874 mplib_push_color(L, h);
875 } else if (FIELD(width)) {
876 lua_pushnumber(L,h->width_field);
877 } else if (FIELD(height)) {
878 lua_pushnumber(L,h->height_field);
879 } else if (FIELD(depth)) {
880 lua_pushnumber(L,h->depth_field);
881 } else if (FIELD(transform)) {
882 mplib_push_transform(L,h);
883 } else if (FIELD(prescript)) {
884 lua_pushstring(L,h->pre_script_field);
885 } else if (FIELD(postscript)) {
886 lua_pushstring(L,h->post_script_field);
892 static char *special_fields[] = { "type", "prescript", NULL };
895 mplib_special_field (lua_State *L, struct mp_graphic_object *h, char *field) {
897 lua_pushstring(L,"special");
898 } else if (FIELD(prescript)) {
899 lua_pushstring(L,h->pre_script_field);
905 static char *start_bounds_fields[] = { "type", "path", NULL };
908 mplib_start_bounds_field (lua_State *L, struct mp_graphic_object *h, char *field) {
910 lua_pushstring(L,"start_bounds");
911 } else if (FIELD(path)) {
912 mplib_push_path(L,h->path_p_field);
918 static char *start_clip_fields[] = { "type", "path", NULL };
921 mplib_start_clip_field (lua_State *L, struct mp_graphic_object *h, char *field) {
923 lua_pushstring(L,"start_clip");
924 } else if (FIELD(path)) {
925 mplib_push_path(L,h->path_p_field);
931 static char *stop_bounds_fields[] = { "type", NULL };
934 mplib_stop_bounds_field (lua_State *L, struct mp_graphic_object *h, char *field) {
935 if (h!=NULL && FIELD(type)) {
936 lua_pushstring(L,"stop_bounds");
942 static char *stop_clip_fields[] = { "type", NULL };
945 mplib_stop_clip_field (lua_State *L, struct mp_graphic_object *h, char *field) {
946 if (h!=NULL && FIELD(type)) {
947 lua_pushstring(L,"stop_clip");
953 static char *no_fields[] = { NULL };
956 mplib_gr_fields (lua_State *L) {
960 struct mp_graphic_object **hh = is_gr_object(L,1);
962 switch ((*hh)->_type_field) {
963 case mp_fill_code: fields = fill_fields; break;
964 case mp_stroked_code: fields = stroked_fields; break;
965 case mp_text_code: fields = text_fields; break;
966 case mp_special_code: fields = special_fields; break;
967 case mp_start_clip_code: fields = start_clip_fields; break;
968 case mp_start_bounds_code: fields = start_bounds_fields; break;
969 case mp_stop_clip_code: fields = stop_clip_fields; break;
970 case mp_stop_bounds_code: fields = stop_bounds_fields; break;
971 default: fields = no_fields;
974 for (f = *fields; f != NULL; f++) {
976 lua_rawseti(L,-2,i); i++;
985 mplib_gr_index (lua_State *L) {
986 struct mp_graphic_object **hh = is_gr_object(L,1);
987 char *field = (char *)luaL_checkstring(L,2);
989 switch ((*hh)->_type_field) {
990 case mp_fill_code: mplib_fill_field(L,*hh,field); break;
991 case mp_stroked_code: mplib_stroked_field(L,*hh,field); break;
992 case mp_text_code: mplib_text_field(L,*hh,field); break;
993 case mp_special_code: mplib_special_field(L,*hh,field); break;
994 case mp_start_clip_code: mplib_start_clip_field(L,*hh,field); break;
995 case mp_start_bounds_code: mplib_start_bounds_field(L,*hh,field); break;
996 case mp_stop_clip_code: mplib_stop_clip_field(L,*hh,field); break;
997 case mp_stop_bounds_code: mplib_stop_bounds_field(L,*hh,field); break;
998 default: lua_pushnil(L);
1007 static const struct luaL_reg mplib_meta[] = {
1008 {"__gc", mplib_collect},
1009 {"__tostring", mplib_tostring},
1010 {NULL, NULL} /* sentinel */
1013 static const struct luaL_reg mplib_fig_meta[] = {
1014 {"__gc", mplib_fig_collect },
1015 {"__tostring", mplib_fig_tostring },
1016 {"objects", mplib_fig_body },
1017 {"postscript", mplib_fig_postscript },
1018 {"boundingbox", mplib_fig_bb },
1019 {NULL, NULL} /* sentinel */
1022 static const struct luaL_reg mplib_gr_meta[] = {
1023 {"__gc", mplib_gr_collect },
1024 {"__tostring", mplib_gr_tostring },
1025 {"fields", mplib_gr_fields },
1026 {"__index", mplib_gr_index },
1027 {NULL, NULL} /* sentinel */
1031 static const struct luaL_reg mplib_d [] = {
1032 {"run", mplib_run },
1033 {"execute", mplib_execute },
1034 {"finish", mplib_finish },
1035 {NULL, NULL} /* sentinel */
1039 static const struct luaL_reg mplib_m[] = {
1041 {NULL, NULL} /* sentinel */
1046 luaopen_mp (lua_State *L) {
1047 luaL_newmetatable(L,MPLIB_GR_METATABLE);
1048 lua_pushvalue(L, -1); /* push metatable */
1049 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
1050 luaL_register(L, NULL, mplib_gr_meta); /* object meta methods */
1053 luaL_newmetatable(L,MPLIB_FIG_METATABLE);
1054 lua_pushvalue(L, -1); /* push metatable */
1055 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
1056 luaL_register(L, NULL, mplib_fig_meta); /* figure meta methods */
1059 luaL_newmetatable(L,MPLIB_METATABLE);
1060 lua_pushvalue(L, -1); /* push metatable */
1061 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
1062 luaL_register(L, NULL, mplib_meta); /* meta methods */
1063 luaL_register(L, NULL, mplib_d); /* dict methods */
1064 luaL_register(L, "mp", mplib_m); /* module functions */