3 Minimum Profit - Programmer Text Editor
5 Copyright (C) 1991-2009 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 */
66 int redraw
; /* redraw trigger */
69 struct drw_1_info drw_1
;
70 struct drw_1_info drw_1_o
;
75 int *offsets
; /* offsets of lines */
76 char *attrs
; /* attributes */
77 int visible
; /* offset to the first visible character */
78 int cursor
; /* offset to cursor */
79 wchar_t *ptr
; /* pointer to joined data */
80 int size
; /* size of joined data */
81 int matchparen_offset
; /* offset to matched paren */
82 int matchparen_o_attr
; /* original attribute there */
83 int cursor_o_attr
; /* original attribute under cursor */
84 mpdm_t v
; /* the data */
85 mpdm_t old
; /* the previously generated array */
86 int mark_offset
; /* offset to the marked block */
87 int mark_size
; /* size of mark_o_attr */
88 char *mark_o_attr
; /* saved attributes for the mark */
93 #define MP_REAL_TAB_SIZE(x) (drw_1.tab_size - ((x) % drw_1.tab_size))
95 static int drw_wcwidth(int x
, wchar_t c
)
96 /* returns the wcwidth of c, or the tab spaces for
97 the x column if it's a tab */
106 r
= MP_REAL_TAB_SIZE(x
);
113 return r
< 0 ? 1 : r
;
117 int drw_vx2x(mpdm_t str
, int vx
)
118 /* returns the character in str that is on column vx */
120 const wchar_t *ptr
= str
->data
;
123 for (n
= x
= 0; n
< vx
&& ptr
[x
] != L
'\0'; x
++)
124 n
+= drw_wcwidth(n
, ptr
[x
]);
130 int drw_x2vx(mpdm_t str
, int x
)
131 /* returns the column where the character at offset x seems to be */
133 const wchar_t *ptr
= str
->data
;
136 for (n
= vx
= 0; n
< x
&& ptr
[n
] != L
'\0'; n
++)
137 vx
+= drw_wcwidth(vx
, ptr
[n
]);
143 static int drw_line_offset(int l
)
144 /* returns the offset into v for line number l */
146 return drw_2
.offsets
[l
- drw_1
.vy
+ drw_1
.p_lines
];
150 static int drw_adjust_y(int y
, int *vy
, int ty
)
151 /* adjusts the visual y position */
155 /* is y above the first visible line? */
159 /* is y below the last visible line? */
160 if (y
> *vy
+ (ty
- 2))
167 static int drw_adjust_x(int x
, int y
, int *vx
, int tx
, wchar_t * ptr
)
168 /* adjust the visual x position */
173 /* calculate the column for the cursor position */
174 for (n
= m
= 0; n
< x
; n
++, ptr
++)
175 m
+= drw_wcwidth(m
, *ptr
);
177 /* if new cursor column is nearer the leftmost column, set */
181 /* if new cursor column is further the rightmost column, set */
182 if (m
> *vx
+ (tx
- 1))
189 static int drw_get_attr(wchar_t * color_name
)
190 /* returns the attribute number for a color */
195 if ((v
= mpdm_hget_s(drw_1
.colors
, color_name
)) != NULL
)
196 attr
= mpdm_ival(mpdm_hget_s(v
, L
"attr"));
202 static int drw_prepare(mpdm_t doc
)
203 /* prepares the document for screen drawing */
205 mpdm_t window
= mpdm_hget_s(mp
, L
"window");
206 mpdm_t config
= mpdm_hget_s(mp
, L
"config");
207 mpdm_t txt
= mpdm_hget_s(doc
, L
"txt");
208 mpdm_t lines
= mpdm_hget_s(txt
, L
"lines");
209 int x
= mpdm_ival(mpdm_hget_s(txt
, L
"x"));
210 int y
= mpdm_ival(mpdm_hget_s(txt
, L
"y"));
213 drw_1
.vx
= mpdm_ival(mpdm_hget_s(txt
, L
"vx"));
214 drw_1
.vy
= mpdm_ival(mpdm_hget_s(txt
, L
"vy"));
215 drw_1
.tx
= mpdm_ival(mpdm_hget_s(window
, L
"tx"));
216 drw_1
.ty
= mpdm_ival(mpdm_hget_s(window
, L
"ty"));
217 drw_1
.tab_size
= mpdm_ival(mpdm_hget_s(config
, L
"tab_size"));
218 drw_1
.mod
= mpdm_ival(mpdm_hget_s(txt
, L
"mod"));
219 drw_1
.preread_lines
= mpdm_ival(mpdm_hget_s(config
, L
"preread_lines"));
220 drw_1
.mark_eol
= mpdm_ival(mpdm_hget_s(config
, L
"mark_eol"));
221 drw_1
.t_lines
= mpdm_size(lines
);
223 /* adjust the visual y coordinate */
224 if (drw_adjust_y(y
, &drw_1
.vy
, drw_1
.ty
))
225 mpdm_hset_s(txt
, L
"vy", MPDM_I(drw_1
.vy
));
227 /* adjust the visual x coordinate */
228 if (drw_adjust_x(x
, y
, &drw_1
.vx
, drw_1
.tx
, mpdm_string(mpdm_aget(lines
, y
))))
229 mpdm_hset_s(txt
, L
"vx", MPDM_I(drw_1
.vx
));
231 /* get the maximum prereadable lines */
232 drw_1
.p_lines
= drw_1
.vy
> drw_1
.preread_lines
? drw_1
.preread_lines
: drw_1
.vy
;
235 drw_1
.n_lines
= drw_1
.ty
+ drw_1
.p_lines
;
237 /* get the mp.colors structure and the most used attributes */
238 drw_1
.colors
= mpdm_hget_s(mp
, L
"colors");
239 drw_1
.normal_attr
= drw_get_attr(L
"normal");
240 drw_1
.cursor_attr
= drw_get_attr(L
"cursor");
242 /* store the syntax highlight structure */
243 drw_1
.syntax
= mpdm_hget_s(doc
, L
"syntax");
245 drw_1
.word_color_func
= mpdm_hget_s(mp
, L
"word_color_func");
247 mpdm_unref(drw_1
.txt
);
248 drw_1
.txt
= mpdm_ref(txt
);
253 /* last search regex */
254 drw_1
.last_search
= mpdm_hget_s(mp
, L
"last_search");
257 drw_1
.redraw
= mpdm_ival(mpdm_hget_s(mp
, L
"redraw_counter"));
259 /* compare drw_1 with drw_1_o; if they are the same,
260 no more expensive calculations on drw_2 are needed */
261 if (memcmp(&drw_1
, &drw_1_o
, sizeof(drw_1
)) == 0)
264 /* different; store now */
265 memcpy(&drw_1_o
, &drw_1
, sizeof(drw_1_o
));
267 /* alloc space for line offsets */
268 drw_2
.offsets
= realloc(drw_2
.offsets
, drw_1
.n_lines
* sizeof(int));
274 drw_2
.ptr
= mpdm_pokev(drw_2
.ptr
, &drw_2
.size
,
275 mpdm_aget(lines
, drw_1
.vy
- drw_1
.p_lines
));
277 /* first line start at 0 */
278 drw_2
.offsets
[0] = 0;
280 /* add the following lines and store their offsets */
281 for (n
= 1; n
< drw_1
.n_lines
; n
++) {
282 /* add the separator */
283 drw_2
.ptr
= mpdm_poke(drw_2
.ptr
, &drw_2
.size
, L
"\n", 1, sizeof(wchar_t));
285 /* this line starts here */
286 drw_2
.offsets
[n
] = drw_2
.size
;
289 drw_2
.ptr
= mpdm_pokev(drw_2
.ptr
, &drw_2
.size
,
290 mpdm_aget(lines
, n
+ drw_1
.vy
- drw_1
.p_lines
));
293 drw_2
.ptr
= mpdm_poke(drw_2
.ptr
, &drw_2
.size
, L
"", 1, sizeof(wchar_t));
296 /* now create a value */
298 drw_2
.v
= mpdm_ref(MPDM_ENS(drw_2
.ptr
, drw_2
.size
));
300 /* alloc and init space for the attributes */
301 drw_2
.attrs
= realloc(drw_2
.attrs
, drw_2
.size
+ 1);
302 memset(drw_2
.attrs
, drw_1
.normal_attr
, drw_2
.size
+ 1);
304 drw_2
.visible
= drw_line_offset(drw_1
.vy
);
310 static int drw_fill_attr(int attr
, int offset
, int size
)
311 /* fill an attribute */
314 memset(drw_2
.attrs
+ offset
, attr
, size
);
316 return offset
+ size
;
320 static int drw_fill_attr_regex(int attr
)
321 /* fills with an attribute the last regex match */
323 return drw_fill_attr(attr
, mpdm_regex_offset
, mpdm_regex_size
);
327 static void drw_words(void)
328 /* fills the attributes for separate words */
331 int o
= drw_2
.visible
;
332 mpdm_t word_color
= NULL
;
333 mpdm_t word_color_func
= NULL
;
335 /* take the hash of word colors, if any */
336 if ((word_color
= mpdm_hget_s(mp
, L
"word_color")) == NULL
)
339 /* get the regex for words */
340 if ((r
= mpdm_hget_s(mp
, L
"word_regex")) == NULL
)
343 /* get the word color function */
344 word_color_func
= mpdm_hget_s(mp
, L
"word_color_func");
346 while ((t
= mpdm_regex(r
, drw_2
.v
, o
)) != NULL
) {
350 if ((v
= mpdm_hget(word_color
, t
)) != NULL
)
352 else if (word_color_func
!= NULL
)
353 attr
= mpdm_ival(mpdm_exec_1(word_color_func
, t
));
355 o
= drw_fill_attr_regex(attr
);
360 static void drw_multiline_regex(mpdm_t a
, int attr
)
361 /* sets the attribute to all matching (possibly multiline) regexes */
365 for (n
= 0; n
< mpdm_size(a
); n
++) {
366 mpdm_t r
= mpdm_aget(a
, n
);
369 /* if the regex is an array, it's a pair of
370 'match from this' / 'match until this' */
371 if (r
->flags
& MPDM_MULTIPLE
) {
372 mpdm_t rs
= mpdm_aget(r
, 0);
373 mpdm_t re
= mpdm_aget(r
, 1);
375 while (mpdm_regex(rs
, drw_2
.v
, o
)) {
378 /* fill the matched part */
379 o
= drw_fill_attr_regex(attr
);
381 /* try to match the end */
382 if (mpdm_regex(re
, drw_2
.v
, o
)) {
383 /* found; fill the attribute
384 to the end of the match */
385 s
= mpdm_regex_size
+ (mpdm_regex_offset
- o
);
388 /* not found; fill to the end
394 o
= drw_fill_attr(attr
, o
, s
);
399 /* while the regex matches, fill attributes */
400 while (mpdm_regex(r
, drw_2
.v
, o
))
401 o
= drw_fill_attr_regex(attr
);
407 static void drw_blocks(void)
408 /* fill attributes for multiline blocks */
413 /* no definitions? return */
414 if (drw_1
.syntax
== NULL
|| (defs
= mpdm_hget_s(drw_1
.syntax
, L
"defs")) == NULL
)
417 for (n
= 0; n
< mpdm_size(defs
); n
+= 2) {
421 /* get the attribute */
422 attr
= mpdm_aget(defs
, n
);
423 attr
= mpdm_hget(drw_1
.colors
, attr
);
424 attr
= mpdm_hget_s(attr
, L
"attr");
426 /* get the list for this word color */
427 list
= mpdm_aget(defs
, n
+ 1);
429 drw_multiline_regex(list
, mpdm_ival(attr
));
434 static void drw_selection(void)
435 /* draws the selected block, if any */
438 int bx
, by
, ex
, ey
, vertical
;
441 int line_offset
, next_line_offset
;
446 /* no mark? return */
447 if ((mark
= mpdm_hget_s(drw_1
.txt
, L
"mark")) == NULL
)
450 bx
= mpdm_ival(mpdm_hget_s(mark
, L
"bx"));
451 by
= mpdm_ival(mpdm_hget_s(mark
, L
"by"));
452 ex
= mpdm_ival(mpdm_hget_s(mark
, L
"ex"));
453 ey
= mpdm_ival(mpdm_hget_s(mark
, L
"ey"));
454 vertical
= mpdm_ival(mpdm_hget_s(mark
, L
"vertical"));
456 /* if block is not visible, return */
457 if (ey
< drw_1
.vy
|| by
> drw_1
.vy
+ drw_1
.ty
)
460 so
= by
< drw_1
.vy
? drw_2
.visible
: drw_line_offset(by
) + bx
;
461 eo
= ey
>= drw_1
.vy
+ drw_1
.ty
? drw_2
.size
: drw_line_offset(ey
) + ex
;
463 /* alloc space and save the attributes being destroyed */
464 drw_2
.mark_offset
= so
;
465 drw_2
.mark_size
= eo
- so
+ 1;
466 drw_2
.mark_o_attr
= malloc(eo
- so
+ 1);
467 memcpy(drw_2
.mark_o_attr
, &drw_2
.attrs
[so
], eo
- so
+ 1);
470 /* normal selection */
471 drw_fill_attr(drw_get_attr(L
"selection"), so
, eo
- so
);
474 /* vertical selection */
475 mby
= by
< drw_1
.vy
? drw_1
.vy
: by
;
476 mey
= ey
>= drw_1
.vy
+ drw_1
.ty
? drw_1
.vy
+ drw_1
.ty
: ey
;
477 line_offset
= drw_line_offset(mby
);
478 attr
= drw_get_attr(L
"selection");
479 for (y
= mby
; y
<= mey
; y
++) {
480 next_line_offset
= drw_line_offset(y
+1);
481 len
= next_line_offset
- line_offset
- 1;
482 so
= bx
> len
? -1 : bx
;
483 eo
= ex
> len
? len
: ex
;
485 if (so
>= 0 && eo
>= so
)
486 drw_fill_attr(attr
, line_offset
+ so
, eo
- so
+ 1);
488 line_offset
= next_line_offset
;
494 static void drw_search_hit(void)
495 /* colorize the search hit, if any */
497 if (drw_1
.last_search
!= NULL
) {
498 mpdm_t l
= mpdm_ref(MPDM_A(0));
500 mpdm_aset(l
, drw_1
.last_search
, 0);
501 drw_multiline_regex(l
, drw_get_attr(L
"search"));
507 static void drw_cursor(void)
508 /* fill the attribute for the cursor */
510 /* calculate the cursor offset */
511 drw_2
.cursor
= drw_line_offset(drw_2
.y
) + drw_2
.x
;
513 drw_2
.cursor_o_attr
= drw_2
.attrs
[drw_2
.cursor
];
514 drw_fill_attr(drw_1
.cursor_attr
, drw_2
.cursor
, 1);
518 static void drw_matching_paren(void)
519 /* highlights the matching paren */
521 int o
= drw_2
.cursor
;
525 /* by default, no offset has been found */
526 drw_2
.matchparen_offset
= -1;
528 /* find the opposite and the increment (direction) */
529 switch (drw_2
.ptr
[o
]) {
556 /* if a direction is set, do the searching */
558 wchar_t s
= drw_2
.ptr
[o
];
560 int l
= i
== -1 ? drw_2
.visible
- 1 : drw_2
.size
;
563 if (drw_2
.ptr
[o
] == s
) {
567 else if (drw_2
.ptr
[o
] == c
) {
568 /* found the opposite */
570 /* found! fill and exit */
571 drw_2
.matchparen_offset
= o
;
572 drw_2
.matchparen_o_attr
= drw_2
.attrs
[o
];
573 drw_fill_attr(drw_get_attr(L
"matching"), o
, 1);
584 static mpdm_t
drw_push_pair(mpdm_t l
, int i
, int a
, wchar_t * tmp
)
585 /* pushes a pair of attribute / string into l */
587 /* create the array, if doesn't exist yet */
591 /* finish the string */
594 /* special magic: if the attribute is the
595 one of the cursor and the string is more than
596 one character, create two strings; the
597 cursor is over a tab */
598 if (a
== drw_1
.cursor_attr
&& i
> 1) {
599 mpdm_push(l
, MPDM_I(a
));
600 mpdm_push(l
, MPDM_NS(tmp
, 1));
602 /* the rest of the string has the original attr */
603 a
= drw_2
.cursor_o_attr
;
609 /* store the attribute and the string */
610 mpdm_push(l
, MPDM_I(a
));
611 mpdm_push(l
, MPDM_S(tmp
));
619 static mpdm_t
drw_line(int line
)
620 /* creates a list of attribute / string pairs for the current line */
624 int o
= drw_2
.offsets
[line
+ drw_1
.p_lines
];
625 int a
= drw_2
.attrs
[o
];
626 wchar_t tmp
[BUF_LINE
];
629 /* loop while not beyond the right margin */
630 for (m
= i
= 0; m
< drw_1
.vx
+ drw_1
.tx
; m
+= t
, o
++) {
631 /* take char and size */
633 t
= drw_wcwidth(m
, c
);
635 /* further the left margin? */
637 /* if the attribute is different or we're out of
638 temporary space, push and go on */
639 if (drw_2
.attrs
[o
] != a
|| i
>= BUF_LINE
- t
- 1) {
640 l
= drw_push_pair(l
, i
, a
, tmp
);
644 /* size is 1, unless it's a tab */
645 n
= c
== L
'\t' ? t
: 1;
647 /* fill tabs with spaces */
648 if (c
== L
'\0' || c
== L
'\t')
651 /* fill EOLs with special marks or spaces */
653 c
= drw_1
.mark_eol
? L
'\xb6' : L
' ';
655 /* if next char will not fit, use a space */
656 if (m
+ t
> drw_1
.vx
+ drw_1
.tx
)
661 n
= m
+ t
- drw_1
.vx
;
665 /* fill the string */
672 if (drw_2
.ptr
[o
] == L
'\0' || drw_2
.ptr
[o
] == L
'\n')
676 return drw_push_pair(l
, i
, a
, tmp
);
680 static mpdm_t
drw_as_array(void)
681 /* returns an mpdm array of ty elements, which are also arrays of
682 attribute - string pairs */
687 /* the array of lines */
688 a
= MPDM_A(drw_1
.ty
);
691 for (n
= 0; n
< drw_1
.ty
; n
++)
692 mpdm_aset(a
, drw_line(n
), n
);
698 static mpdm_t
drw_optimize_array(mpdm_t a
, int optimize
)
699 /* optimizes the array, NULLifying all lines that are the same as the last time */
701 mpdm_t o
= drw_2
.old
;
704 if (optimize
&& o
!= NULL
) {
710 /* compare each array */
711 while (n
< mpdm_size(o
) && n
< mpdm_size(r
)) {
712 /* if both lines are equal, optimize out */
713 if (mpdm_cmp(mpdm_aget(o
, n
), mpdm_aget(r
, n
)) == 0)
714 mpdm_aset(r
, NULL
, n
);
720 mpdm_unref(drw_2
.old
);
721 drw_2
.old
= mpdm_ref(a
);
727 static void drw_restore_attrs(void)
728 /* restored the patched attrs */
730 /* matching paren, if any */
731 if (drw_2
.matchparen_offset
!= -1)
732 drw_fill_attr(drw_2
.matchparen_o_attr
, drw_2
.matchparen_offset
, 1);
735 drw_fill_attr(drw_2
.cursor_o_attr
, drw_2
.cursor
, 1);
737 /* marked block, if any */
738 if (drw_2
.mark_o_attr
!= NULL
) {
739 memcpy(&drw_2
.attrs
[drw_2
.mark_offset
], drw_2
.mark_o_attr
, drw_2
.mark_size
);
741 free(drw_2
.mark_o_attr
);
742 drw_2
.mark_o_attr
= NULL
;
747 static mpdm_t
drw_draw(mpdm_t doc
, int optimize
)
748 /* main document drawing function: takes a document and returns an array of
749 arrays of attribute / string pairs */
753 if (drw_prepare(doc
)) {
754 /* colorize separate words */
757 /* colorize multiline blocks */
761 /* now set the marked block (if any) */
764 /* colorize the search hit */
770 /* highlight the matching paren */
771 drw_matching_paren();
773 /* convert to an array of string / atribute pairs */
777 r
= drw_optimize_array(r
, optimize
);
779 /* restore the patched attrs */
788 mpdm_t
mp_draw(mpdm_t doc
, int optimize
)
789 /* main generic drawing function: if the document has a 'paint' code,
790 calls it; otherwise, call drw_draw() */
793 static int ppp
= 0; /* previous private paint */
796 /* if previous paint was private, disable optimizations */
801 if ((f
= mpdm_hget_s(doc
, L
"paint")) != NULL
) {
803 r
= mpdm_exec_2(f
, doc
, MPDM_I(optimize
));
806 r
= drw_draw(doc
, optimize
);
809 /* if there is a global post_paint function, execute it */
810 if ((f
= mpdm_hget_s(mp
, L
"post_paint")) != NULL
)
811 r
= mpdm_exec_1(f
, r
);
813 /* if doc has a post_paint function, execute it */
814 if ((f
= mpdm_hget_s(doc
, L
"post_paint")) != NULL
)
815 r
= mpdm_exec_1(f
, r
);
821 #define THR_SPEED_STEP 10
822 #define THR_MAX_SPEED 7
824 int mp_keypress_throttle(int keydown
)
825 /* processes key acceleration and throttle */
827 static int keydowns
= 0;
834 /* as keydowns accumulate, speed increases, which is the number
835 of cycles the redraw will be skipped (up to a maximum) */
836 if ((speed
= 1 + (++keydowns
/ THR_SPEED_STEP
)) > THR_MAX_SPEED
)
837 speed
= THR_MAX_SPEED
;
839 if (++seq
% speed
== 0)
853 mpdm_t
mp_active(void)
854 /* interface to mp.active() */
856 return mpdm_exec(mpdm_hget_s(mp
, L
"active"), NULL
);
860 mpdm_t
mp_process_action(mpdm_t action
)
861 /* interface to mp.process_action() */
863 return mpdm_exec_1(mpdm_hget_s(mp
, L
"process_action"), action
);
867 mpdm_t
mp_process_event(mpdm_t keycode
)
868 /* interface to mp.process_event() */
870 return mpdm_exec_1(mpdm_hget_s(mp
, L
"process_event"), keycode
);
874 mpdm_t
mp_set_y(mpdm_t doc
, int y
)
875 /* interface to mp.set_y() */
877 return mpdm_exec_2(mpdm_hget_s(mp
, L
"set_y"), doc
, MPDM_I(y
));
881 mpdm_t
mp_build_status_line(void)
882 /* interface to mp.build_status_line() */
884 return mpdm_exec(mpdm_hget_s(mp
, L
"build_status_line"), NULL
);
888 mpdm_t
mp_get_history(mpdm_t key
)
889 /* interface to mp.get_history() */
891 return mpdm_exec_1(mpdm_hget_s(mp
, L
"get_history"), key
);
895 mpdm_t
mp_get_doc_names(void)
896 /* interface to mp.get_doc_names() */
898 return mpdm_exec(mpdm_hget_s(mp
, L
"get_doc_names"), NULL
);
902 mpdm_t
mp_menu_label(mpdm_t action
)
903 /* interface to mp.menu_label() */
905 return mpdm_exec_1(mpdm_hget_s(mp
, L
"menu_label"), action
);
909 mpdm_t
mp_pending_key(void)
910 /* interface to mp.pending_key() */
912 return mpdm_exec_1(mpdm_hget_s(mp
, L
"pending_key"), NULL
);
916 mpdm_t
mp_process_keyseq(mpdm_t key
)
917 /* interface to mp.process_keyseq() */
919 return mpdm_exec_1(mpdm_hget_s(mp
, L
"process_keyseq"), key
);
923 mpdm_t
mp_exit(mpdm_t args
)
924 /* exit the editor (set mp_exit_requested) */
926 mp_exit_requested
= 1;
932 mpdm_t
mp_vx2x(mpdm_t args
)
933 /* interface to drw_vx2x() */
935 return MPDM_I(drw_vx2x(mpdm_aget(args
, 0), mpdm_ival(mpdm_aget(args
, 1))));
939 mpdm_t
mp_x2vx(mpdm_t args
)
940 /* interface to drw_x2vx() */
942 return MPDM_I(drw_x2vx(mpdm_aget(args
, 0), mpdm_ival(mpdm_aget(args
, 1))));
945 mpdm_t
mp_plain_load(mpdm_t args
)
946 /* loads a plain file into an array (highly optimized one) */
948 mpdm_t f
= mpdm_aget(args
, 0);
949 mpdm_t a
= MPDM_A(0);
953 while ((v
= mpdm_read(f
)) != NULL
) {
954 const wchar_t *ptr
= v
->data
;
958 if (size
&& ptr
[size
- 1] == L
'\n') {
959 if (--size
&& ptr
[size
- 1] == L
'\r')
965 mpdm_push(a
, MPDM_NS(ptr
, size
));
969 /* if last line was chomped, add a last, empty one */
971 mpdm_push(a
, MPDM_LS(L
""));
977 void mp_startup(int argc
, char *argv
[])
983 /* reset the structures */
984 memset(&drw_1
, '\0', sizeof(drw_1
));
985 memset(&drw_1_o
, '\0', sizeof(drw_1_o
));
987 /* create main namespace */
989 mpdm_hset_s(mpdm_root(), L
"mp", mp
);
991 /* basic functions and data */
992 mpdm_hset_s(mp
, L
"x2vx", MPDM_X(mp_x2vx
));
993 mpdm_hset_s(mp
, L
"vx2x", MPDM_X(mp_vx2x
));
994 mpdm_hset_s(mp
, L
"exit", MPDM_X(mp_exit
));
995 mpdm_hset_s(mp
, L
"plain_load", MPDM_X(mp_plain_load
));
996 mpdm_hset_s(mp
, L
"window", MPDM_H(0));
997 mpdm_hset_s(mp
, L
"drv", MPDM_H(0));
1000 mpdm_hset_s(mp
, L
"VERSION", MPDM_S(L
"" VERSION
));
1002 /* creates the INC (executable path) array */
1005 /* add installed library path */
1006 mpdm_push(INC
, mpdm_strcat(mpdm_hget_s(mpdm_root(), L
"APPDIR"),
1007 MPDM_MBS(CONFOPT_APPNAME
))
1011 mpdm_hset_s(mpdm_root(), L
"INC", INC
);
1013 if (!TRY_DRIVERS()) {
1014 printf("No usable driver found; exiting.\n");
1018 mpsl_argv(argc
, argv
);
1026 mpsl_eval(MPDM_LS(L
"load('mp_core.mpsl');"), NULL
);
1028 if ((e
= mpdm_hget_s(mpdm_root(), L
"ERROR")) != NULL
) {
1029 mpdm_write_wcs(stdout
, mpdm_string(e
));
1035 void mp_shutdown(void)
1041 int main(int argc
, char *argv
[])
1043 mp_startup(argc
, argv
);