3 Minimum Profit - Programmer Text Editor
5 Copyright (C) 1991-2007 Angel Ortega <angel@triptico.com>
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 http://www.triptico.com
41 int mpi_preread_lines
= 60;
44 int mp_exit_requested
= 0;
53 /* private data for drawing syntax-highlighted text */
56 mpdm_t txt
; /* the document */
57 mpdm_t syntax
; /* syntax highlight information */
58 mpdm_t colors
; /* color definitions (for attributes) */
59 mpdm_t word_color_func
; /* word color function (just for detection) */
60 int normal_attr
; /* normal attr */
61 int cursor_attr
; /* cursor attr */
62 int n_lines
; /* total number of lines */
63 int p_lines
; /* number of prereaded lines */
64 int vx
; /* first visible column */
65 int vy
; /* first visible line */
66 int tx
; /* horizontal window size */
67 int ty
; /* vertical window size */
68 int tab_size
; /* tabulator size */
69 int mod
; /* modify count */
72 struct drw_1_info drw_1
;
73 struct drw_1_info drw_1_o
;
78 int * offsets
; /* offsets of lines */
79 char * attrs
; /* attributes */
80 int visible
; /* offset to the first visible character */
81 int cursor
; /* offset to cursor */
82 wchar_t * ptr
; /* pointer to joined data */
83 int size
; /* size of joined data */
84 int matchparen_offset
; /* offset to matched paren */
85 int matchparen_o_attr
; /* original attribute there */
86 int cursor_o_attr
; /* original attribute under cursor */
87 mpdm_t v
; /* the data */
88 mpdm_t old
; /* the previously generated array */
89 int mark_offset
; /* offset to the marked block */
90 int mark_size
; /* size of mark_o_attr */
91 char * mark_o_attr
; /* saved attributes for the mark */
95 #define MP_REAL_TAB_SIZE(x) (drw_1.tab_size - ((x) % drw_1.tab_size))
97 static int drw_wcwidth(int x
, wchar_t c
)
98 /* returns the wcwidth of c, or the tab spaces for
99 the x column if it's a tab */
104 case L
'\n': r
= 1; break;
105 case L
'\t': r
= MP_REAL_TAB_SIZE(x
); break;
106 default: r
= mpdm_wcwidth(c
); break;
109 return(r
< 0 ? 1 : r
);
113 int drw_vx2x(mpdm_t str
, int vx
)
114 /* returns the character in str that is on column vx */
116 wchar_t * ptr
= str
->data
;
119 for(n
= x
= 0;n
< vx
&& ptr
[x
] != L
'\0';x
++)
120 n
+= drw_wcwidth(n
, ptr
[x
]);
126 int drw_x2vx(mpdm_t str
, int x
)
127 /* returns the column where the character at offset x seems to be */
129 wchar_t * ptr
= str
->data
;
132 for(n
= vx
= 0;n
< x
&& ptr
[n
] != L
'\0';n
++)
133 vx
+= drw_wcwidth(vx
, ptr
[n
]);
139 static int drw_line_offset(int l
)
140 /* returns the offset into v for line number l */
142 return(drw_2
.offsets
[l
- drw_1
.vy
+ drw_1
.p_lines
]);
146 static int drw_adjust_y(int y
, int * vy
, int ty
)
147 /* adjusts the visual y position */
151 /* is y above the first visible line? */
154 /* is y below the last visible line? */
155 if(y
> *vy
+ (ty
- 2)) *vy
= y
- (ty
- 2);
161 static int drw_adjust_x(int x
, int y
, int * vx
, int tx
, wchar_t * ptr
)
162 /* adjust the visual x position */
167 /* calculate the column for the cursor position */
168 for(n
= m
= 0;n
< x
;n
++, ptr
++)
169 m
+= drw_wcwidth(m
, *ptr
);
171 /* if new cursor column is nearer the leftmost column, set */
174 /* if new cursor column is further the rightmost column, set */
175 if(m
> *vx
+ (tx
- 1)) *vx
= m
- (tx
- 1);
181 static int drw_get_attr(wchar_t * color_name
)
182 /* returns the attribute number for a color */
187 if((v
= mpdm_hget_s(drw_1
.colors
, color_name
)) != NULL
)
188 attr
= mpdm_ival(mpdm_hget_s(v
, L
"attr"));
194 static int drw_prepare(mpdm_t doc
)
195 /* prepares the document for screen drawing */
197 mpdm_t window
= mpdm_hget_s(mp
, L
"window");
198 mpdm_t config
= mpdm_hget_s(mp
, L
"config");
199 mpdm_t txt
= mpdm_hget_s(doc
, L
"txt");
200 mpdm_t lines
= mpdm_hget_s(txt
, L
"lines");
201 int x
= mpdm_ival(mpdm_hget_s(txt
, L
"x"));
202 int y
= mpdm_ival(mpdm_hget_s(txt
, L
"y"));
205 drw_1
.vx
= mpdm_ival(mpdm_hget_s(txt
, L
"vx"));
206 drw_1
.vy
= mpdm_ival(mpdm_hget_s(txt
, L
"vy"));
207 drw_1
.tx
= mpdm_ival(mpdm_hget_s(window
, L
"tx"));
208 drw_1
.ty
= mpdm_ival(mpdm_hget_s(window
, L
"ty"));
209 drw_1
.tab_size
= mpdm_ival(mpdm_hget_s(config
, L
"tab_size"));
210 drw_1
.mod
= mpdm_ival(mpdm_hget_s(txt
, L
"mod"));
212 /* adjust the visual y coordinate */
213 if(drw_adjust_y(y
, &drw_1
.vy
, drw_1
.ty
))
214 mpdm_hset_s(txt
, L
"vy", MPDM_I(drw_1
.vy
));
216 /* adjust the visual x coordinate */
217 if(drw_adjust_x(x
, y
, &drw_1
.vx
, drw_1
.tx
, mpdm_string(mpdm_aget(lines
, y
))))
218 mpdm_hset_s(txt
, L
"vx", MPDM_I(drw_1
.vx
));
220 /* get the maximum prereadable lines */
221 drw_1
.p_lines
= drw_1
.vy
> mpi_preread_lines
? mpi_preread_lines
: drw_1
.vy
;
224 drw_1
.n_lines
= drw_1
.ty
+ drw_1
.p_lines
;
226 /* get the mp.colors structure and the most used attributes */
227 drw_1
.colors
= mpdm_hget_s(mp
, L
"colors");
228 drw_1
.normal_attr
= drw_get_attr(L
"normal");
229 drw_1
.cursor_attr
= drw_get_attr(L
"cursor");
231 /* store the syntax highlight structure */
232 drw_1
.syntax
= mpdm_hget_s(doc
, L
"syntax");
234 drw_1
.word_color_func
= mpdm_hget_s(mp
, L
"word_color_func");
236 mpdm_unref(drw_1
.txt
);
237 drw_1
.txt
= mpdm_ref(txt
);
242 /* compare drw_1 with drw_1_o; if they are the same,
243 no more expensive calculations on drw_2 are needed */
244 if(memcmp(&drw_1
, &drw_1_o
, sizeof(drw_1
)) == 0)
247 /* different; store now */
248 memcpy(&drw_1_o
, &drw_1
, sizeof(drw_1_o
));
250 /* alloc space for line offsets */
251 drw_2
.offsets
= realloc(drw_2
.offsets
, drw_1
.n_lines
* sizeof(int));
257 drw_2
.ptr
= mpdm_pokev(drw_2
.ptr
, &drw_2
.size
,
258 mpdm_aget(lines
, drw_1
.vy
- drw_1
.p_lines
));
260 /* first line start at 0 */
261 drw_2
.offsets
[0] = 0;
263 /* add the following lines and store their offsets */
264 for(n
= 1;n
< drw_1
.n_lines
;n
++)
266 /* add the separator */
267 drw_2
.ptr
= mpdm_poke(drw_2
.ptr
, &drw_2
.size
,
268 L
"\n", 1, sizeof(wchar_t));
270 /* this line starts here */
271 drw_2
.offsets
[n
] = drw_2
.size
;
274 drw_2
.ptr
= mpdm_pokev(drw_2
.ptr
, &drw_2
.size
,
275 mpdm_aget(lines
, n
+ drw_1
.vy
- drw_1
.p_lines
));
278 drw_2
.ptr
= mpdm_poke(drw_2
.ptr
, &drw_2
.size
, L
"", 1, sizeof(wchar_t));
281 /* now create a value */
283 drw_2
.v
= mpdm_ref(MPDM_ENS(drw_2
.ptr
, drw_2
.size
));
285 /* alloc and init space for the attributes */
286 drw_2
.attrs
= realloc(drw_2
.attrs
, drw_2
.size
+ 1);
287 memset(drw_2
.attrs
, drw_1
.normal_attr
, drw_2
.size
+ 1);
289 drw_2
.visible
= drw_line_offset(drw_1
.vy
);
295 static int drw_fill_attr(int attr
, int offset
, int size
)
296 /* fill an attribute */
299 memset(drw_2
.attrs
+ offset
, attr
, size
);
301 return(offset
+ size
);
305 static int drw_fill_attr_regex(int attr
)
306 /* fills with an attribute the last regex match */
308 return(drw_fill_attr(attr
, mpdm_regex_offset
, mpdm_regex_size
));
312 static void drw_words(void)
313 /* fills the attributes for separate words */
316 int o
= drw_2
.visible
;
317 mpdm_t word_color
= NULL
;
318 mpdm_t word_color_func
= NULL
;
320 /* take the hash of word colors, if any */
321 if((word_color
= mpdm_hget_s(mp
, L
"word_color")) == NULL
)
324 /* get the regex for words */
325 if((r
= mpdm_hget_s(mp
, L
"word_regex")) == NULL
)
328 /* get the word color function */
329 word_color_func
= mpdm_hget_s(mp
, L
"word_color_func");
331 while((t
= mpdm_regex(r
, drw_2
.v
, o
)) != NULL
)
336 if((v
= mpdm_hget(word_color
, t
)) != NULL
)
339 if(word_color_func
!= NULL
)
340 attr
= mpdm_ival(mpdm_exec_1(word_color_func
, t
));
342 o
= drw_fill_attr_regex(attr
);
347 static void drw_multiline_regex(mpdm_t a
, int attr
)
348 /* sets the attribute to all matching (possibly multiline) regexes */
352 for(n
= 0;n
< mpdm_size(a
);n
++)
354 mpdm_t r
= mpdm_aget(a
, n
);
357 /* if the regex is an array, it's a pair of
358 'match from this' / 'match until this' */
359 if(r
->flags
& MPDM_MULTIPLE
)
361 mpdm_t rs
= mpdm_aget(r
, 0);
362 mpdm_t re
= mpdm_aget(r
, 1);
364 while(mpdm_regex(rs
, drw_2
.v
, o
))
368 /* fill the matched part */
369 o
= drw_fill_attr_regex(attr
);
371 /* try to match the end */
372 if(mpdm_regex(re
, drw_2
.v
, o
))
374 /* found; fill the attribute
375 to the end of the match */
376 s
= mpdm_regex_size
+
377 (mpdm_regex_offset
- o
);
381 /* not found; fill to the end
387 o
= drw_fill_attr(attr
, o
, s
);
393 /* while the regex matches, fill attributes */
394 while(mpdm_regex(r
, drw_2
.v
, o
))
395 o
= drw_fill_attr_regex(attr
);
401 static void drw_blocks(void)
402 /* fill attributes for multiline blocks */
407 /* no definitions? return */
408 if(drw_1
.syntax
== NULL
|| (defs
= mpdm_hget_s(drw_1
.syntax
, L
"defs")) == NULL
)
411 for(n
= 0;n
< mpdm_size(defs
);n
+= 2)
416 /* get the attribute */
417 attr
= mpdm_aget(defs
, n
);
418 attr
= mpdm_hget(drw_1
.colors
, attr
);
419 attr
= mpdm_hget_s(attr
, L
"attr");
421 /* get the list for this word color */
422 list
= mpdm_aget(defs
, n
+ 1);
424 drw_multiline_regex(list
, mpdm_ival(attr
));
429 static void drw_selection(void)
430 /* draws the selected block, if any */
436 /* no mark? return */
437 if((mark
= mpdm_hget_s(drw_1
.txt
, L
"mark")) == NULL
)
440 bx
= mpdm_ival(mpdm_hget_s(mark
, L
"bx"));
441 by
= mpdm_ival(mpdm_hget_s(mark
, L
"by"));
442 ex
= mpdm_ival(mpdm_hget_s(mark
, L
"ex"));
443 ey
= mpdm_ival(mpdm_hget_s(mark
, L
"ey"));
445 /* if block is not visible, return */
446 if(ey
< drw_1
.vy
|| by
> drw_1
.vy
+ drw_1
.ty
)
449 so
= by
< drw_1
.vy
? drw_2
.visible
: drw_line_offset(by
) + bx
;
450 eo
= ey
>= drw_1
.vy
+ drw_1
.ty
? drw_2
.size
: drw_line_offset(ey
) + ex
;
452 /* alloc space and save the attributes being destroyed */
453 drw_2
.mark_offset
= so
;
454 drw_2
.mark_size
= eo
- so
;
455 drw_2
.mark_o_attr
= malloc(eo
- so
);
456 memcpy(drw_2
.mark_o_attr
, &drw_2
.attrs
[so
], eo
- so
);
458 drw_fill_attr(drw_get_attr(L
"selection"), so
, eo
- so
);
462 static void drw_cursor(void)
463 /* fill the attribute for the cursor */
465 /* calculate the cursor offset */
466 drw_2
.cursor
= drw_line_offset(drw_2
.y
) + drw_2
.x
;
468 drw_2
.cursor_o_attr
= drw_2
.attrs
[drw_2
.cursor
];
469 drw_fill_attr(drw_1
.cursor_attr
, drw_2
.cursor
, 1);
473 static void drw_matching_paren(void)
474 /* highlights the matching paren */
476 int o
= drw_2
.cursor
;
480 /* by default, no offset has been found */
481 drw_2
.matchparen_offset
= -1;
483 /* find the opposite and the increment (direction) */
484 switch(drw_2
.ptr
[o
]) {
485 case L
'(': c
= L
')'; i
= 1; break;
486 case L
'{': c
= L
'}'; i
= 1; break;
487 case L
'[': c
= L
']'; i
= 1; break;
488 case L
')': c
= L
'('; i
= -1; break;
489 case L
'}': c
= L
'{'; i
= -1; break;
490 case L
']': c
= L
'['; i
= -1; break;
493 /* if a direction is set, do the searching */
496 wchar_t s
= drw_2
.ptr
[o
];
498 int l
= i
== -1 ? drw_2
.visible
- 1 : drw_2
.size
;
502 if (drw_2
.ptr
[o
] == s
)
508 if (drw_2
.ptr
[o
] == c
)
510 /* found the opposite */
513 /* found! fill and exit */
514 drw_2
.matchparen_offset
= o
;
515 drw_2
.matchparen_o_attr
= drw_2
.attrs
[o
];
516 drw_fill_attr(drw_get_attr(L
"matching"), o
, 1);
527 static mpdm_t
drw_push_pair(mpdm_t l
, int i
, int a
, wchar_t * tmp
)
528 /* pushes a pair of attribute / string into l */
530 /* create the array, if doesn't exist yet */
531 if(l
== NULL
) l
= MPDM_A(0);
533 /* finish the string */
536 /* special magic: if the attribute is the
537 one of the cursor and the string is more than
538 one character, create two strings; the
539 cursor is over a tab */
540 if(a
== drw_1
.cursor_attr
&& i
> 1)
542 mpdm_push(l
, MPDM_I(a
));
543 mpdm_push(l
, MPDM_NS(tmp
, 1));
545 /* the rest of the string has the original attr */
546 a
= drw_2
.cursor_o_attr
;
552 /* store the attribute and the string */
553 mpdm_push(l
, MPDM_I(a
));
554 mpdm_push(l
, MPDM_S(tmp
));
562 static mpdm_t
drw_line(int line
)
563 /* creates a list of attribute / string pairs for the current line */
567 int o
= drw_2
.offsets
[line
+ drw_1
.p_lines
];
568 int a
= drw_2
.attrs
[o
];
569 wchar_t tmp
[BUF_LINE
];
572 /* loop while not beyond the right margin */
573 for(m
= i
= 0;m
< drw_1
.vx
+ drw_1
.tx
;m
+= t
, o
++)
575 /* take char and size */
577 t
= drw_wcwidth(m
, c
);
579 /* further the left margin? */
582 /* if the attribute is different or we're out of
583 temporary space, push and go on */
584 if(drw_2
.attrs
[o
] != a
|| i
>= BUF_LINE
- t
- 1)
586 l
= drw_push_pair(l
, i
, a
, tmp
);
590 /* size is 1, unless it's a tab */
591 n
= c
== L
'\t' ? t
: 1;
593 /* fill EOLs and tabs with spaces */
594 if(c
== L
'\0' || c
== L
'\n' || c
== L
'\t')
597 /* if next char will not fit, use a space */
598 if(m
+ t
> drw_1
.vx
+ drw_1
.tx
)
604 n
= m
+ t
- drw_1
.vx
;
608 /* fill the string */
615 if(drw_2
.ptr
[o
] == L
'\0' || drw_2
.ptr
[o
] == L
'\n')
619 return(drw_push_pair(l
, i
, a
, tmp
));
623 static mpdm_t
drw_as_array(void)
624 /* returns an mpdm array of ty elements, which are also arrays of
625 attribute - string pairs */
630 /* the array of lines */
631 a
= MPDM_A(drw_1
.ty
);
634 for(n
= 0;n
< drw_1
.ty
;n
++)
635 mpdm_aset(a
, drw_line(n
), n
);
641 static mpdm_t
drw_optimize_array(mpdm_t a
, int optimize
)
642 /* optimizes the array, NULLifying all lines that are the same as the last time */
644 mpdm_t o
= drw_2
.old
;
647 if(optimize
&& o
!= NULL
)
654 /* compare each array */
655 while(n
< mpdm_size(o
) && n
< mpdm_size(r
))
657 /* if both lines are equal, optimize out */
658 if(mpdm_cmp(mpdm_aget(o
, n
), mpdm_aget(r
, n
)) == 0)
659 mpdm_aset(r
, NULL
, n
);
665 mpdm_unref(drw_2
.old
); drw_2
.old
= mpdm_ref(a
);
671 static void drw_restore_attrs(void)
672 /* restored the patched attrs */
674 /* matching paren, if any */
675 if(drw_2
.matchparen_offset
!= -1)
676 drw_fill_attr(drw_2
.matchparen_o_attr
, drw_2
.matchparen_offset
, 1);
679 drw_fill_attr(drw_2
.cursor_o_attr
, drw_2
.cursor
, 1);
681 /* marked block, if any */
682 if(drw_2
.mark_o_attr
!= NULL
)
684 memcpy(&drw_2
.attrs
[drw_2
.mark_offset
],
685 drw_2
.mark_o_attr
, drw_2
.mark_size
);
687 free(drw_2
.mark_o_attr
);
688 drw_2
.mark_o_attr
= NULL
;
693 static mpdm_t
drw_draw(mpdm_t doc
, int optimize
)
694 /* main document drawing function: takes a document and returns an array of
695 arrays of attribute / string pairs */
701 /* colorize separate words */
704 /* colorize multiline blocks */
708 /* now set the marked block (if any) */
714 /* highlight the matching paren */
715 drw_matching_paren();
717 /* convert to an array of string / atribute pairs */
721 r
= drw_optimize_array(r
, optimize
);
723 /* restore the patched attrs */
730 mpdm_t
mp_draw(mpdm_t doc
, int optimize
)
731 /* main generic drawing function: if the document has a 'paint' code,
732 calls it; otherwise, call drw_draw() */
735 static int ppp
= 0; /* previous private paint */
738 /* if previous paint was private, disable optimizations */
739 if(ppp
) optimize
= ppp
= 0;
743 if((f
= mpdm_hget_s(doc
, L
"paint")) != NULL
)
746 r
= mpdm_exec_2(f
, doc
, MPDM_I(optimize
));
749 r
= drw_draw(doc
, optimize
);
752 /* if there is a global post_paint function, execute it */
753 if((f
= mpdm_hget_s(mp
, L
"post_paint")) != NULL
)
754 r
= mpdm_exec_1(f
, r
);
756 /* if doc has a post_paint function, execute it */
757 if((f
= mpdm_hget_s(doc
, L
"post_paint")) != NULL
)
758 r
= mpdm_exec_1(f
, r
);
764 mpdm_t
mp_active(void)
765 /* interface to mp.active() */
767 return(mpdm_exec(mpdm_hget_s(mp
, L
"active"), NULL
));
771 mpdm_t
mp_process_action(mpdm_t action
)
772 /* interface to mp.process_action() */
774 return(mpdm_exec_1(mpdm_hget_s(mp
, L
"process_action"), action
));
778 mpdm_t
mp_process_event(mpdm_t keycode
)
779 /* interface to mp.process_event() */
781 return(mpdm_exec_1(mpdm_hget_s(mp
, L
"process_event"), keycode
));
785 mpdm_t
mp_set_y(mpdm_t doc
, int y
)
786 /* interface to mp.set_y() */
788 return(mpdm_exec_2(mpdm_hget_s(mp
, L
"set_y"), doc
, MPDM_I(y
)));
792 mpdm_t
mp_build_status_line(void)
793 /* interface to mp.build_status_line() */
795 return(mpdm_exec(mpdm_hget_s(mp
, L
"build_status_line"), NULL
));
799 mpdm_t
mp_get_history(mpdm_t key
)
800 /* interface to mp.get_history() */
802 return(mpdm_exec_1(mpdm_hget_s(mp
, L
"get_history"), key
));
806 mpdm_t
mp_menu_label(mpdm_t action
)
807 /* interface to mp.menu_label() */
809 return(mpdm_exec_1(mpdm_hget_s(mp
, L
"menu_label"), action
));
813 mpdm_t
mp_pending_key(void)
814 /* interface to mp.pending_key() */
816 return(mpdm_exec_1(mpdm_hget_s(mp
, L
"pending_key"), NULL
));
820 mpdm_t
mp_process_keyseq(mpdm_t key
)
821 /* interface to mp.process_keyseq() */
823 return(mpdm_exec_1(mpdm_hget_s(mp
, L
"process_keyseq"), key
));
827 mpdm_t
mp_exit(mpdm_t args
)
828 /* exit the editor (set mp_exit_requested) */
830 mp_exit_requested
= 1;
836 mpdm_t
mp_vx2x(mpdm_t args
)
837 /* interface to drw_vx2x() */
839 return(MPDM_I(drw_vx2x(mpdm_aget(args
, 0),
840 mpdm_ival(mpdm_aget(args
, 1)))));
844 mpdm_t
mp_x2vx(mpdm_t args
)
845 /* interface to drw_x2vx() */
847 return(MPDM_I(drw_x2vx(mpdm_aget(args
, 0),
848 mpdm_ival(mpdm_aget(args
, 1)))));
851 mpdm_t
mp_plain_load(mpdm_t args
)
852 /* loads a plain file into an array (highly optimized one) */
854 mpdm_t f
= mpdm_aget(args
, 0);
855 mpdm_t a
= MPDM_A(0);
859 while((v
= mpdm_read(f
)) != NULL
)
861 wchar_t * ptr
= v
->data
;
865 if(size
&& ptr
[size
- 1] == L
'\n')
867 if(--size
&& ptr
[size
- 1] == L
'\r')
873 mpdm_push(a
, MPDM_NS(ptr
, size
));
877 /* if last line was chomped, add a last, empty one */
878 if(chomped
) mpdm_push(a
, MPDM_LS(L
""));
884 void mp_startup(int argc
, char * argv
[])
890 /* reset the structures */
891 memset(&drw_1
, '\0', sizeof(drw_1
));
892 memset(&drw_1_o
, '\0', sizeof(drw_1_o
));
894 /* create main namespace */
896 mpdm_hset_s(mpdm_root(), L
"mp", mp
);
898 /* basic functions and data */
899 mpdm_hset_s(mp
, L
"x2vx", MPDM_X(mp_x2vx
));
900 mpdm_hset_s(mp
, L
"vx2x", MPDM_X(mp_vx2x
));
901 mpdm_hset_s(mp
, L
"exit", MPDM_X(mp_exit
));
902 mpdm_hset_s(mp
, L
"plain_load", MPDM_X(mp_plain_load
));
903 mpdm_hset_s(mp
, L
"window", MPDM_H(0));
904 mpdm_hset_s(mp
, L
"drv", MPDM_H(0));
907 mpdm_hset_s(mp
, L
"VERSION", MPDM_S(L
"" VERSION
));
909 /* creates the INC (executable path) array */
912 /* add installed library path */
913 mpdm_push(INC
, mpdm_strcat(
914 mpdm_hget_s(mpdm_root(), L
"APPDIR"),
915 MPDM_MBS(CONFOPT_APPNAME
))
919 mpdm_hset_s(mpdm_root(), L
"INC", INC
);
923 printf("No usable driver found; exiting.\n");
927 mpsl_argv(argc
, argv
);
935 mpsl_eval(MPDM_LS(L
"load('mp_core.mpsl');"), NULL
);
937 if((e
= mpdm_hget_s(mpdm_root(), L
"ERROR")) != NULL
)
939 mpdm_write_wcs(stdout
, mpdm_string(e
));
945 void mp_shutdown(void)
951 int main(int argc
, char * argv
[])
953 mp_startup(argc
, argv
);