3 Minimum Profit - Programmer Text Editor
5 Copyright (C) 1991-2010 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 */
107 r
= MP_REAL_TAB_SIZE(x
);
115 return r
< 0 ? 1 : r
;
119 int drw_vx2x(mpdm_t str
, int vx
)
120 /* returns the character in str that is on column vx */
122 const wchar_t *ptr
= str
->data
;
125 for (n
= x
= 0; n
< vx
&& ptr
[x
] != L
'\0'; x
++)
126 n
+= drw_wcwidth(n
, ptr
[x
]);
132 int drw_x2vx(mpdm_t str
, int x
)
133 /* returns the column where the character at offset x seems to be */
135 const wchar_t *ptr
= str
->data
;
138 for (n
= vx
= 0; n
< x
&& ptr
[n
] != L
'\0'; n
++)
139 vx
+= drw_wcwidth(vx
, ptr
[n
]);
145 static int drw_line_offset(int l
)
146 /* returns the offset into v for line number l */
148 return drw_2
.offsets
[l
- drw_1
.vy
+ drw_1
.p_lines
];
152 static int drw_adjust_y(int y
, int *vy
, int ty
)
153 /* adjusts the visual y position */
157 /* is y above the first visible line? */
161 /* is y below the last visible line? */
162 if (y
> *vy
+ (ty
- 2))
169 static int drw_adjust_x(int x
, int y
, int *vx
, int tx
, wchar_t * ptr
)
170 /* adjust the visual x position */
175 /* calculate the column for the cursor position */
176 for (n
= m
= 0; n
< x
; n
++, ptr
++)
177 m
+= drw_wcwidth(m
, *ptr
);
179 /* if new cursor column is nearer the leftmost column, set */
183 /* if new cursor column is further the rightmost column, set */
184 if (m
> *vx
+ (tx
- 1))
191 static int drw_get_attr(wchar_t * color_name
)
192 /* returns the attribute number for a color */
197 if ((v
= mpdm_hget_s(drw_1
.colors
, color_name
)) != NULL
)
198 attr
= mpdm_ival(mpdm_hget_s(v
, L
"attr"));
204 static int drw_prepare(mpdm_t doc
)
205 /* prepares the document for screen drawing */
207 mpdm_t window
= mpdm_hget_s(mp
, L
"window");
208 mpdm_t config
= mpdm_hget_s(mp
, L
"config");
209 mpdm_t txt
= mpdm_hget_s(doc
, L
"txt");
210 mpdm_t lines
= mpdm_hget_s(txt
, L
"lines");
211 int x
= mpdm_ival(mpdm_hget_s(txt
, L
"x"));
212 int y
= mpdm_ival(mpdm_hget_s(txt
, L
"y"));
215 drw_1
.vx
= mpdm_ival(mpdm_hget_s(txt
, L
"vx"));
216 drw_1
.vy
= mpdm_ival(mpdm_hget_s(txt
, L
"vy"));
217 drw_1
.tx
= mpdm_ival(mpdm_hget_s(window
, L
"tx"));
218 drw_1
.ty
= mpdm_ival(mpdm_hget_s(window
, L
"ty"));
219 drw_1
.tab_size
= mpdm_ival(mpdm_hget_s(config
, L
"tab_size"));
220 drw_1
.mod
= mpdm_ival(mpdm_hget_s(txt
, L
"mod"));
221 drw_1
.preread_lines
= mpdm_ival(mpdm_hget_s(config
, L
"preread_lines"));
222 drw_1
.mark_eol
= mpdm_ival(mpdm_hget_s(config
, L
"mark_eol"));
223 drw_1
.t_lines
= mpdm_size(lines
);
225 /* adjust the visual y coordinate */
226 if (drw_adjust_y(y
, &drw_1
.vy
, drw_1
.ty
))
227 mpdm_hset_s(txt
, L
"vy", MPDM_I(drw_1
.vy
));
229 /* adjust the visual x coordinate */
231 (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 */
236 drw_1
.vy
> drw_1
.preread_lines
? drw_1
.preread_lines
: drw_1
.vy
;
239 drw_1
.n_lines
= drw_1
.ty
+ drw_1
.p_lines
;
241 /* get the mp.colors structure and the most used attributes */
242 drw_1
.colors
= mpdm_hget_s(mp
, L
"colors");
243 drw_1
.normal_attr
= drw_get_attr(L
"normal");
244 drw_1
.cursor_attr
= drw_get_attr(L
"cursor");
246 /* store the syntax highlight structure */
247 drw_1
.syntax
= mpdm_hget_s(doc
, L
"syntax");
249 drw_1
.word_color_func
= mpdm_hget_s(mp
, L
"word_color_func");
252 mpdm_unref(drw_1
.txt
);
258 /* last search regex */
259 drw_1
.last_search
= mpdm_hget_s(mp
, L
"last_search");
262 drw_1
.redraw
= mpdm_ival(mpdm_hget_s(mp
, L
"redraw_counter"));
264 /* compare drw_1 with drw_1_o; if they are the same,
265 no more expensive calculations on drw_2 are needed */
266 if (memcmp(&drw_1
, &drw_1_o
, sizeof(drw_1
)) == 0)
269 /* different; store now */
270 memcpy(&drw_1_o
, &drw_1
, sizeof(drw_1_o
));
272 /* alloc space for line offsets */
273 drw_2
.offsets
= realloc(drw_2
.offsets
, drw_1
.n_lines
* sizeof(int));
279 drw_2
.ptr
= mpdm_pokev(drw_2
.ptr
, &drw_2
.size
,
280 mpdm_aget(lines
, drw_1
.vy
- drw_1
.p_lines
));
282 /* first line start at 0 */
283 drw_2
.offsets
[0] = 0;
285 /* add the following lines and store their offsets */
286 for (n
= 1; n
< drw_1
.n_lines
; n
++) {
287 /* add the separator */
289 mpdm_poke(drw_2
.ptr
, &drw_2
.size
, L
"\n", 1, sizeof(wchar_t));
291 /* this line starts here */
292 drw_2
.offsets
[n
] = drw_2
.size
;
295 drw_2
.ptr
= mpdm_pokev(drw_2
.ptr
, &drw_2
.size
,
297 n
+ drw_1
.vy
- drw_1
.p_lines
));
300 drw_2
.ptr
= mpdm_poke(drw_2
.ptr
, &drw_2
.size
, L
"", 1, sizeof(wchar_t));
303 /* now create a value */
305 drw_2
.v
= mpdm_ref(MPDM_ENS(drw_2
.ptr
, drw_2
.size
));
307 /* alloc and init space for the attributes */
308 drw_2
.attrs
= realloc(drw_2
.attrs
, drw_2
.size
+ 1);
309 memset(drw_2
.attrs
, drw_1
.normal_attr
, drw_2
.size
+ 1);
311 drw_2
.visible
= drw_line_offset(drw_1
.vy
);
317 static int drw_fill_attr(int attr
, int offset
, int size
)
318 /* fill an attribute */
321 memset(drw_2
.attrs
+ offset
, attr
, size
);
323 return offset
+ size
;
327 static int drw_fill_attr_regex(int attr
)
328 /* fills with an attribute the last regex match */
330 return drw_fill_attr(attr
, mpdm_regex_offset
, mpdm_regex_size
);
334 static void drw_words(void)
335 /* fills the attributes for separate words */
338 int o
= drw_2
.visible
;
339 mpdm_t word_color
= NULL
;
340 mpdm_t word_color_func
= NULL
;
342 /* take the hash of word colors, if any */
343 if ((word_color
= mpdm_hget_s(mp
, L
"word_color")) == NULL
)
346 /* get the regex for words */
347 if ((r
= mpdm_hget_s(mp
, L
"word_regex")) == NULL
)
350 /* get the word color function */
351 word_color_func
= mpdm_hget_s(mp
, L
"word_color_func");
353 while ((t
= mpdm_regex(drw_2
.v
, r
, o
)) != NULL
) {
359 if ((v
= mpdm_hget(word_color
, t
)) != NULL
)
361 else if (word_color_func
!= NULL
)
362 attr
= mpdm_ival(mpdm_exec_1(word_color_func
, t
, NULL
));
364 o
= drw_fill_attr_regex(attr
);
371 static void drw_multiline_regex(mpdm_t a
, int attr
)
372 /* sets the attribute to all matching (possibly multiline) regexes */
376 for (n
= 0; n
< mpdm_size(a
); n
++) {
377 mpdm_t r
= mpdm_aget(a
, n
);
380 /* if the regex is an array, it's a pair of
381 'match from this' / 'match until this' */
382 if (r
->flags
& MPDM_MULTIPLE
) {
383 mpdm_t rs
= mpdm_aget(r
, 0);
384 mpdm_t re
= mpdm_aget(r
, 1);
386 while (!mpdm_is_null(mpdm_regex(drw_2
.v
, rs
, o
))) {
389 /* fill the matched part */
390 o
= drw_fill_attr_regex(attr
);
392 /* try to match the end */
393 if (!mpdm_is_null(mpdm_regex(drw_2
.v
, re
, o
))) {
394 /* found; fill the attribute
395 to the end of the match */
396 s
= mpdm_regex_size
+ (mpdm_regex_offset
- o
);
399 /* not found; fill to the end
405 o
= drw_fill_attr(attr
, o
, s
);
411 if (*mpdm_string(r
) == L
'%') {
412 /* it's a sscanf() expression */
415 while ((v
= mpdm_ref(mpdm_sscanf(drw_2
.v
, r
, o
)))
416 && mpdm_size(v
) == 2) {
417 int i
= mpdm_ival(mpdm_aget(v
, 0));
418 int s
= mpdm_ival(mpdm_aget(v
, 1)) - i
;
420 o
= drw_fill_attr(attr
, i
, s
);
427 /* while the regex matches, fill attributes */
428 while (!mpdm_is_null(mpdm_regex(drw_2
.v
, r
, o
)))
429 o
= drw_fill_attr_regex(attr
);
436 static void drw_blocks(void)
437 /* fill attributes for multiline blocks */
442 /* no definitions? return */
443 if (drw_1
.syntax
== NULL
444 || (defs
= mpdm_hget_s(drw_1
.syntax
, L
"defs")) == NULL
)
447 for (n
= 0; n
< mpdm_size(defs
); n
+= 2) {
451 /* get the attribute */
452 attr
= mpdm_aget(defs
, n
);
453 attr
= mpdm_hget(drw_1
.colors
, attr
);
454 attr
= mpdm_hget_s(attr
, L
"attr");
456 /* get the list for this word color */
457 list
= mpdm_aget(defs
, n
+ 1);
459 drw_multiline_regex(list
, mpdm_ival(attr
));
464 static void drw_selection(void)
465 /* draws the selected block, if any */
468 int bx
, by
, ex
, ey
, vertical
;
471 int line_offset
, next_line_offset
;
476 /* no mark? return */
477 if ((mark
= mpdm_hget_s(drw_1
.txt
, L
"mark")) == NULL
)
480 bx
= mpdm_ival(mpdm_hget_s(mark
, L
"bx"));
481 by
= mpdm_ival(mpdm_hget_s(mark
, L
"by"));
482 ex
= mpdm_ival(mpdm_hget_s(mark
, L
"ex"));
483 ey
= mpdm_ival(mpdm_hget_s(mark
, L
"ey"));
484 vertical
= mpdm_ival(mpdm_hget_s(mark
, L
"vertical"));
486 /* if block is not visible, return */
487 if (ey
< drw_1
.vy
|| by
>= drw_1
.vy
+ drw_1
.ty
)
490 so
= by
< drw_1
.vy
? drw_2
.visible
: drw_line_offset(by
) + bx
;
491 eo
= ey
>= drw_1
.vy
+ drw_1
.ty
? drw_2
.size
: drw_line_offset(ey
) + ex
;
493 /* alloc space and save the attributes being destroyed */
494 drw_2
.mark_offset
= so
;
495 drw_2
.mark_size
= eo
- so
+ 1;
496 drw_2
.mark_o_attr
= malloc(eo
- so
+ 1);
497 memcpy(drw_2
.mark_o_attr
, &drw_2
.attrs
[so
], eo
- so
+ 1);
500 /* normal selection */
501 drw_fill_attr(drw_get_attr(L
"selection"), so
, eo
- so
);
504 /* vertical selection */
505 mby
= by
< drw_1
.vy
? drw_1
.vy
: by
;
506 mey
= ey
>= drw_1
.vy
+ drw_1
.ty
? drw_1
.vy
+ drw_1
.ty
: ey
;
507 line_offset
= drw_line_offset(mby
);
508 attr
= drw_get_attr(L
"selection");
509 for (y
= mby
; y
<= mey
; y
++) {
510 next_line_offset
= drw_line_offset(y
+ 1);
511 len
= next_line_offset
- line_offset
- 1;
512 so
= bx
> len
? -1 : bx
;
513 eo
= ex
> len
? len
: ex
;
515 if (so
>= 0 && eo
>= so
)
516 drw_fill_attr(attr
, line_offset
+ so
, eo
- so
+ 1);
518 line_offset
= next_line_offset
;
524 static void drw_search_hit(void)
525 /* colorize the search hit, if any */
527 if (drw_1
.last_search
!= NULL
) {
528 mpdm_t l
= mpdm_ref(MPDM_A(0));
530 mpdm_aset(l
, drw_1
.last_search
, 0);
531 drw_multiline_regex(l
, drw_get_attr(L
"search"));
537 static void drw_cursor(void)
538 /* fill the attribute for the cursor */
540 /* calculate the cursor offset */
541 drw_2
.cursor
= drw_line_offset(drw_2
.y
) + drw_2
.x
;
543 drw_2
.cursor_o_attr
= drw_2
.attrs
[drw_2
.cursor
];
544 drw_fill_attr(drw_1
.cursor_attr
, drw_2
.cursor
, 1);
548 static void drw_matching_paren(void)
549 /* highlights the matching paren */
551 int o
= drw_2
.cursor
;
555 /* by default, no offset has been found */
556 drw_2
.matchparen_offset
= -1;
558 /* find the opposite and the increment (direction) */
559 switch (drw_2
.ptr
[o
]) {
586 /* if a direction is set, do the searching */
588 wchar_t s
= drw_2
.ptr
[o
];
590 int l
= i
== -1 ? drw_2
.visible
- 1 : drw_2
.size
;
593 if (drw_2
.ptr
[o
] == s
) {
597 else if (drw_2
.ptr
[o
] == c
) {
598 /* found the opposite */
600 /* found! fill and exit */
601 drw_2
.matchparen_offset
= o
;
602 drw_2
.matchparen_o_attr
= drw_2
.attrs
[o
];
603 drw_fill_attr(drw_get_attr(L
"matching"), o
, 1);
614 static mpdm_t
drw_push_pair(mpdm_t l
, int i
, int a
, wchar_t * tmp
)
615 /* pushes a pair of attribute / string into l */
617 /* create the array, if doesn't exist yet */
623 /* finish the string */
626 /* special magic: if the attribute is the
627 one of the cursor and the string is more than
628 one character, create two strings; the
629 cursor is over a tab */
630 if (a
== drw_1
.cursor_attr
&& i
> 1) {
631 mpdm_push(l
, MPDM_I(a
));
632 mpdm_push(l
, MPDM_NS(tmp
, 1));
634 /* the rest of the string has the original attr */
635 a
= drw_2
.cursor_o_attr
;
641 /* store the attribute and the string */
642 mpdm_push(l
, MPDM_I(a
));
643 mpdm_push(l
, MPDM_S(tmp
));
653 static mpdm_t
drw_line(int line
)
654 /* creates a list of attribute / string pairs for the current line */
658 int o
= drw_2
.offsets
[line
+ drw_1
.p_lines
];
659 int a
= drw_2
.attrs
[o
];
660 wchar_t tmp
[BUF_LINE
];
663 /* loop while not beyond the right margin */
664 for (m
= i
= 0; m
< drw_1
.vx
+ drw_1
.tx
; m
+= t
, o
++) {
665 /* take char and size */
667 t
= drw_wcwidth(m
, c
);
669 /* further the left margin? */
671 /* if the attribute is different or we're out of
672 temporary space, push and go on */
673 if (drw_2
.attrs
[o
] != a
|| i
>= BUF_LINE
- t
- 1) {
674 l
= drw_push_pair(l
, i
, a
, tmp
);
678 /* size is 1, unless it's a tab */
679 n
= c
== L
'\t' ? t
: 1;
681 /* fill tabs with spaces */
682 if (c
== L
'\0' || c
== L
'\t')
683 c
= drw_1
.mark_eol
? L
'\xb7' : L
' ';
685 /* fill EOLs with special marks or spaces */
687 c
= drw_1
.mark_eol
? L
'\xb6' : L
' ';
689 /* if next char will not fit, use a space */
690 if (m
+ t
> drw_1
.vx
+ drw_1
.tx
)
695 n
= m
+ t
- drw_1
.vx
;
699 /* fill the string */
706 if (drw_2
.ptr
[o
] == L
'\0' || drw_2
.ptr
[o
] == L
'\n')
710 return drw_push_pair(l
, i
, a
, tmp
);
714 static mpdm_t
drw_as_array(void)
715 /* returns an mpdm array of ty elements, which are also arrays of
716 attribute - string pairs */
721 /* the array of lines */
722 a
= MPDM_A(drw_1
.ty
);
726 for (n
= 0; n
< drw_1
.ty
; n
++)
727 mpdm_aset(a
, drw_line(n
), n
);
735 static mpdm_t
drw_optimize_array(mpdm_t a
, int optimize
)
736 /* optimizes the array, NULLifying all lines that are the same as the last time */
738 mpdm_t o
= drw_2
.old
;
743 if (optimize
&& o
!= NULL
) {
751 /* compare each array */
752 while (n
< mpdm_size(o
) && n
< mpdm_size(r
)) {
753 /* if both lines are equal, optimize out */
754 if (mpdm_cmp(mpdm_aget(o
, n
), mpdm_aget(r
, n
)) == 0)
755 mpdm_aset(r
, NULL
, n
);
764 mpdm_unref(drw_2
.old
);
773 static void drw_restore_attrs(void)
774 /* restored the patched attrs */
776 /* matching paren, if any */
777 if (drw_2
.matchparen_offset
!= -1)
778 drw_fill_attr(drw_2
.matchparen_o_attr
, drw_2
.matchparen_offset
, 1);
781 drw_fill_attr(drw_2
.cursor_o_attr
, drw_2
.cursor
, 1);
783 /* marked block, if any */
784 if (drw_2
.mark_o_attr
!= NULL
) {
785 memcpy(&drw_2
.attrs
[drw_2
.mark_offset
], drw_2
.mark_o_attr
,
788 free(drw_2
.mark_o_attr
);
789 drw_2
.mark_o_attr
= NULL
;
794 static mpdm_t
drw_draw(mpdm_t doc
, int optimize
)
795 /* main document drawing function: takes a document and returns an array of
796 arrays of attribute / string pairs */
800 if (drw_prepare(doc
)) {
801 /* colorize separate words */
804 /* colorize multiline blocks */
808 /* now set the marked block (if any) */
811 /* colorize the search hit */
817 /* highlight the matching paren */
818 drw_matching_paren();
820 /* convert to an array of string / atribute pairs */
824 r
= drw_optimize_array(r
, optimize
);
826 /* restore the patched attrs */
835 mpdm_t
mp_draw(mpdm_t doc
, int optimize
)
836 /* main generic drawing function: if the document has a 'paint' code,
837 calls it; otherwise, call drw_draw() */
840 static int ppp
= 0; /* previous private paint */
844 /* if previous paint was private, disable optimizations */
849 if ((f
= mpdm_hget_s(doc
, L
"paint")) != NULL
) {
851 r
= mpdm_exec_2(f
, doc
, MPDM_I(optimize
), NULL
);
854 r
= drw_draw(doc
, optimize
);
857 /* if there is a global post_paint list of functions, execute it */
858 if ((f
= mpdm_hget_s(mp
, L
"post_paint")) != NULL
) {
859 for (n
= 0; n
< mpdm_size(f
); n
++)
860 r
= mpdm_exec_2(mpdm_aget(f
, n
), doc
, r
, NULL
);
863 /* if doc has a post_paint list of functions, execute it */
864 if ((f
= mpdm_hget_s(doc
, L
"post_paint")) != NULL
) {
865 for (n
= 0; n
< mpdm_size(f
); n
++)
866 r
= mpdm_exec_2(mpdm_aget(f
, n
), doc
, r
, NULL
);
873 #define THR_SPEED_STEP 10
874 #define THR_MAX_SPEED 7
876 int mp_keypress_throttle(int keydown
)
877 /* processes key acceleration and throttle */
879 static int keydowns
= 0;
886 /* as keydowns accumulate, speed increases, which is the number
887 of cycles the redraw will be skipped (up to a maximum) */
888 if ((speed
= 1 + (++keydowns
/ THR_SPEED_STEP
)) > THR_MAX_SPEED
)
889 speed
= THR_MAX_SPEED
;
891 if (++seq
% speed
== 0)
905 mpdm_t
mp_active(void)
906 /* interface to mp.active() */
908 return mpdm_exec(mpdm_hget_s(mp
, L
"active"), NULL
, NULL
);
912 void mp_process_action(mpdm_t action
)
913 /* interface to mp.process_action() */
915 mpdm_void(mpdm_exec_1
916 (mpdm_hget_s(mp
, L
"process_action"), action
, NULL
));
920 void mp_process_event(mpdm_t keycode
)
921 /* interface to mp.process_event() */
923 mpdm_void(mpdm_exec_1
924 (mpdm_hget_s(mp
, L
"process_event"), keycode
, NULL
));
928 void mp_set_y(mpdm_t doc
, int y
)
929 /* interface to mp.set_y() */
931 mpdm_void(mpdm_exec_2
932 (mpdm_hget_s(mp
, L
"set_y"), doc
, MPDM_I(y
), NULL
));
936 mpdm_t
mp_build_status_line(void)
937 /* interface to mp.build_status_line() */
939 return mpdm_exec(mpdm_hget_s(mp
, L
"build_status_line"), NULL
, NULL
);
943 mpdm_t
mp_get_history(mpdm_t key
)
944 /* interface to mp.get_history() */
946 return mpdm_exec_1(mpdm_hget_s(mp
, L
"get_history"), key
, NULL
);
950 mpdm_t
mp_get_doc_names(void)
951 /* interface to mp.get_doc_names() */
953 return mpdm_exec(mpdm_hget_s(mp
, L
"get_doc_names"), NULL
, NULL
);
957 mpdm_t
mp_menu_label(mpdm_t action
)
958 /* interface to mp.menu_label() */
960 return mpdm_exec_1(mpdm_hget_s(mp
, L
"menu_label"), action
, NULL
);
964 mpdm_t
mp_pending_key(void)
965 /* interface to mp.pending_key() */
967 return mpdm_exec_1(mpdm_hget_s(mp
, L
"pending_key"), NULL
, NULL
);
971 mpdm_t
mp_process_keyseq(mpdm_t key
)
972 /* interface to mp.process_keyseq() */
974 return mpdm_exec_1(mpdm_hget_s(mp
, L
"process_keyseq"), key
, NULL
);
978 mpdm_t
mp_exit(mpdm_t args
, mpdm_t ctxt
)
979 /* exit the editor (set mp_exit_requested) */
981 mp_exit_requested
= 1;
987 static mpdm_t
exit_requested(mpdm_t args
, mpdm_t ctxt
)
988 /* returns the value of the mp_exit_requested variable */
990 return MPDM_I(mp_exit_requested
);
994 mpdm_t
mp_vx2x(mpdm_t args
, mpdm_t ctxt
)
995 /* interface to drw_vx2x() */
999 (mpdm_aget(args
, 0), mpdm_ival(mpdm_aget(args
, 1))));
1003 mpdm_t
mp_x2vx(mpdm_t args
, mpdm_t ctxt
)
1004 /* interface to drw_x2vx() */
1008 (mpdm_aget(args
, 0), mpdm_ival(mpdm_aget(args
, 1))));
1011 mpdm_t
mp_plain_load(mpdm_t args
, mpdm_t ctxt
)
1012 /* loads a plain file into an array (highly optimized one) */
1014 mpdm_t f
= mpdm_aget(args
, 0);
1023 /* clean last seen EOL */
1024 mpdm_hset_s(mp
, L
"last_seen_eol", NULL
);
1026 /* NOTE: this code rewrites a value, which is *illegal*,
1027 to avoid generating too much residual values */
1028 while ((v
= mpdm_read(f
)) != NULL
) {
1029 wchar_t *ptr
= (wchar_t *) v
->data
;
1033 if (size
&& ptr
[size
- 1] == L
'\n') {
1034 if (--size
&& ptr
[size
- 1] == L
'\r') {
1048 /* if last line was chomped, add a last, empty one */
1050 mpdm_push(a
, MPDM_LS(L
""));
1052 /* store the last seen EOL */
1053 mpdm_hset_s(mp
, L
"last_seen_eol", MPDM_LS(eol
== 2 ? L
"\r\n" : L
"\n"));
1061 void mp_startup(int argc
, char *argv
[])
1067 /* reset the structures */
1068 memset(&drw_1
, '\0', sizeof(drw_1
));
1069 memset(&drw_1_o
, '\0', sizeof(drw_1_o
));
1071 /* create main namespace */
1073 mpdm_hset_s(mpdm_root(), L
"mp", mp
);
1075 /* basic functions and data */
1076 mpdm_hset_s(mp
, L
"x2vx", MPDM_X(mp_x2vx
));
1077 mpdm_hset_s(mp
, L
"vx2x", MPDM_X(mp_vx2x
));
1078 mpdm_hset_s(mp
, L
"exit", MPDM_X(mp_exit
));
1079 mpdm_hset_s(mp
, L
"exit_requested", MPDM_X(exit_requested
));
1080 mpdm_hset_s(mp
, L
"plain_load", MPDM_X(mp_plain_load
));
1081 mpdm_hset_s(mp
, L
"window", MPDM_H(0));
1082 mpdm_hset_s(mp
, L
"drv", MPDM_H(0));
1085 mpdm_hset_s(mp
, L
"VERSION", MPDM_S(L
"" VERSION
));
1087 /* creates the INC (executable path) array */
1088 INC
= mpdm_hset_s(mpdm_root(), L
"INC", MPDM_A(0));
1090 /* add installed library path */
1091 mpdm_push(INC
, mpdm_strcat(mpdm_hget_s(mpdm_root(), L
"APPDIR"),
1092 MPDM_MBS(CONFOPT_APPNAME
))
1095 if (!TRY_DRIVERS()) {
1096 printf("No usable driver found; exiting.\n");
1100 mpsl_argv(argc
, argv
);
1108 mpsl_eval(MPDM_LS(L
"load('mp_core.mpsl');"), NULL
, NULL
);
1110 if ((e
= mpdm_hget_s(mpdm_root(), L
"ERROR")) != NULL
) {
1111 mpdm_write_wcs(stdout
, mpdm_string(e
));
1117 void mp_shutdown(void)
1119 /* unref pending values */
1120 mpdm_unref(drw_1
.txt
);
1121 mpdm_unref(drw_2
.v
);
1122 mpdm_unref(drw_2
.old
);
1124 #ifdef DEBUG_CLEANUP
1125 mpdm_unref(mpdm_root());
1132 int main(int argc
, char *argv
[])
1134 mp_startup(argc
, argv
);