Updated TODO.
[mp-5.x.git] / mp_core.c
blob3acd714829cd3dcf0a104ebf67d45f3a955a3e8c
1 /*
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
25 #include "config.h"
27 #include <stdio.h>
28 #include <wchar.h>
29 #include <stdlib.h>
30 #include <string.h>
32 #include "mpdm.h"
33 #include "mpsl.h"
35 #include "mp.h"
37 /*******************
38 Data
39 ********************/
41 int mpi_preread_lines = 60;
43 /* exit requested? */
44 int mp_exit_requested = 0;
46 /* main namespace */
47 mpdm_t mp = NULL;
49 /*******************
50 Code
51 ********************/
53 /* private data for drawing syntax-highlighted text */
55 struct drw_1_info {
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;
75 static struct {
76 int x; /* cursor x */
77 int y; /* cursor y */
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 */
92 } drw_2;
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 */
101 int r;
103 switch(c) {
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;
117 int n, x;
119 for(n = x = 0;n < vx && ptr[x] != L'\0';x++)
120 n += drw_wcwidth(n, ptr[x]);
122 return(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;
130 int n, vx;
132 for(n = vx = 0;n < x && ptr[n] != L'\0';n++)
133 vx += drw_wcwidth(vx, ptr[n]);
135 return(vx);
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 */
149 int t = *vy;
151 /* is y above the first visible line? */
152 if(y < *vy) *vy = y;
154 /* is y below the last visible line? */
155 if(y > *vy + (ty - 2)) *vy = y - (ty - 2);
157 return(t != *vy);
161 static int drw_adjust_x(int x, int y, int * vx, int tx, wchar_t * ptr)
162 /* adjust the visual x position */
164 int n, m;
165 int t = *vx;
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 */
172 if(m < *vx) *vx = m;
174 /* if new cursor column is further the rightmost column, set */
175 if(m > *vx + (tx - 1)) *vx = m - (tx - 1);
177 return(t != *vx);
181 static int drw_get_attr(wchar_t * color_name)
182 /* returns the attribute number for a color */
184 mpdm_t v;
185 int attr = 0;
187 if((v = mpdm_hget_s(drw_1.colors, color_name)) != NULL)
188 attr = mpdm_ival(mpdm_hget_s(v, L"attr"));
190 return(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"));
203 int n;
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;
223 /* maximum lines */
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);
239 drw_2.x = x;
240 drw_2.y = y;
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)
245 return(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));
253 drw_2.ptr = NULL;
254 drw_2.size = 0;
256 /* add first line */
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;
273 /* now add it */
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));
279 drw_2.size--;
281 /* now create a value */
282 mpdm_unref(drw_2.v);
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);
291 return(1);
295 static int drw_fill_attr(int attr, int offset, int size)
296 /* fill an attribute */
298 if(attr != -1)
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 */
315 mpdm_t r, t;
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)
322 return;
324 /* get the regex for words */
325 if((r = mpdm_hget_s(mp, L"word_regex")) == NULL)
326 return;
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)
333 int attr = -1;
334 mpdm_t v;
336 if((v = mpdm_hget(word_color, t)) != NULL)
337 attr = mpdm_ival(v);
338 else
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 */
350 int n;
352 for(n = 0;n < mpdm_size(a);n++)
354 mpdm_t r = mpdm_aget(a, n);
355 int o = 0;
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))
366 int s;
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);
379 else
381 /* not found; fill to the end
382 of the document */
383 s = drw_2.size - o;
386 /* fill to there */
387 o = drw_fill_attr(attr, o, s);
390 else
392 /* it's a scalar: */
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 */
404 mpdm_t defs;
405 int n;
407 /* no definitions? return */
408 if(drw_1.syntax == NULL || (defs = mpdm_hget_s(drw_1.syntax, L"defs")) == NULL)
409 return;
411 for(n = 0;n < mpdm_size(defs);n += 2)
413 mpdm_t attr;
414 mpdm_t list;
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 */
432 mpdm_t mark;
433 int bx, by, ex, ey;
434 int so, eo;
436 /* no mark? return */
437 if((mark = mpdm_hget_s(drw_1.txt, L"mark")) == NULL)
438 return;
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)
447 return;
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;
477 int i = 0;
478 wchar_t c;
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 */
494 if(i)
496 wchar_t s = drw_2.ptr[o];
497 int m = 0;
498 int l = i == -1 ? drw_2.visible - 1 : drw_2.size;
500 while(o != l)
502 if (drw_2.ptr[o] == s)
504 /* found the same */
505 m++;
507 else
508 if (drw_2.ptr[o] == c)
510 /* found the opposite */
511 if(--m == 0)
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);
517 break;
521 o += i;
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 */
534 tmp[i] = L'\0';
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;
548 /* one char less */
549 tmp[i - 1] = L'\0';
552 /* store the attribute and the string */
553 mpdm_push(l, MPDM_I(a));
554 mpdm_push(l, MPDM_S(tmp));
556 return(l);
560 #define BUF_LINE 128
562 static mpdm_t drw_line(int line)
563 /* creates a list of attribute / string pairs for the current line */
565 mpdm_t l = NULL;
566 int m, i, t, n;
567 int o = drw_2.offsets[line + drw_1.p_lines];
568 int a = drw_2.attrs[o];
569 wchar_t tmp[BUF_LINE];
570 wchar_t c;
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 */
576 c = drw_2.ptr[o];
577 t = drw_wcwidth(m, c);
579 /* further the left margin? */
580 if(m >= drw_1.vx)
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);
587 i = 0;
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')
595 c = L' ';
597 /* if next char will not fit, use a space */
598 if(m + t > drw_1.vx + drw_1.tx)
599 c = L' ';
601 else
603 /* left filler */
604 n = m + t - drw_1.vx;
605 c = L' ';
608 /* fill the string */
609 for(;n > 0;n--)
610 tmp[i++] = c;
612 a = drw_2.attrs[o];
614 /* end of line? */
615 if(drw_2.ptr[o] == L'\0' || drw_2.ptr[o] == L'\n')
616 break;
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 */
627 mpdm_t a;
628 int n;
630 /* the array of lines */
631 a = MPDM_A(drw_1.ty);
633 /* push each line */
634 for(n = 0;n < drw_1.ty;n++)
635 mpdm_aset(a, drw_line(n), n);
637 return(a);
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;
645 mpdm_t r = a;
647 if(optimize && o != NULL)
649 int n = 0;
651 /* creates a copy */
652 r = mpdm_clone(a);
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);
661 n++;
665 mpdm_unref(drw_2.old); drw_2.old = mpdm_ref(a);
667 return(r);
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);
678 /* cursor */
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 */
697 mpdm_t r = NULL;
699 if(drw_prepare(doc))
701 /* colorize separate words */
702 drw_words();
704 /* colorize multiline blocks */
705 drw_blocks();
708 /* now set the marked block (if any) */
709 drw_selection();
711 /* the cursor */
712 drw_cursor();
714 /* highlight the matching paren */
715 drw_matching_paren();
717 /* convert to an array of string / atribute pairs */
718 r = drw_as_array();
720 /* optimize */
721 r = drw_optimize_array(r, optimize);
723 /* restore the patched attrs */
724 drw_restore_attrs();
726 return(r);
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() */
734 mpdm_t r = NULL;
735 static int ppp = 0; /* previous private paint */
736 mpdm_t f;
738 /* if previous paint was private, disable optimizations */
739 if(ppp) optimize = ppp = 0;
741 if(doc != NULL)
743 if((f = mpdm_hget_s(doc, L"paint")) != NULL)
745 ppp = 1;
746 r = mpdm_exec_2(f, doc, MPDM_I(optimize));
748 else
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);
760 return(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;
832 return(NULL);
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);
856 mpdm_t v;
857 int chomped = 1;
859 while((v = mpdm_read(f)) != NULL)
861 wchar_t * ptr = v->data;
862 int size = v->size;
864 /* chomp */
865 if(size && ptr[size - 1] == L'\n')
867 if(--size && ptr[size - 1] == L'\r')
868 --size;
870 else
871 chomped = 0;
873 mpdm_push(a, MPDM_NS(ptr, size));
874 mpdm_destroy(v);
877 /* if last line was chomped, add a last, empty one */
878 if(chomped) mpdm_push(a, MPDM_LS(L""));
880 return(a);
884 void mp_startup(int argc, char * argv[])
886 mpdm_t INC;
888 mpsl_startup();
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 */
895 mp = MPDM_H(0);
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));
906 /* version */
907 mpdm_hset_s(mp, L"VERSION", MPDM_S(L"" VERSION));
909 /* creates the INC (executable path) array */
910 INC = MPDM_A(0);
912 /* add installed library path */
913 mpdm_push(INC, mpdm_strcat(
914 mpdm_hget_s(mpdm_root(), L"APPDIR"),
915 MPDM_MBS(CONFOPT_APPNAME))
918 /* set INC */
919 mpdm_hset_s(mpdm_root(), L"INC", INC);
921 if(!TRY_DRIVERS())
923 printf("No usable driver found; exiting.\n");
924 exit(1);
927 mpsl_argv(argc, argv);
931 void mp_mpsl(void)
933 mpdm_t e;
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));
940 printf("\n");
945 void mp_shutdown(void)
947 mpsl_shutdown();
951 int main(int argc, char * argv[])
953 mp_startup(argc, argv);
955 mp_mpsl();
957 mp_shutdown();
959 return(0);