3 Minimum Profit - Programmer Text Editor
5 Code common to Qt4 and KDE4 drivers.
7 Copyright (C) 2009/2010 Angel Ortega <angel@triptico.com>
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 http://www.triptico.com
28 QScrollBar
*scrollbar
;
29 static int font_width
= -1;
30 static int font_height
= -1;
31 static int mouse_down
= 0;
32 static int key_down
= 0;
34 mpdm_t timer_func
= NULL
;
38 static void draw_status(void);
40 static mpdm_t
qstring_to_str(QString s
)
41 /* converts a QString to an MPDM string */
47 wchar_t *wptr
= (wchar_t *) malloc((t
+ 1) * sizeof(wchar_t));
49 r
= MPDM_ENS(wptr
, t
);
59 QString
str_to_qstring(mpdm_t s
)
60 /* converts an MPDM string to a QString */
66 wptr
= mpdm_string(s
);
67 r
= QString::fromWCharArray(wptr
);
74 #define MAX_COLORS 1000
75 QPen inks
[MAX_COLORS
];
76 QBrush papers
[MAX_COLORS
];
77 bool underlines
[MAX_COLORS
];
80 static void build_colors(void)
81 /* builds the colors */
88 /* gets the color definitions and attribute names */
89 colors
= mpdm_hget_s(mp
, L
"colors");
90 l
= mpdm_ref(mpdm_keys(colors
));
94 for (n
= 0; n
< s
&& (c
= mpdm_aget(l
, n
)) != NULL
; n
++) {
96 mpdm_t d
= mpdm_hget(colors
, c
);
97 mpdm_t v
= mpdm_hget_s(d
, L
"gui");
99 /* store the 'normal' attribute */
100 if (wcscmp(mpdm_string(c
), L
"normal") == 0)
104 mpdm_hset_s(d
, L
"attr", MPDM_I(n
));
106 rgbi
= mpdm_ival(mpdm_aget(v
, 0));
107 rgbp
= mpdm_ival(mpdm_aget(v
, 1));
110 v
= mpdm_hget_s(d
, L
"flags");
112 if (mpdm_seek_s(v
, L
"reverse", 1) != -1) {
119 mpdm_seek_s(v
, L
"underline", 1) != -1 ? true : false;
121 inks
[n
] = QPen(QColor::fromRgbF((float) ((rgbi
& 0x00ff0000) >> 16)
123 (float) ((rgbi
& 0x0000ff00) >> 8)
125 (float) ((rgbi
& 0x000000ff)) /
128 papers
[n
] = QBrush(QColor::fromRgbF((float)
129 ((rgbp
& 0x00ff0000) >> 16) /
131 (float) ((rgbp
& 0x0000ff00) >>
133 (float) ((rgbp
& 0x000000ff)) /
141 static QFont
build_font(int rebuild
)
142 /* (re)builds the font */
148 char *font_face
= (char *) "Mono";
152 if ((c
= mpdm_hget_s(mp
, L
"config")) != NULL
) {
155 if ((v
= mpdm_hget_s(c
, L
"font_size")) != NULL
)
156 font_size
= mpdm_ival(v
);
158 mpdm_hset_s(c
, L
"font_size", MPDM_I(font_size
));
160 if ((v
= mpdm_hget_s(c
, L
"font_face")) != NULL
) {
161 w
= mpdm_ref(MPDM_2MBS((wchar_t *) v
->data
));
162 font_face
= (char *) w
->data
;
165 mpdm_hset_s(c
, L
"font_face", MPDM_MBS(font_face
));
168 font
= QFont(QString(font_face
), font_size
);
176 static void build_menu(void)
177 /* builds the menu */
182 /* gets the current menu */
183 if ((m
= mpdm_hget_s(mp
, L
"menu")) == NULL
)
188 for (n
= 0; n
< mpdm_size(m
); n
++) {
194 mi
= mpdm_aget(m
, n
);
195 v
= mpdm_aget(mi
, 0);
197 MENU_CLASS
*menu
= new MENU_CLASS(str_to_qstring(mpdm_gettext(v
)));
200 v
= mpdm_aget(mi
, 1);
202 for (i
= 0; i
< mpdm_size(v
); i
++) {
204 mpdm_t w
= mpdm_aget(v
, i
);
206 wptr
= mpdm_string(w
);
209 menu
->addSeparator();
211 menu
->addAction(str_to_qstring(mp_menu_label(w
)));
214 menubar
->addMenu(menu
);
221 static int ignore_scrollbar_signal
= 0;
223 static void draw_scrollbar(void)
228 mpdm_t txt
= mpdm_hget_s(mp_active(), L
"txt");
229 mpdm_t window
= mpdm_hget_s(mp
, L
"window");
230 int vy
= mpdm_ival(mpdm_hget_s(txt
, L
"vy"));
231 int ty
= mpdm_ival(mpdm_hget_s(window
, L
"ty"));
232 int l
= mpdm_size(mpdm_hget_s(txt
, L
"lines")) - ty
;
234 if (ol
!= l
|| ovy
!= vy
|| oty
!= ty
) {
236 ignore_scrollbar_signal
= 1;
238 scrollbar
->setMinimum(0);
239 scrollbar
->setMaximum(ol
= l
);
240 scrollbar
->setValue(ovy
= vy
);
241 scrollbar
->setPageStep(oty
= ty
);
243 ignore_scrollbar_signal
= 0;
248 static void draw_filetabs(void)
250 static mpdm_t last
= NULL
;
254 names
= mpdm_ref(mp_get_doc_names());
256 /* get mp.active_i now, because it can be changed
257 from the signal handler */
258 i
= mpdm_ival(mpdm_hget_s(mp
, L
"active_i"));
260 /* is the list different from the previous one? */
261 if (mpdm_cmp(names
, last
) != 0) {
263 while (file_tabs
->count())
264 file_tabs
->removeTab(0);
266 /* create the new ones */
267 for (n
= 0; n
< mpdm_size(names
); n
++)
268 file_tabs
->addTab(str_to_qstring(mpdm_aget(names
, n
)));
270 /* store for the next time */
272 last
= mpdm_ref(names
);
277 /* set the active one */
278 file_tabs
->setCurrentIndex(i
);
282 /** MPArea methods **/
284 MPArea::MPArea(QWidget
* parent
):QWidget(parent
)
286 setAttribute(Qt::WA_InputMethodEnabled
, true);
288 setAcceptDrops(true);
290 timer
= new QTimer();
291 connect(timer
, SIGNAL(timeout()), this, SLOT(from_timer()));
295 bool MPArea::event(QEvent
* event
)
297 /* special tab processing */
298 if (event
->type() == QEvent::KeyPress
) {
299 QKeyEvent
*ke
= (QKeyEvent
*) event
;
301 if (ke
->key() == Qt::Key_Tab
) {
302 mp_process_event(MPDM_LS(L
"tab"));
307 if (ke
->key() == Qt::Key_Backtab
) {
308 mp_process_event(MPDM_LS(L
"shift-tab"));
314 /* keep normal processing */
315 return QWidget::event(event
);
318 void MPArea::paintEvent(QPaintEvent
*)
323 bool underline
= false;
325 QPainter
painter(this);
327 font
= build_font(0);
328 font
.setUnderline(false);
329 painter
.setFont(font
);
331 font_width
= painter
.fontMetrics().width("M");
332 font_height
= painter
.fontMetrics().height();
334 /* calculate window size */
335 w
= mpdm_hget_s(mp
, L
"window");
336 mpdm_hset_s(w
, L
"tx", MPDM_I(this->width() / font_width
));
337 mpdm_hset_s(w
, L
"ty", MPDM_I(this->height() / font_height
));
339 w
= mp_draw(mp_active(), 0);
340 y
= painter
.fontMetrics().ascent() + 1;
342 painter
.setBackgroundMode(Qt::OpaqueMode
);
344 painter
.setBrush(papers
[normal_attr
]);
345 painter
.drawRect(0, 0, this->width(), this->height());
349 for (n
= 0; n
< mpdm_size(w
); n
++) {
350 mpdm_t l
= mpdm_aget(w
, n
);
356 for (m
= 0; m
< mpdm_size(l
); m
++) {
360 /* get the attribute and the string */
361 attr
= mpdm_ival(mpdm_aget(l
, m
++));
364 painter
.setPen(inks
[attr
]);
365 painter
.setBackground(papers
[attr
]);
367 QString qs
= str_to_qstring(s
);
369 if (underline
!= underlines
[attr
]) {
370 underline
= underlines
[attr
];
371 font
.setUnderline(underline
);
372 painter
.setFont(font
);
375 painter
.drawText(x
, y
, qs
);
377 x
+= painter
.fontMetrics().width(qs
);
389 area
->setFocus(Qt::OtherFocusReason
);
393 void MPArea::inputMethodEvent(QInputMethodEvent
* event
)
395 QString s
= event
->commitString();
397 mp_process_event(qstring_to_str(s
));
402 void MPArea::keyReleaseEvent(QKeyEvent
* event
)
404 if (!event
->isAutoRepeat()) {
407 if (mp_keypress_throttle(0))
413 void MPArea::keyPressEvent(QKeyEvent
* event
)
420 /* set mp.shift_pressed */
421 if (event
->modifiers() & Qt::ShiftModifier
)
422 mpdm_hset_s(mp
, L
"shift_pressed", MPDM_I(1));
424 if (event
->modifiers() & Qt::ControlModifier
) {
425 switch (event
->key()) {
427 ptr
= (wchar_t *) L
"ctrl-cursor-up";
430 ptr
= (wchar_t *) L
"ctrl-cursor-down";
433 ptr
= (wchar_t *) L
"ctrl-cursor-left";
436 ptr
= (wchar_t *) L
"ctrl-cursor-right";
439 ptr
= (wchar_t *) L
"ctrl-page-up";
441 case Qt::Key_PageDown
:
442 ptr
= (wchar_t *) L
"ctrl-page-down";
445 ptr
= (wchar_t *) L
"ctrl-home";
448 ptr
= (wchar_t *) L
"ctrl-end";
451 ptr
= (wchar_t *) L
"ctrl-space";
454 ptr
= (wchar_t *) L
"ctrl-f1";
457 ptr
= (wchar_t *) L
"ctrl-f2";
460 ptr
= (wchar_t *) L
"ctrl-f3";
463 ptr
= (wchar_t *) L
"ctrl-f4";
466 ptr
= (wchar_t *) L
"ctrl-f5";
469 ptr
= (wchar_t *) L
"ctrl-f6";
472 ptr
= (wchar_t *) L
"ctrl-f7";
475 ptr
= (wchar_t *) L
"ctrl-f8";
478 ptr
= (wchar_t *) L
"ctrl-f9";
481 ptr
= (wchar_t *) L
"ctrl-f10";
484 ptr
= (wchar_t *) L
"ctrl-f11";
487 ptr
= (wchar_t *) L
"ctrl-f12";
490 ptr
= (wchar_t *) L
"ctrl-a";
493 ptr
= (wchar_t *) L
"ctrl-b";
496 ptr
= (wchar_t *) L
"ctrl-c";
499 ptr
= (wchar_t *) L
"ctrl-d";
502 ptr
= (wchar_t *) L
"ctrl-e";
505 ptr
= (wchar_t *) L
"ctrl-f";
508 ptr
= (wchar_t *) L
"ctrl-g";
511 ptr
= (wchar_t *) L
"ctrl-h";
514 ptr
= (wchar_t *) L
"ctrl-i";
517 ptr
= (wchar_t *) L
"ctrl-j";
520 ptr
= (wchar_t *) L
"ctrl-k";
523 ptr
= (wchar_t *) L
"ctrl-l";
526 ptr
= (wchar_t *) L
"ctrl-m";
529 ptr
= (wchar_t *) L
"ctrl-n";
532 ptr
= (wchar_t *) L
"ctrl-o";
535 ptr
= (wchar_t *) L
"ctrl-p";
538 ptr
= (wchar_t *) L
"ctrl-q";
541 ptr
= (wchar_t *) L
"ctrl-r";
544 ptr
= (wchar_t *) L
"ctrl-s";
547 ptr
= (wchar_t *) L
"ctrl-t";
550 ptr
= (wchar_t *) L
"ctrl-u";
553 ptr
= (wchar_t *) L
"ctrl-v";
556 ptr
= (wchar_t *) L
"ctrl-w";
559 ptr
= (wchar_t *) L
"ctrl-x";
562 ptr
= (wchar_t *) L
"ctrl-y";
565 ptr
= (wchar_t *) L
"ctrl-z";
569 ptr
= (wchar_t *) L
"ctrl-enter";
577 if (event
->modifiers() & Qt::AltModifier
) {
578 switch (event
->key()) {
580 ptr
= (wchar_t *) L
"alt-cursor-up";
583 ptr
= (wchar_t *) L
"alt-cursor-down";
586 ptr
= (wchar_t *) L
"alt-cursor-left";
589 ptr
= (wchar_t *) L
"alt-cursor-right";
592 ptr
= (wchar_t *) L
"alt-page-up";
594 case Qt::Key_PageDown
:
595 ptr
= (wchar_t *) L
"alt-page-down";
598 ptr
= (wchar_t *) L
"alt-home";
601 ptr
= (wchar_t *) L
"alt-end";
604 ptr
= (wchar_t *) L
"alt-space";
607 ptr
= (wchar_t *) L
"alt-f1";
610 ptr
= (wchar_t *) L
"alt-f2";
613 ptr
= (wchar_t *) L
"alt-f3";
616 ptr
= (wchar_t *) L
"alt-f4";
619 ptr
= (wchar_t *) L
"alt-f5";
622 ptr
= (wchar_t *) L
"alt-f6";
625 ptr
= (wchar_t *) L
"alt-f7";
628 ptr
= (wchar_t *) L
"alt-f8";
631 ptr
= (wchar_t *) L
"alt-f9";
634 ptr
= (wchar_t *) L
"alt-f10";
637 ptr
= (wchar_t *) L
"alt-f11";
640 ptr
= (wchar_t *) L
"alt-f12";
643 ptr
= (wchar_t *) L
"alt-a";
646 ptr
= (wchar_t *) L
"alt-b";
649 ptr
= (wchar_t *) L
"alt-c";
652 ptr
= (wchar_t *) L
"alt-d";
655 ptr
= (wchar_t *) L
"alt-e";
658 ptr
= (wchar_t *) L
"alt-f";
661 ptr
= (wchar_t *) L
"alt-g";
664 ptr
= (wchar_t *) L
"alt-h";
667 ptr
= (wchar_t *) L
"alt-i";
670 ptr
= (wchar_t *) L
"alt-j";
673 ptr
= (wchar_t *) L
"alt-k";
676 ptr
= (wchar_t *) L
"alt-l";
679 ptr
= (wchar_t *) L
"alt-m";
682 ptr
= (wchar_t *) L
"alt-n";
685 ptr
= (wchar_t *) L
"alt-o";
688 ptr
= (wchar_t *) L
"alt-p";
691 ptr
= (wchar_t *) L
"alt-q";
694 ptr
= (wchar_t *) L
"alt-r";
697 ptr
= (wchar_t *) L
"alt-s";
700 ptr
= (wchar_t *) L
"alt-t";
703 ptr
= (wchar_t *) L
"alt-u";
706 ptr
= (wchar_t *) L
"alt-v";
709 ptr
= (wchar_t *) L
"alt-w";
712 ptr
= (wchar_t *) L
"alt-x";
715 ptr
= (wchar_t *) L
"alt-y";
718 ptr
= (wchar_t *) L
"alt-z";
722 ptr
= (wchar_t *) L
"alt-enter";
730 switch (event
->key()) {
732 ptr
= (wchar_t *) L
"cursor-up";
735 ptr
= (wchar_t *) L
"cursor-down";
738 ptr
= (wchar_t *) L
"cursor-left";
741 ptr
= (wchar_t *) L
"cursor-right";
744 ptr
= (wchar_t *) L
"page-up";
746 case Qt::Key_PageDown
:
747 ptr
= (wchar_t *) L
"page-down";
750 ptr
= (wchar_t *) L
"home";
753 ptr
= (wchar_t *) L
"end";
756 ptr
= (wchar_t *) L
"space";
759 ptr
= (wchar_t *) L
"f1";
762 ptr
= (wchar_t *) L
"f2";
765 ptr
= (wchar_t *) L
"f3";
768 ptr
= (wchar_t *) L
"f4";
771 ptr
= (wchar_t *) L
"f5";
774 ptr
= (wchar_t *) L
"f6";
777 ptr
= (wchar_t *) L
"f7";
780 ptr
= (wchar_t *) L
"f8";
783 ptr
= (wchar_t *) L
"f9";
786 ptr
= (wchar_t *) L
"f10";
789 ptr
= (wchar_t *) L
"f11";
792 ptr
= (wchar_t *) L
"f12";
795 ptr
= (wchar_t *) L
"insert";
797 case Qt::Key_Backspace
:
798 ptr
= (wchar_t *) L
"backspace";
801 ptr
= (wchar_t *) L
"delete";
805 ptr
= (wchar_t *) L
"enter";
808 ptr
= (wchar_t *) L
"escape";
817 k
= qstring_to_str(event
->text());
824 if (mp_keypress_throttle(1))
829 void MPArea::mousePressEvent(QMouseEvent
* event
)
835 QPoint pos
= event
->pos();
837 mpdm_hset_s(mp
, L
"mouse_x", MPDM_I(pos
.x() / font_width
));
838 mpdm_hset_s(mp
, L
"mouse_y", MPDM_I(pos
.y() / font_height
));
840 switch (event
->button()) {
842 ptr
= (wchar_t *) L
"mouse-left-button";
845 ptr
= (wchar_t *) L
"mouse-middle-button";
847 case Qt::RightButton
:
848 ptr
= (wchar_t *) L
"mouse-right-button";
855 mp_process_event(MPDM_S(ptr
));
861 void MPArea::mouseReleaseEvent(QMouseEvent
* event
)
867 void MPArea::mouseMoveEvent(QMouseEvent
* event
)
875 QPoint pos
= event
->pos();
878 x
= pos
.x() / font_width
;
879 y
= pos
.y() / font_height
;
881 if (ox
!= x
&& oy
!= y
) {
882 mpdm_hset_s(mp
, L
"mouse_to_x", MPDM_I(x
));
883 mpdm_hset_s(mp
, L
"mouse_to_y", MPDM_I(y
));
885 mp_process_event(MPDM_LS(L
"mouse-drag"));
893 void MPArea::wheelEvent(QWheelEvent
* event
)
895 if (event
->delta() > 0)
896 mp_process_event(MPDM_S(L
"mouse-wheel-up"));
898 mp_process_event(MPDM_S(L
"mouse-wheel-down"));
904 void MPArea::dragEnterEvent(QDragEnterEvent
* event
)
906 if (event
->mimeData()->hasFormat("text/uri-list"))
907 event
->acceptProposedAction();
911 void MPArea::dropEvent(QDropEvent
* event
)
914 mpdm_t v
= qstring_to_str(event
->mimeData()->text());
915 mpdm_t l
= MPDM_A(0);
919 /* split the list of files */
920 v
= mpdm_split_s(v
, L
"\n");
922 for (n
= 0; n
< mpdm_size(v
); n
++) {
924 mpdm_t w
= mpdm_aget(v
, n
);
926 /* strip file:///, if found */
927 ptr
= mpdm_string(w
);
929 if (wcsncmp(ptr
, L
"file://", 7) == 0)
933 mpdm_push(l
, MPDM_S(ptr
));
936 mpdm_hset_s(mp
, L
"dropped_files", l
);
938 event
->acceptProposedAction();
939 mp_process_event(MPDM_LS(L
"dropped-files"));
949 void MPArea::from_scrollbar(int value
)
951 if (!ignore_scrollbar_signal
) {
952 mpdm_t v
= mp_active();
956 /* set the vy to the same value */
957 v
= mpdm_hget_s(v
, L
"txt");
958 mpdm_hset_s(v
, L
"vy", MPDM_I(value
));
965 void MPArea::from_filetabs(int value
)
968 /* sets the active one */
969 mpdm_hset_s(mp
, L
"active_i", MPDM_I(value
));
975 void MPArea::from_menu(QAction
* action
)
977 mpdm_t label
= qstring_to_str(action
->text());
978 label
= mpdm_sregex(label
, MPDM_LS(L
"/&/"), NULL
, 0);
980 mpdm_t a
= mpdm_hget_s(mp
, L
"actions_by_menu_label");
982 mp_process_action(mpdm_hget(a
, label
));
987 void MPArea::from_timer(void)
989 mpdm_void(mpdm_exec(timer_func
, NULL
, NULL
));
994 /** driver functions **/
996 static mpdm_t
qt4_drv_update_ui(mpdm_t a
, mpdm_t ctxt
)
1006 static mpdm_t
qt4_drv_busy(mpdm_t a
, mpdm_t ctxt
)
1008 int onoff
= mpdm_ival(mpdm_aget(a
, 0));
1010 window
->setCursor(onoff
? Qt::WaitCursor
: Qt::ArrowCursor
);
1016 static mpdm_t
qt4_drv_main_loop(mpdm_t a
, mpdm_t ctxt
)
1024 static mpdm_t
qt4_drv_shutdown(mpdm_t a
, mpdm_t ctxt
)
1028 if ((v
= mpdm_hget_s(mp
, L
"exit_message")) != NULL
) {
1029 mpdm_write_wcs(stdout
, mpdm_string(v
));
1037 static mpdm_t
qt4_drv_clip_to_sys(mpdm_t a
, mpdm_t ctxt
)
1041 QClipboard
*qc
= QApplication::clipboard();
1043 /* gets the clipboard and joins */
1044 v
= mpdm_hget_s(mp
, L
"clipboard");
1046 if (mpdm_size(v
) != 0) {
1047 v
= mpdm_join_s(v
, L
"\n");
1048 qc
->setText(str_to_qstring(v
), QClipboard::Selection
);
1055 static mpdm_t
qt4_drv_sys_to_clip(mpdm_t a
, mpdm_t ctxt
)
1057 QClipboard
*qc
= QApplication::clipboard();
1058 QString qs
= qc
->text(QClipboard::Selection
);
1060 /* split and set as the clipboard */
1061 mpdm_hset_s(mp
, L
"clipboard", mpdm_split_s(qstring_to_str(qs
), L
"\n"));
1062 mpdm_hset_s(mp
, L
"clipboard_vertical", MPDM_I(0));
1068 static mpdm_t
qt4_drv_timer(mpdm_t a
, mpdm_t ctxt
)
1070 int msecs
= mpdm_ival(mpdm_aget(a
, 0));
1071 mpdm_t func
= mpdm_aget(a
, 1);
1074 mpdm_unref(timer_func
);
1077 if (timer_func
== NULL
)
1078 area
->timer
->stop();
1080 area
->timer
->start(msecs
);