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
40 int mp_exit_requested
= 0;
45 /** private data for drawing syntax-highlighted text **/
48 mpdm_t txt
; /* the document */
49 mpdm_t syntax
; /* syntax highlight information */
50 mpdm_t colors
; /* color definitions (for attributes) */
51 mpdm_t word_color_func
; /* word color function (just for detection) */
52 mpdm_t last_search
; /* last search regex */
53 int normal_attr
; /* normal attr */
54 int cursor_attr
; /* cursor attr */
55 int n_lines
; /* number of processed lines */
56 int p_lines
; /* number of prereaded lines */
57 int t_lines
; /* total lines in document */
58 int vx
; /* first visible column */
59 int vy
; /* first visible line */
60 int tx
; /* horizontal window size */
61 int ty
; /* vertical window size */
62 int tab_size
; /* tabulator size */
63 int mod
; /* modify count */
64 int preread_lines
; /* lines to pre-read (for synhi blocks) */
65 int mark_eol
; /* mark end of lines */
68 struct drw_1_info drw_1
;
69 struct drw_1_info drw_1_o
;
74 int *offsets
; /* offsets of lines */
75 char *attrs
; /* attributes */
76 int visible
; /* offset to the first visible character */
77 int cursor
; /* offset to cursor */
78 wchar_t *ptr
; /* pointer to joined data */
79 int size
; /* size of joined data */
80 int matchparen_offset
; /* offset to matched paren */
81 int matchparen_o_attr
; /* original attribute there */
82 int cursor_o_attr
; /* original attribute under cursor */
83 mpdm_t v
; /* the data */
84 mpdm_t old
; /* the previously generated array */
85 int mark_offset
; /* offset to the marked block */
86 int mark_size
; /* size of mark_o_attr */
87 char *mark_o_attr
; /* saved attributes for the mark */
92 #define MP_REAL_TAB_SIZE(x) (drw_1.tab_size - ((x) % drw_1.tab_size))
94 static int drw_wcwidth(int x
, wchar_t c
)
95 /* returns the wcwidth of c, or the tab spaces for
96 the x column if it's a tab */
105 r
= MP_REAL_TAB_SIZE(x
);
112 return r
< 0 ? 1 : r
;
116 int drw_vx2x(mpdm_t str
, int vx
)
117 /* returns the character in str that is on column vx */
119 const wchar_t *ptr
= str
->data
;
122 for (n
= x
= 0; n
< vx
&& ptr
[x
] != L
'\0'; x
++)
123 n
+= drw_wcwidth(n
, ptr
[x
]);
129 int drw_x2vx(mpdm_t str
, int x
)
130 /* returns the column where the character at offset x seems to be */
132 const wchar_t *ptr
= str
->data
;
135 for (n
= vx
= 0; n
< x
&& ptr
[n
] != L
'\0'; n
++)
136 vx
+= drw_wcwidth(vx
, ptr
[n
]);
142 static int drw_line_offset(int l
)
143 /* returns the offset into v for line number l */
145 return drw_2
.offsets
[l
- drw_1
.vy
+ drw_1
.p_lines
];
149 static int drw_adjust_y(int y
, int *vy
, int ty
)
150 /* adjusts the visual y position */
154 /* is y above the first visible line? */
158 /* is y below the last visible line? */
159 if (y
> *vy
+ (ty
- 2))
166 static int drw_adjust_x(int x
, int y
, int *vx
, int tx
, wchar_t * ptr
)
167 /* adjust the visual x position */
172 /* calculate the column for the cursor position */
173 for (n
= m
= 0; n
< x
; n
++, ptr
++)
174 m
+= drw_wcwidth(m
, *ptr
);
176 /* if new cursor column is nearer the leftmost column, set */
180 /* if new cursor column is further the rightmost column, set */
181 if (m
> *vx
+ (tx
- 1))
188 static int drw_get_attr(wchar_t * color_name
)
189 /* returns the attribute number for a color */
194 if ((v
= mpdm_hget_s(drw_1
.colors
, color_name
)) != NULL
)
195 attr
= mpdm_ival(mpdm_hget_s(v
, L
"attr"));
201 static int drw_prepare(mpdm_t doc
)
202 /* prepares the document for screen drawing */
204 mpdm_t window
= mpdm_hget_s(mp
, L
"window");
205 mpdm_t config
= mpdm_hget_s(mp
, L
"config");
206 mpdm_t txt
= mpdm_hget_s(doc
, L
"txt");
207 mpdm_t lines
= mpdm_hget_s(txt
, L
"lines");
208 int x
= mpdm_ival(mpdm_hget_s(txt
, L
"x"));
209 int y
= mpdm_ival(mpdm_hget_s(txt
, L
"y"));
212 drw_1
.vx
= mpdm_ival(mpdm_hget_s(txt
, L
"vx"));
213 drw_1
.vy
= mpdm_ival(mpdm_hget_s(txt
, L
"vy"));
214 drw_1
.tx
= mpdm_ival(mpdm_hget_s(window
, L
"tx"));
215 drw_1
.ty
= mpdm_ival(mpdm_hget_s(window
, L
"ty"));
216 drw_1
.tab_size
= mpdm_ival(mpdm_hget_s(config
, L
"tab_size"));
217 drw_1
.mod
= mpdm_ival(mpdm_hget_s(txt
, L
"mod"));
218 drw_1
.preread_lines
= mpdm_ival(mpdm_hget_s(config
, L
"preread_lines"));
219 drw_1
.mark_eol
= mpdm_ival(mpdm_hget_s(config
, L
"mark_eol"));
220 drw_1
.t_lines
= mpdm_size(lines
);
222 /* adjust the visual y coordinate */
223 if (drw_adjust_y(y
, &drw_1
.vy
, drw_1
.ty
))
224 mpdm_hset_s(txt
, L
"vy", MPDM_I(drw_1
.vy
));
226 /* adjust the visual x coordinate */
227 if (drw_adjust_x(x
, y
, &drw_1
.vx
, drw_1
.tx
, mpdm_string(mpdm_aget(lines
, y
))))
228 mpdm_hset_s(txt
, L
"vx", MPDM_I(drw_1
.vx
));
230 /* get the maximum prereadable lines */
231 drw_1
.p_lines
= drw_1
.vy
> drw_1
.preread_lines
? drw_1
.preread_lines
: drw_1
.vy
;
234 drw_1
.n_lines
= drw_1
.ty
+ drw_1
.p_lines
;
236 /* get the mp.colors structure and the most used attributes */
237 drw_1
.colors
= mpdm_hget_s(mp
, L
"colors");
238 drw_1
.normal_attr
= drw_get_attr(L
"normal");
239 drw_1
.cursor_attr
= drw_get_attr(L
"cursor");
241 /* store the syntax highlight structure */
242 drw_1
.syntax
= mpdm_hget_s(doc
, L
"syntax");
244 drw_1
.word_color_func
= mpdm_hget_s(mp
, L
"word_color_func");
246 mpdm_unref(drw_1
.txt
);
247 drw_1
.txt
= mpdm_ref(txt
);
252 /* last search regex */
253 drw_1
.last_search
= mpdm_hget_s(mp
, L
"last_search");
255 /* compare drw_1 with drw_1_o; if they are the same,
256 no more expensive calculations on drw_2 are needed */
257 if (memcmp(&drw_1
, &drw_1_o
, sizeof(drw_1
)) == 0)
260 /* different; store now */
261 memcpy(&drw_1_o
, &drw_1
, sizeof(drw_1_o
));
263 /* alloc space for line offsets */
264 drw_2
.offsets
= realloc(drw_2
.offsets
, drw_1
.n_lines
* sizeof(int));
270 drw_2
.ptr
= mpdm_pokev(drw_2
.ptr
, &drw_2
.size
,
271 mpdm_aget(lines
, drw_1
.vy
- drw_1
.p_lines
));
273 /* first line start at 0 */
274 drw_2
.offsets
[0] = 0;
276 /* add the following lines and store their offsets */
277 for (n
= 1; n
< drw_1
.n_lines
; n
++) {
278 /* add the separator */
279 drw_2
.ptr
= mpdm_poke(drw_2
.ptr
, &drw_2
.size
, L
"\n", 1, sizeof(wchar_t));
281 /* this line starts here */
282 drw_2
.offsets
[n
] = drw_2
.size
;
285 drw_2
.ptr
= mpdm_pokev(drw_2
.ptr
, &drw_2
.size
,
286 mpdm_aget(lines
, n
+ drw_1
.vy
- drw_1
.p_lines
));
289 drw_2
.ptr
= mpdm_poke(drw_2
.ptr
, &drw_2
.size
, L
"", 1, sizeof(wchar_t));
292 /* now create a value */
294 drw_2
.v
= mpdm_ref(MPDM_ENS(drw_2
.ptr
, drw_2
.size
));
296 /* alloc and init space for the attributes */
297 drw_2
.attrs
= realloc(drw_2
.attrs
, drw_2
.size
+ 1);
298 memset(drw_2
.attrs
, drw_1
.normal_attr
, drw_2
.size
+ 1);
300 drw_2
.visible
= drw_line_offset(drw_1
.vy
);
306 static int drw_fill_attr(int attr
, int offset
, int size
)
307 /* fill an attribute */
310 memset(drw_2
.attrs
+ offset
, attr
, size
);
312 return offset
+ size
;
316 static int drw_fill_attr_regex(int attr
)
317 /* fills with an attribute the last regex match */
319 return drw_fill_attr(attr
, mpdm_regex_offset
, mpdm_regex_size
);
323 static void drw_words(void)
324 /* fills the attributes for separate words */
327 int o
= drw_2
.visible
;
328 mpdm_t word_color
= NULL
;
329 mpdm_t word_color_func
= NULL
;
331 /* take the hash of word colors, if any */
332 if ((word_color
= mpdm_hget_s(mp
, L
"word_color")) == NULL
)
335 /* get the regex for words */
336 if ((r
= mpdm_hget_s(mp
, L
"word_regex")) == NULL
)
339 /* get the word color function */
340 word_color_func
= mpdm_hget_s(mp
, L
"word_color_func");
342 while ((t
= mpdm_regex(r
, drw_2
.v
, o
)) != NULL
) {
346 if ((v
= mpdm_hget(word_color
, t
)) != NULL
)
348 else if (word_color_func
!= NULL
)
349 attr
= mpdm_ival(mpdm_exec_1(word_color_func
, t
));
351 o
= drw_fill_attr_regex(attr
);
356 static void drw_multiline_regex(mpdm_t a
, int attr
)
357 /* sets the attribute to all matching (possibly multiline) regexes */
361 for (n
= 0; n
< mpdm_size(a
); n
++) {
362 mpdm_t r
= mpdm_aget(a
, n
);
365 /* if the regex is an array, it's a pair of
366 'match from this' / 'match until this' */
367 if (r
->flags
& MPDM_MULTIPLE
) {
368 mpdm_t rs
= mpdm_aget(r
, 0);
369 mpdm_t re
= mpdm_aget(r
, 1);
371 while (mpdm_regex(rs
, drw_2
.v
, o
)) {
374 /* fill the matched part */
375 o
= drw_fill_attr_regex(attr
);
377 /* try to match the end */
378 if (mpdm_regex(re
, drw_2
.v
, o
)) {
379 /* found; fill the attribute
380 to the end of the match */
381 s
= mpdm_regex_size
+ (mpdm_regex_offset
- o
);
384 /* not found; fill to the end
390 o
= drw_fill_attr(attr
, o
, s
);
395 /* while the regex matches, fill attributes */
396 while (mpdm_regex(r
, drw_2
.v
, o
))
397 o
= drw_fill_attr_regex(attr
);
403 static void drw_blocks(void)
404 /* fill attributes for multiline blocks */
409 /* no definitions? return */
410 if (drw_1
.syntax
== NULL
|| (defs
= mpdm_hget_s(drw_1
.syntax
, L
"defs")) == NULL
)
413 for (n
= 0; n
< mpdm_size(defs
); n
+= 2) {
417 /* get the attribute */
418 attr
= mpdm_aget(defs
, n
);
419 attr
= mpdm_hget(drw_1
.colors
, attr
);
420 attr
= mpdm_hget_s(attr
, L
"attr");
422 /* get the list for this word color */
423 list
= mpdm_aget(defs
, n
+ 1);
425 drw_multiline_regex(list
, mpdm_ival(attr
));
430 static void drw_selection(void)
431 /* draws the selected block, if any */
434 int bx
, by
, ex
, ey
, vertical
;
437 int line_offset
, next_line_offset
;
442 /* no mark? return */
443 if ((mark
= mpdm_hget_s(drw_1
.txt
, L
"mark")) == NULL
)
446 bx
= mpdm_ival(mpdm_hget_s(mark
, L
"bx"));
447 by
= mpdm_ival(mpdm_hget_s(mark
, L
"by"));
448 ex
= mpdm_ival(mpdm_hget_s(mark
, L
"ex"));
449 ey
= mpdm_ival(mpdm_hget_s(mark
, L
"ey"));
450 vertical
= mpdm_ival(mpdm_hget_s(mark
, L
"vertical"));
452 /* if block is not visible, return */
453 if (ey
< drw_1
.vy
|| by
> drw_1
.vy
+ drw_1
.ty
)
456 so
= by
< drw_1
.vy
? drw_2
.visible
: drw_line_offset(by
) + bx
;
457 eo
= ey
>= drw_1
.vy
+ drw_1
.ty
? drw_2
.size
: drw_line_offset(ey
) + ex
;
459 /* alloc space and save the attributes being destroyed */
460 drw_2
.mark_offset
= so
;
461 drw_2
.mark_size
= eo
- so
+ 1;
462 drw_2
.mark_o_attr
= malloc(eo
- so
+ 1);
463 memcpy(drw_2
.mark_o_attr
, &drw_2
.attrs
[so
], eo
- so
+ 1);
466 /* normal selection */
467 drw_fill_attr(drw_get_attr(L
"selection"), so
, eo
- so
);
470 /* vertical selection */
471 mby
= by
< drw_1
.vy
? drw_1
.vy
: by
;
472 mey
= ey
>= drw_1
.vy
+ drw_1
.ty
? drw_1
.vy
+ drw_1
.ty
: ey
;
473 line_offset
= drw_line_offset(mby
);
474 attr
= drw_get_attr(L
"selection");
475 for (y
= mby
; y
<= mey
; y
++) {
476 next_line_offset
= drw_line_offset(y
+1);
477 len
= next_line_offset
- line_offset
- 1;
478 so
= bx
> len
? -1 : bx
;
479 eo
= ex
> len
? len
: ex
;
481 if (so
>= 0 && eo
>= so
)
482 drw_fill_attr(attr
, line_offset
+ so
, eo
- so
+ 1);
484 line_offset
= next_line_offset
;
490 static void drw_search_hit(void)
491 /* colorize the search hit, if any */
493 if (drw_1
.last_search
!= NULL
) {
494 mpdm_t l
= mpdm_ref(MPDM_A(0));
496 mpdm_aset(l
, drw_1
.last_search
, 0);
497 drw_multiline_regex(l
, drw_get_attr(L
"search"));
503 static void drw_cursor(void)
504 /* fill the attribute for the cursor */
506 /* calculate the cursor offset */
507 drw_2
.cursor
= drw_line_offset(drw_2
.y
) + drw_2
.x
;
509 drw_2
.cursor_o_attr
= drw_2
.attrs
[drw_2
.cursor
];
510 drw_fill_attr(drw_1
.cursor_attr
, drw_2
.cursor
, 1);
514 static void drw_matching_paren(void)
515 /* highlights the matching paren */
517 int o
= drw_2
.cursor
;
521 /* by default, no offset has been found */
522 drw_2
.matchparen_offset
= -1;
524 /* find the opposite and the increment (direction) */
525 switch (drw_2
.ptr
[o
]) {
552 /* if a direction is set, do the searching */
554 wchar_t s
= drw_2
.ptr
[o
];
556 int l
= i
== -1 ? drw_2
.visible
- 1 : drw_2
.size
;
559 if (drw_2
.ptr
[o
] == s
) {
563 else if (drw_2
.ptr
[o
] == c
) {
564 /* found the opposite */
566 /* found! fill and exit */
567 drw_2
.matchparen_offset
= o
;
568 drw_2
.matchparen_o_attr
= drw_2
.attrs
[o
];
569 drw_fill_attr(drw_get_attr(L
"matching"), o
, 1);
580 static mpdm_t
drw_push_pair(mpdm_t l
, int i
, int a
, wchar_t * tmp
)
581 /* pushes a pair of attribute / string into l */
583 /* create the array, if doesn't exist yet */
587 /* finish the string */
590 /* special magic: if the attribute is the
591 one of the cursor and the string is more than
592 one character, create two strings; the
593 cursor is over a tab */
594 if (a
== drw_1
.cursor_attr
&& i
> 1) {
595 mpdm_push(l
, MPDM_I(a
));
596 mpdm_push(l
, MPDM_NS(tmp
, 1));
598 /* the rest of the string has the original attr */
599 a
= drw_2
.cursor_o_attr
;
605 /* store the attribute and the string */
606 mpdm_push(l
, MPDM_I(a
));
607 mpdm_push(l
, MPDM_S(tmp
));
615 static mpdm_t
drw_line(int line
)
616 /* creates a list of attribute / string pairs for the current line */
620 int o
= drw_2
.offsets
[line
+ drw_1
.p_lines
];
621 int a
= drw_2
.attrs
[o
];
622 wchar_t tmp
[BUF_LINE
];
625 /* loop while not beyond the right margin */
626 for (m
= i
= 0; m
< drw_1
.vx
+ drw_1
.tx
; m
+= t
, o
++) {
627 /* take char and size */
629 t
= drw_wcwidth(m
, c
);
631 /* further the left margin? */
633 /* if the attribute is different or we're out of
634 temporary space, push and go on */
635 if (drw_2
.attrs
[o
] != a
|| i
>= BUF_LINE
- t
- 1) {
636 l
= drw_push_pair(l
, i
, a
, tmp
);
640 /* size is 1, unless it's a tab */
641 n
= c
== L
'\t' ? t
: 1;
643 /* fill tabs with spaces */
644 if (c
== L
'\0' || c
== L
'\t')
647 /* fill EOLs with special marks or spaces */
649 c
= drw_1
.mark_eol
? L
'\xb6' : L
' ';
651 /* if next char will not fit, use a space */
652 if (m
+ t
> drw_1
.vx
+ drw_1
.tx
)
657 n
= m
+ t
- drw_1
.vx
;
661 /* fill the string */
668 if (drw_2
.ptr
[o
] == L
'\0' || drw_2
.ptr
[o
] == L
'\n')
672 return drw_push_pair(l
, i
, a
, tmp
);
676 static mpdm_t
drw_as_array(void)
677 /* returns an mpdm array of ty elements, which are also arrays of
678 attribute - string pairs */
683 /* the array of lines */
684 a
= MPDM_A(drw_1
.ty
);
687 for (n
= 0; n
< drw_1
.ty
; n
++)
688 mpdm_aset(a
, drw_line(n
), n
);
694 static mpdm_t
drw_optimize_array(mpdm_t a
, int optimize
)
695 /* optimizes the array, NULLifying all lines that are the same as the last time */
697 mpdm_t o
= drw_2
.old
;
700 if (optimize
&& o
!= NULL
) {
706 /* compare each array */
707 while (n
< mpdm_size(o
) && n
< mpdm_size(r
)) {
708 /* if both lines are equal, optimize out */
709 if (mpdm_cmp(mpdm_aget(o
, n
), mpdm_aget(r
, n
)) == 0)
710 mpdm_aset(r
, NULL
, n
);
716 mpdm_unref(drw_2
.old
);
717 drw_2
.old
= mpdm_ref(a
);
723 static void drw_restore_attrs(void)
724 /* restored the patched attrs */
726 /* matching paren, if any */
727 if (drw_2
.matchparen_offset
!= -1)
728 drw_fill_attr(drw_2
.matchparen_o_attr
, drw_2
.matchparen_offset
, 1);
731 drw_fill_attr(drw_2
.cursor_o_attr
, drw_2
.cursor
, 1);
733 /* marked block, if any */
734 if (drw_2
.mark_o_attr
!= NULL
) {
735 memcpy(&drw_2
.attrs
[drw_2
.mark_offset
], drw_2
.mark_o_attr
, drw_2
.mark_size
);
737 free(drw_2
.mark_o_attr
);
738 drw_2
.mark_o_attr
= NULL
;
743 static mpdm_t
drw_draw(mpdm_t doc
, int optimize
)
744 /* main document drawing function: takes a document and returns an array of
745 arrays of attribute / string pairs */
749 if (drw_prepare(doc
)) {
750 /* colorize separate words */
753 /* colorize multiline blocks */
757 /* now set the marked block (if any) */
760 /* colorize the search hit */
766 /* highlight the matching paren */
767 drw_matching_paren();
769 /* convert to an array of string / atribute pairs */
773 r
= drw_optimize_array(r
, optimize
);
775 /* restore the patched attrs */
784 mpdm_t
mp_draw(mpdm_t doc
, int optimize
)
785 /* main generic drawing function: if the document has a 'paint' code,
786 calls it; otherwise, call drw_draw() */
789 static int ppp
= 0; /* previous private paint */
792 /* if previous paint was private, disable optimizations */
797 if ((f
= mpdm_hget_s(doc
, L
"paint")) != NULL
) {
799 r
= mpdm_exec_2(f
, doc
, MPDM_I(optimize
));
802 r
= drw_draw(doc
, optimize
);
805 /* if there is a global post_paint function, execute it */
806 if ((f
= mpdm_hget_s(mp
, L
"post_paint")) != NULL
)
807 r
= mpdm_exec_1(f
, r
);
809 /* if doc has a post_paint function, execute it */
810 if ((f
= mpdm_hget_s(doc
, L
"post_paint")) != NULL
)
811 r
= mpdm_exec_1(f
, r
);
817 #define THR_SPEED_STEP 10
818 #define THR_MAX_SPEED 7
820 int mp_keypress_throttle(int keydown
)
821 /* processes key acceleration and throttle */
823 static int keydowns
= 0;
830 /* as keydowns accumulate, speed increases, which is the number
831 of cycles the redraw will be skipped (up to a maximum) */
832 if ((speed
= 1 + (++keydowns
/ THR_SPEED_STEP
)) > THR_MAX_SPEED
)
833 speed
= THR_MAX_SPEED
;
835 if (++seq
% speed
== 0)
849 mpdm_t
mp_active(void)
850 /* interface to mp.active() */
852 return mpdm_exec(mpdm_hget_s(mp
, L
"active"), NULL
);
856 mpdm_t
mp_process_action(mpdm_t action
)
857 /* interface to mp.process_action() */
859 return mpdm_exec_1(mpdm_hget_s(mp
, L
"process_action"), action
);
863 mpdm_t
mp_process_event(mpdm_t keycode
)
864 /* interface to mp.process_event() */
866 return mpdm_exec_1(mpdm_hget_s(mp
, L
"process_event"), keycode
);
870 mpdm_t
mp_set_y(mpdm_t doc
, int y
)
871 /* interface to mp.set_y() */
873 return mpdm_exec_2(mpdm_hget_s(mp
, L
"set_y"), doc
, MPDM_I(y
));
877 mpdm_t
mp_build_status_line(void)
878 /* interface to mp.build_status_line() */
880 return mpdm_exec(mpdm_hget_s(mp
, L
"build_status_line"), NULL
);
884 mpdm_t
mp_get_history(mpdm_t key
)
885 /* interface to mp.get_history() */
887 return mpdm_exec_1(mpdm_hget_s(mp
, L
"get_history"), key
);
891 mpdm_t
mp_get_doc_names(void)
892 /* interface to mp.get_doc_names() */
894 return mpdm_exec(mpdm_hget_s(mp
, L
"get_doc_names"), NULL
);
898 mpdm_t
mp_menu_label(mpdm_t action
)
899 /* interface to mp.menu_label() */
901 return mpdm_exec_1(mpdm_hget_s(mp
, L
"menu_label"), action
);
905 mpdm_t
mp_pending_key(void)
906 /* interface to mp.pending_key() */
908 return mpdm_exec_1(mpdm_hget_s(mp
, L
"pending_key"), NULL
);
912 mpdm_t
mp_process_keyseq(mpdm_t key
)
913 /* interface to mp.process_keyseq() */
915 return mpdm_exec_1(mpdm_hget_s(mp
, L
"process_keyseq"), key
);
919 mpdm_t
mp_exit(mpdm_t args
)
920 /* exit the editor (set mp_exit_requested) */
922 mp_exit_requested
= 1;
928 mpdm_t
mp_vx2x(mpdm_t args
)
929 /* interface to drw_vx2x() */
931 return MPDM_I(drw_vx2x(mpdm_aget(args
, 0), mpdm_ival(mpdm_aget(args
, 1))));
935 mpdm_t
mp_x2vx(mpdm_t args
)
936 /* interface to drw_x2vx() */
938 return MPDM_I(drw_x2vx(mpdm_aget(args
, 0), mpdm_ival(mpdm_aget(args
, 1))));
941 mpdm_t
mp_plain_load(mpdm_t args
)
942 /* loads a plain file into an array (highly optimized one) */
944 mpdm_t f
= mpdm_aget(args
, 0);
945 mpdm_t a
= MPDM_A(0);
949 while ((v
= mpdm_read(f
)) != NULL
) {
950 const wchar_t *ptr
= v
->data
;
954 if (size
&& ptr
[size
- 1] == L
'\n') {
955 if (--size
&& ptr
[size
- 1] == L
'\r')
961 mpdm_push(a
, MPDM_NS(ptr
, size
));
965 /* if last line was chomped, add a last, empty one */
967 mpdm_push(a
, MPDM_LS(L
""));
973 void mp_startup(int argc
, char *argv
[])
979 /* reset the structures */
980 memset(&drw_1
, '\0', sizeof(drw_1
));
981 memset(&drw_1_o
, '\0', sizeof(drw_1_o
));
983 /* create main namespace */
985 mpdm_hset_s(mpdm_root(), L
"mp", mp
);
987 /* basic functions and data */
988 mpdm_hset_s(mp
, L
"x2vx", MPDM_X(mp_x2vx
));
989 mpdm_hset_s(mp
, L
"vx2x", MPDM_X(mp_vx2x
));
990 mpdm_hset_s(mp
, L
"exit", MPDM_X(mp_exit
));
991 mpdm_hset_s(mp
, L
"plain_load", MPDM_X(mp_plain_load
));
992 mpdm_hset_s(mp
, L
"window", MPDM_H(0));
993 mpdm_hset_s(mp
, L
"drv", MPDM_H(0));
996 mpdm_hset_s(mp
, L
"VERSION", MPDM_S(L
"" VERSION
));
998 /* creates the INC (executable path) array */
1001 /* add installed library path */
1002 mpdm_push(INC
, mpdm_strcat(mpdm_hget_s(mpdm_root(), L
"APPDIR"),
1003 MPDM_MBS(CONFOPT_APPNAME
))
1007 mpdm_hset_s(mpdm_root(), L
"INC", INC
);
1009 if (!TRY_DRIVERS()) {
1010 printf("No usable driver found; exiting.\n");
1014 mpsl_argv(argc
, argv
);
1022 mpsl_eval(MPDM_LS(L
"load('mp_core.mpsl');"), NULL
);
1024 if ((e
= mpdm_hget_s(mpdm_root(), L
"ERROR")) != NULL
) {
1025 mpdm_write_wcs(stdout
, mpdm_string(e
));
1031 void mp_shutdown(void)
1037 int main(int argc
, char *argv
[])
1039 mp_startup(argc
, argv
);