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
42 int mp_exit_requested
= 0;
51 /* private data for drawing syntax-highlighted text */
54 mpdm_t txt
; /* the document */
55 mpdm_t syntax
; /* syntax highlight information */
56 mpdm_t colors
; /* color definitions (for attributes) */
57 mpdm_t word_color_func
; /* word color function (just for detection) */
58 int normal_attr
; /* normal attr */
59 int cursor_attr
; /* cursor attr */
60 int n_lines
; /* number of processed lines */
61 int p_lines
; /* number of prereaded lines */
62 int t_lines
; /* total lines in document */
63 int vx
; /* first visible column */
64 int vy
; /* first visible line */
65 int tx
; /* horizontal window size */
66 int ty
; /* vertical window size */
67 int tab_size
; /* tabulator size */
68 int mod
; /* modify count */
69 int preread_lines
; /* lines to pre-read (for synhi blocks) */
70 int mark_eol
; /* mark end of lines */
73 struct drw_1_info drw_1
;
74 struct drw_1_info drw_1_o
;
79 int *offsets
; /* offsets of lines */
80 char *attrs
; /* attributes */
81 int visible
; /* offset to the first visible character */
82 int cursor
; /* offset to cursor */
83 wchar_t *ptr
; /* pointer to joined data */
84 int size
; /* size of joined data */
85 int matchparen_offset
; /* offset to matched paren */
86 int matchparen_o_attr
; /* original attribute there */
87 int cursor_o_attr
; /* original attribute under cursor */
88 mpdm_t v
; /* the data */
89 mpdm_t old
; /* the previously generated array */
90 int mark_offset
; /* offset to the marked block */
91 int mark_size
; /* size of mark_o_attr */
92 char *mark_o_attr
; /* saved attributes for the mark */
96 #define MP_REAL_TAB_SIZE(x) (drw_1.tab_size - ((x) % drw_1.tab_size))
98 static int drw_wcwidth(int x
, wchar_t c
)
99 /* returns the wcwidth of c, or the tab spaces for
100 the x column if it's a tab */
109 r
= MP_REAL_TAB_SIZE(x
);
116 return r
< 0 ? 1 : r
;
120 int drw_vx2x(mpdm_t str
, int vx
)
121 /* returns the character in str that is on column vx */
123 const wchar_t *ptr
= str
->data
;
126 for (n
= x
= 0; n
< vx
&& ptr
[x
] != L
'\0'; x
++)
127 n
+= drw_wcwidth(n
, ptr
[x
]);
133 int drw_x2vx(mpdm_t str
, int x
)
134 /* returns the column where the character at offset x seems to be */
136 const wchar_t *ptr
= str
->data
;
139 for (n
= vx
= 0; n
< x
&& ptr
[n
] != L
'\0'; n
++)
140 vx
+= drw_wcwidth(vx
, ptr
[n
]);
146 static int drw_line_offset(int l
)
147 /* returns the offset into v for line number l */
149 return drw_2
.offsets
[l
- drw_1
.vy
+ drw_1
.p_lines
];
153 static int drw_adjust_y(int y
, int *vy
, int ty
)
154 /* adjusts the visual y position */
158 /* is y above the first visible line? */
162 /* is y below the last visible line? */
163 if (y
> *vy
+ (ty
- 2))
170 static int drw_adjust_x(int x
, int y
, int *vx
, int tx
, wchar_t * ptr
)
171 /* adjust the visual x position */
176 /* calculate the column for the cursor position */
177 for (n
= m
= 0; n
< x
; n
++, ptr
++)
178 m
+= drw_wcwidth(m
, *ptr
);
180 /* if new cursor column is nearer the leftmost column, set */
184 /* if new cursor column is further the rightmost column, set */
185 if (m
> *vx
+ (tx
- 1))
192 static int drw_get_attr(wchar_t * color_name
)
193 /* returns the attribute number for a color */
198 if ((v
= mpdm_hget_s(drw_1
.colors
, color_name
)) != NULL
)
199 attr
= mpdm_ival(mpdm_hget_s(v
, L
"attr"));
205 static int drw_prepare(mpdm_t doc
)
206 /* prepares the document for screen drawing */
208 mpdm_t window
= mpdm_hget_s(mp
, L
"window");
209 mpdm_t config
= mpdm_hget_s(mp
, L
"config");
210 mpdm_t txt
= mpdm_hget_s(doc
, L
"txt");
211 mpdm_t lines
= mpdm_hget_s(txt
, L
"lines");
212 int x
= mpdm_ival(mpdm_hget_s(txt
, L
"x"));
213 int y
= mpdm_ival(mpdm_hget_s(txt
, L
"y"));
216 drw_1
.vx
= mpdm_ival(mpdm_hget_s(txt
, L
"vx"));
217 drw_1
.vy
= mpdm_ival(mpdm_hget_s(txt
, L
"vy"));
218 drw_1
.tx
= mpdm_ival(mpdm_hget_s(window
, L
"tx"));
219 drw_1
.ty
= mpdm_ival(mpdm_hget_s(window
, L
"ty"));
220 drw_1
.tab_size
= mpdm_ival(mpdm_hget_s(config
, L
"tab_size"));
221 drw_1
.mod
= mpdm_ival(mpdm_hget_s(txt
, L
"mod"));
222 drw_1
.preread_lines
= mpdm_ival(mpdm_hget_s(config
, L
"preread_lines"));
223 drw_1
.mark_eol
= mpdm_ival(mpdm_hget_s(config
, L
"mark_eol"));
224 drw_1
.t_lines
= mpdm_size(lines
);
226 /* adjust the visual y coordinate */
227 if (drw_adjust_y(y
, &drw_1
.vy
, drw_1
.ty
))
228 mpdm_hset_s(txt
, L
"vy", MPDM_I(drw_1
.vy
));
230 /* adjust the visual x coordinate */
231 if (drw_adjust_x(x
, y
, &drw_1
.vx
, drw_1
.tx
, mpdm_string(mpdm_aget(lines
, y
))))
232 mpdm_hset_s(txt
, L
"vx", MPDM_I(drw_1
.vx
));
234 /* get the maximum prereadable lines */
235 drw_1
.p_lines
= drw_1
.vy
> drw_1
.preread_lines
? drw_1
.preread_lines
: drw_1
.vy
;
238 drw_1
.n_lines
= drw_1
.ty
+ drw_1
.p_lines
;
240 /* get the mp.colors structure and the most used attributes */
241 drw_1
.colors
= mpdm_hget_s(mp
, L
"colors");
242 drw_1
.normal_attr
= drw_get_attr(L
"normal");
243 drw_1
.cursor_attr
= drw_get_attr(L
"cursor");
245 /* store the syntax highlight structure */
246 drw_1
.syntax
= mpdm_hget_s(doc
, L
"syntax");
248 drw_1
.word_color_func
= mpdm_hget_s(mp
, L
"word_color_func");
250 mpdm_unref(drw_1
.txt
);
251 drw_1
.txt
= mpdm_ref(txt
);
256 /* compare drw_1 with drw_1_o; if they are the same,
257 no more expensive calculations on drw_2 are needed */
258 if (memcmp(&drw_1
, &drw_1_o
, sizeof(drw_1
)) == 0)
261 /* different; store now */
262 memcpy(&drw_1_o
, &drw_1
, sizeof(drw_1_o
));
264 /* alloc space for line offsets */
265 drw_2
.offsets
= realloc(drw_2
.offsets
, drw_1
.n_lines
* sizeof(int));
271 drw_2
.ptr
= mpdm_pokev(drw_2
.ptr
, &drw_2
.size
,
272 mpdm_aget(lines
, drw_1
.vy
- drw_1
.p_lines
));
274 /* first line start at 0 */
275 drw_2
.offsets
[0] = 0;
277 /* add the following lines and store their offsets */
278 for (n
= 1; n
< drw_1
.n_lines
; n
++) {
279 /* add the separator */
280 drw_2
.ptr
= mpdm_poke(drw_2
.ptr
, &drw_2
.size
, L
"\n", 1, sizeof(wchar_t));
282 /* this line starts here */
283 drw_2
.offsets
[n
] = drw_2
.size
;
286 drw_2
.ptr
= mpdm_pokev(drw_2
.ptr
, &drw_2
.size
,
287 mpdm_aget(lines
, n
+ drw_1
.vy
- drw_1
.p_lines
));
290 drw_2
.ptr
= mpdm_poke(drw_2
.ptr
, &drw_2
.size
, L
"", 1, sizeof(wchar_t));
293 /* now create a value */
295 drw_2
.v
= mpdm_ref(MPDM_ENS(drw_2
.ptr
, drw_2
.size
));
297 /* alloc and init space for the attributes */
298 drw_2
.attrs
= realloc(drw_2
.attrs
, drw_2
.size
+ 1);
299 memset(drw_2
.attrs
, drw_1
.normal_attr
, drw_2
.size
+ 1);
301 drw_2
.visible
= drw_line_offset(drw_1
.vy
);
307 static int drw_fill_attr(int attr
, int offset
, int size
)
308 /* fill an attribute */
311 memset(drw_2
.attrs
+ offset
, attr
, size
);
313 return offset
+ size
;
317 static int drw_fill_attr_regex(int attr
)
318 /* fills with an attribute the last regex match */
320 return drw_fill_attr(attr
, mpdm_regex_offset
, mpdm_regex_size
);
324 static void drw_words(void)
325 /* fills the attributes for separate words */
328 int o
= drw_2
.visible
;
329 mpdm_t word_color
= NULL
;
330 mpdm_t word_color_func
= NULL
;
332 /* take the hash of word colors, if any */
333 if ((word_color
= mpdm_hget_s(mp
, L
"word_color")) == NULL
)
336 /* get the regex for words */
337 if ((r
= mpdm_hget_s(mp
, L
"word_regex")) == NULL
)
340 /* get the word color function */
341 word_color_func
= mpdm_hget_s(mp
, L
"word_color_func");
343 while ((t
= mpdm_regex(r
, drw_2
.v
, o
)) != NULL
) {
347 if ((v
= mpdm_hget(word_color
, t
)) != NULL
)
349 else if (word_color_func
!= NULL
)
350 attr
= mpdm_ival(mpdm_exec_1(word_color_func
, t
));
352 o
= drw_fill_attr_regex(attr
);
357 static void drw_multiline_regex(mpdm_t a
, int attr
)
358 /* sets the attribute to all matching (possibly multiline) regexes */
362 for (n
= 0; n
< mpdm_size(a
); n
++) {
363 mpdm_t r
= mpdm_aget(a
, n
);
366 /* if the regex is an array, it's a pair of
367 'match from this' / 'match until this' */
368 if (r
->flags
& MPDM_MULTIPLE
) {
369 mpdm_t rs
= mpdm_aget(r
, 0);
370 mpdm_t re
= mpdm_aget(r
, 1);
372 while (mpdm_regex(rs
, drw_2
.v
, o
)) {
375 /* fill the matched part */
376 o
= drw_fill_attr_regex(attr
);
378 /* try to match the end */
379 if (mpdm_regex(re
, drw_2
.v
, o
)) {
380 /* found; fill the attribute
381 to the end of the match */
382 s
= mpdm_regex_size
+ (mpdm_regex_offset
- o
);
385 /* not found; fill to the end
391 o
= drw_fill_attr(attr
, o
, s
);
396 /* while the regex matches, fill attributes */
397 while (mpdm_regex(r
, drw_2
.v
, o
))
398 o
= drw_fill_attr_regex(attr
);
404 static void drw_blocks(void)
405 /* fill attributes for multiline blocks */
410 /* no definitions? return */
411 if (drw_1
.syntax
== NULL
|| (defs
= mpdm_hget_s(drw_1
.syntax
, L
"defs")) == NULL
)
414 for (n
= 0; n
< mpdm_size(defs
); n
+= 2) {
418 /* get the attribute */
419 attr
= mpdm_aget(defs
, n
);
420 attr
= mpdm_hget(drw_1
.colors
, attr
);
421 attr
= mpdm_hget_s(attr
, L
"attr");
423 /* get the list for this word color */
424 list
= mpdm_aget(defs
, n
+ 1);
426 drw_multiline_regex(list
, mpdm_ival(attr
));
431 static void drw_selection(void)
432 /* draws the selected block, if any */
435 int bx
, by
, ex
, ey
, vertical
;
438 int line_offset
, next_line_offset
;
443 /* no mark? return */
444 if ((mark
= mpdm_hget_s(drw_1
.txt
, L
"mark")) == NULL
)
447 bx
= mpdm_ival(mpdm_hget_s(mark
, L
"bx"));
448 by
= mpdm_ival(mpdm_hget_s(mark
, L
"by"));
449 ex
= mpdm_ival(mpdm_hget_s(mark
, L
"ex"));
450 ey
= mpdm_ival(mpdm_hget_s(mark
, L
"ey"));
451 vertical
= mpdm_ival(mpdm_hget_s(mark
, L
"vertical"));
453 /* if block is not visible, return */
454 if (ey
< drw_1
.vy
|| by
> drw_1
.vy
+ drw_1
.ty
)
457 so
= by
< drw_1
.vy
? drw_2
.visible
: drw_line_offset(by
) + bx
;
458 eo
= ey
>= drw_1
.vy
+ drw_1
.ty
? drw_2
.size
: drw_line_offset(ey
) + ex
;
460 /* alloc space and save the attributes being destroyed */
461 drw_2
.mark_offset
= so
;
462 drw_2
.mark_size
= eo
- so
+ 1;
463 drw_2
.mark_o_attr
= malloc(eo
- so
+ 1);
464 memcpy(drw_2
.mark_o_attr
, &drw_2
.attrs
[so
], eo
- so
+ 1);
467 /* normal selection */
468 drw_fill_attr(drw_get_attr(L
"selection"), so
, eo
- so
);
471 /* vertical selection */
472 mby
= by
< drw_1
.vy
? drw_1
.vy
: by
;
473 mey
= ey
>= drw_1
.vy
+ drw_1
.ty
? drw_1
.vy
+ drw_1
.ty
: ey
;
474 line_offset
= drw_line_offset(mby
);
475 attr
= drw_get_attr(L
"selection");
476 for (y
= mby
; y
<= mey
; y
++) {
477 next_line_offset
= drw_line_offset(y
+1);
478 len
= next_line_offset
- line_offset
- 1;
479 so
= bx
> len
? -1 : bx
;
480 eo
= ex
> len
? len
: ex
;
482 if (so
>= 0 && eo
>= so
)
483 drw_fill_attr(attr
, line_offset
+ so
, eo
- so
+ 1);
485 line_offset
= next_line_offset
;
491 static void drw_search_hit(void)
492 /* colorize the search hit, if any */
496 if ((v
= mpdm_hget_s(mp
, L
"last_search")) != NULL
) {
497 mpdm_t l
= mpdm_ref(MPDM_A(0));
500 drw_multiline_regex(l
, drw_get_attr(L
"search"));
506 static void drw_cursor(void)
507 /* fill the attribute for the cursor */
509 /* calculate the cursor offset */
510 drw_2
.cursor
= drw_line_offset(drw_2
.y
) + drw_2
.x
;
512 drw_2
.cursor_o_attr
= drw_2
.attrs
[drw_2
.cursor
];
513 drw_fill_attr(drw_1
.cursor_attr
, drw_2
.cursor
, 1);
517 static void drw_matching_paren(void)
518 /* highlights the matching paren */
520 int o
= drw_2
.cursor
;
524 /* by default, no offset has been found */
525 drw_2
.matchparen_offset
= -1;
527 /* find the opposite and the increment (direction) */
528 switch (drw_2
.ptr
[o
]) {
555 /* if a direction is set, do the searching */
557 wchar_t s
= drw_2
.ptr
[o
];
559 int l
= i
== -1 ? drw_2
.visible
- 1 : drw_2
.size
;
562 if (drw_2
.ptr
[o
] == s
) {
566 else if (drw_2
.ptr
[o
] == c
) {
567 /* found the opposite */
569 /* found! fill and exit */
570 drw_2
.matchparen_offset
= o
;
571 drw_2
.matchparen_o_attr
= drw_2
.attrs
[o
];
572 drw_fill_attr(drw_get_attr(L
"matching"), o
, 1);
583 static mpdm_t
drw_push_pair(mpdm_t l
, int i
, int a
, wchar_t * tmp
)
584 /* pushes a pair of attribute / string into l */
586 /* create the array, if doesn't exist yet */
590 /* finish the string */
593 /* special magic: if the attribute is the
594 one of the cursor and the string is more than
595 one character, create two strings; the
596 cursor is over a tab */
597 if (a
== drw_1
.cursor_attr
&& i
> 1) {
598 mpdm_push(l
, MPDM_I(a
));
599 mpdm_push(l
, MPDM_NS(tmp
, 1));
601 /* the rest of the string has the original attr */
602 a
= drw_2
.cursor_o_attr
;
608 /* store the attribute and the string */
609 mpdm_push(l
, MPDM_I(a
));
610 mpdm_push(l
, MPDM_S(tmp
));
618 static mpdm_t
drw_line(int line
)
619 /* creates a list of attribute / string pairs for the current line */
623 int o
= drw_2
.offsets
[line
+ drw_1
.p_lines
];
624 int a
= drw_2
.attrs
[o
];
625 wchar_t tmp
[BUF_LINE
];
628 /* loop while not beyond the right margin */
629 for (m
= i
= 0; m
< drw_1
.vx
+ drw_1
.tx
; m
+= t
, o
++) {
630 /* take char and size */
632 t
= drw_wcwidth(m
, c
);
634 /* further the left margin? */
636 /* if the attribute is different or we're out of
637 temporary space, push and go on */
638 if (drw_2
.attrs
[o
] != a
|| i
>= BUF_LINE
- t
- 1) {
639 l
= drw_push_pair(l
, i
, a
, tmp
);
643 /* size is 1, unless it's a tab */
644 n
= c
== L
'\t' ? t
: 1;
646 /* fill tabs with spaces */
647 if (c
== L
'\0' || c
== L
'\t')
650 /* fill EOLs with special marks or spaces */
652 c
= drw_1
.mark_eol
? L
'\xb6' : L
' ';
654 /* if next char will not fit, use a space */
655 if (m
+ t
> drw_1
.vx
+ drw_1
.tx
)
660 n
= m
+ t
- drw_1
.vx
;
664 /* fill the string */
671 if (drw_2
.ptr
[o
] == L
'\0' || drw_2
.ptr
[o
] == L
'\n')
675 return drw_push_pair(l
, i
, a
, tmp
);
679 static mpdm_t
drw_as_array(void)
680 /* returns an mpdm array of ty elements, which are also arrays of
681 attribute - string pairs */
686 /* the array of lines */
687 a
= MPDM_A(drw_1
.ty
);
690 for (n
= 0; n
< drw_1
.ty
; n
++)
691 mpdm_aset(a
, drw_line(n
), n
);
697 static mpdm_t
drw_optimize_array(mpdm_t a
, int optimize
)
698 /* optimizes the array, NULLifying all lines that are the same as the last time */
700 mpdm_t o
= drw_2
.old
;
703 if (optimize
&& o
!= NULL
) {
709 /* compare each array */
710 while (n
< mpdm_size(o
) && n
< mpdm_size(r
)) {
711 /* if both lines are equal, optimize out */
712 if (mpdm_cmp(mpdm_aget(o
, n
), mpdm_aget(r
, n
)) == 0)
713 mpdm_aset(r
, NULL
, n
);
719 mpdm_unref(drw_2
.old
);
720 drw_2
.old
= mpdm_ref(a
);
726 static void drw_restore_attrs(void)
727 /* restored the patched attrs */
729 /* matching paren, if any */
730 if (drw_2
.matchparen_offset
!= -1)
731 drw_fill_attr(drw_2
.matchparen_o_attr
, drw_2
.matchparen_offset
, 1);
734 drw_fill_attr(drw_2
.cursor_o_attr
, drw_2
.cursor
, 1);
736 /* marked block, if any */
737 if (drw_2
.mark_o_attr
!= NULL
) {
738 memcpy(&drw_2
.attrs
[drw_2
.mark_offset
], drw_2
.mark_o_attr
, drw_2
.mark_size
);
740 free(drw_2
.mark_o_attr
);
741 drw_2
.mark_o_attr
= NULL
;
746 static mpdm_t
drw_draw(mpdm_t doc
, int optimize
)
747 /* main document drawing function: takes a document and returns an array of
748 arrays of attribute / string pairs */
752 if (drw_prepare(doc
)) {
753 /* colorize separate words */
756 /* colorize multiline blocks */
760 /* now set the marked block (if any) */
763 /* colorize the search hit */
769 /* highlight the matching paren */
770 drw_matching_paren();
772 /* convert to an array of string / atribute pairs */
776 r
= drw_optimize_array(r
, optimize
);
778 /* restore the patched attrs */
785 mpdm_t
mp_draw(mpdm_t doc
, int optimize
)
786 /* main generic drawing function: if the document has a 'paint' code,
787 calls it; otherwise, call drw_draw() */
790 static int ppp
= 0; /* previous private paint */
793 /* if previous paint was private, disable optimizations */
798 if ((f
= mpdm_hget_s(doc
, L
"paint")) != NULL
) {
800 r
= mpdm_exec_2(f
, doc
, MPDM_I(optimize
));
803 r
= drw_draw(doc
, optimize
);
806 /* if there is a global post_paint function, execute it */
807 if ((f
= mpdm_hget_s(mp
, L
"post_paint")) != NULL
)
808 r
= mpdm_exec_1(f
, r
);
810 /* if doc has a post_paint function, execute it */
811 if ((f
= mpdm_hget_s(doc
, L
"post_paint")) != NULL
)
812 r
= mpdm_exec_1(f
, r
);
818 #define THR_SPEED_STEP 10
819 #define THR_MAX_SPEED 7
821 int mp_keypress_throttle(int keydown
)
822 /* processes key acceleration and throttle */
824 static int keydowns
= 0;
831 /* as keydowns accumulate, speed increases, which is the number
832 of cycles the redraw will be skipped (up to a maximum) */
833 if ((speed
= 1 + (++keydowns
/ THR_SPEED_STEP
)) > THR_MAX_SPEED
)
834 speed
= THR_MAX_SPEED
;
836 if (++seq
% speed
== 0)
850 mpdm_t
mp_active(void)
851 /* interface to mp.active() */
853 return mpdm_exec(mpdm_hget_s(mp
, L
"active"), NULL
);
857 mpdm_t
mp_process_action(mpdm_t action
)
858 /* interface to mp.process_action() */
860 return mpdm_exec_1(mpdm_hget_s(mp
, L
"process_action"), action
);
864 mpdm_t
mp_process_event(mpdm_t keycode
)
865 /* interface to mp.process_event() */
867 return mpdm_exec_1(mpdm_hget_s(mp
, L
"process_event"), keycode
);
871 mpdm_t
mp_set_y(mpdm_t doc
, int y
)
872 /* interface to mp.set_y() */
874 return mpdm_exec_2(mpdm_hget_s(mp
, L
"set_y"), doc
, MPDM_I(y
));
878 mpdm_t
mp_build_status_line(void)
879 /* interface to mp.build_status_line() */
881 return mpdm_exec(mpdm_hget_s(mp
, L
"build_status_line"), NULL
);
885 mpdm_t
mp_get_history(mpdm_t key
)
886 /* interface to mp.get_history() */
888 return mpdm_exec_1(mpdm_hget_s(mp
, L
"get_history"), key
);
892 mpdm_t
mp_get_doc_names(void)
893 /* interface to mp.get_doc_names() */
895 return mpdm_exec(mpdm_hget_s(mp
, L
"get_doc_names"), NULL
);
899 mpdm_t
mp_menu_label(mpdm_t action
)
900 /* interface to mp.menu_label() */
902 return mpdm_exec_1(mpdm_hget_s(mp
, L
"menu_label"), action
);
906 mpdm_t
mp_pending_key(void)
907 /* interface to mp.pending_key() */
909 return mpdm_exec_1(mpdm_hget_s(mp
, L
"pending_key"), NULL
);
913 mpdm_t
mp_process_keyseq(mpdm_t key
)
914 /* interface to mp.process_keyseq() */
916 return mpdm_exec_1(mpdm_hget_s(mp
, L
"process_keyseq"), key
);
920 mpdm_t
mp_exit(mpdm_t args
)
921 /* exit the editor (set mp_exit_requested) */
923 mp_exit_requested
= 1;
929 mpdm_t
mp_vx2x(mpdm_t args
)
930 /* interface to drw_vx2x() */
932 return MPDM_I(drw_vx2x(mpdm_aget(args
, 0), mpdm_ival(mpdm_aget(args
, 1))));
936 mpdm_t
mp_x2vx(mpdm_t args
)
937 /* interface to drw_x2vx() */
939 return MPDM_I(drw_x2vx(mpdm_aget(args
, 0), mpdm_ival(mpdm_aget(args
, 1))));
942 mpdm_t
mp_plain_load(mpdm_t args
)
943 /* loads a plain file into an array (highly optimized one) */
945 mpdm_t f
= mpdm_aget(args
, 0);
946 mpdm_t a
= MPDM_A(0);
950 while ((v
= mpdm_read(f
)) != NULL
) {
951 const wchar_t *ptr
= v
->data
;
955 if (size
&& ptr
[size
- 1] == L
'\n') {
956 if (--size
&& ptr
[size
- 1] == L
'\r')
962 mpdm_push(a
, MPDM_NS(ptr
, size
));
966 /* if last line was chomped, add a last, empty one */
968 mpdm_push(a
, MPDM_LS(L
""));
974 void mp_startup(int argc
, char *argv
[])
980 /* reset the structures */
981 memset(&drw_1
, '\0', sizeof(drw_1
));
982 memset(&drw_1_o
, '\0', sizeof(drw_1_o
));
984 /* create main namespace */
986 mpdm_hset_s(mpdm_root(), L
"mp", mp
);
988 /* basic functions and data */
989 mpdm_hset_s(mp
, L
"x2vx", MPDM_X(mp_x2vx
));
990 mpdm_hset_s(mp
, L
"vx2x", MPDM_X(mp_vx2x
));
991 mpdm_hset_s(mp
, L
"exit", MPDM_X(mp_exit
));
992 mpdm_hset_s(mp
, L
"plain_load", MPDM_X(mp_plain_load
));
993 mpdm_hset_s(mp
, L
"window", MPDM_H(0));
994 mpdm_hset_s(mp
, L
"drv", MPDM_H(0));
997 mpdm_hset_s(mp
, L
"VERSION", MPDM_S(L
"" VERSION
));
999 /* creates the INC (executable path) array */
1002 /* add installed library path */
1003 mpdm_push(INC
, mpdm_strcat(mpdm_hget_s(mpdm_root(), L
"APPDIR"),
1004 MPDM_MBS(CONFOPT_APPNAME
))
1008 mpdm_hset_s(mpdm_root(), L
"INC", INC
);
1010 if (!TRY_DRIVERS()) {
1011 printf("No usable driver found; exiting.\n");
1015 mpsl_argv(argc
, argv
);
1023 mpsl_eval(MPDM_LS(L
"load('mp_core.mpsl');"), NULL
);
1025 if ((e
= mpdm_hget_s(mpdm_root(), L
"ERROR")) != NULL
) {
1026 mpdm_write_wcs(stdout
, mpdm_string(e
));
1032 void mp_shutdown(void)
1038 int main(int argc
, char *argv
[])
1040 mp_startup(argc
, argv
);