blob: b3f3aa12c1f68f0ecdbe43b28906c5b27c349a6c [file] [log] [blame]
Bram Moolenaar843ee412004-06-30 16:16:41 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 */
8
9/*
10 * Porting to KDE(2) was done by
11 *
12 * (C) 2000 by Thomas Capricelli <orzel@freehackers.org>
13 *
14 * Please visit http://freehackers.org/kvim for other vim- or
15 * kde-related coding.
16 *
17 * $Id$
18 *
19 */
20
21#include <qscrollbar.h>
22#include <qcstring.h>
23#include <qdatetime.h>
24#include <qcursor.h>
25#include <qfontmetrics.h>
26#include <qpaintdevice.h>
27#include <qclipboard.h>
28#include <qregexp.h>
29#include <kaboutkde.h>
30#include <kiconloader.h>
31#include <kfontdialog.h>
32#include <kmessagebox.h>
33#include <dcopclient.h>
34#include <kwin.h>
35#include <kmenubar.h>
36#include <kconfig.h>
37#if (QT_VERSION>=300)
38#include <qnamespace.h>
39#include <ktip.h>
40#endif
41#include <qpopupmenu.h>
42#include <qpainter.h>
43#include <qtextcodec.h>
44#include <qfontmetrics.h>
45#include <qfont.h>
46
47
48#include "gui_kde_widget.h"
49
50
51extern "C" {
52#include "vim.h"
53#include "version.h"
54}
55
56#include <stdio.h>
57
58/*
59 * global variable for KDE, we can't put them in Gui, cause there are C++ types
60 */
61VimMainWindow *vmw=0;
62SBPool *sbpool=0;
63QString *argServerName=0;
64
65#ifdef FEAT_MOUSESHAPE
66/* The last set mouse pointer shape is remembered, to be used when it goes
67 * from hidden to not hidden. */
68static int last_shape = 0;
69#endif
70
71/*
72 * Arguments handled by KDE internally.
73 */
74
75#if QT_VERSION>=300
76static int tip=0; // 1 no dialog, 0 use it if enabled in conf, 2 force the tip
77#endif
78static int reverse=0; // 0 bg : white, 1 : bg : black
79QString *startfont;
80QSize *startsize;
81static int gui_argc = 0;
82static char **gui_argv = NULL;
83
84/*
85 * Parse the GUI related command-line arguments. Any arguments used are
86 * deleted from argv, and *argc is decremented accordingly. This is called
87 * when vim is started, whether or not the GUI has been started.
88 */
89 void
90gui_mch_prepare(int *argc, char **argv)// {{{
91{
92 //copy args for KDE/Qt
93 gui_argc = 0;
94 //this one is not really good as all options are not for KDE/Qt ...
95 gui_argv = (char **)lalloc((long_u)(*argc * sizeof(char *)), FALSE);
96 if (gui_argv == NULL)
97 return;
98 gui_argv[gui_argc++] = argv[0];
99
100 int found = 0;
101 for (int i = 1; i < *argc ; i++)
102 {
103 if (found!=2)
104 found = 0;
105 else {
106 found=0;
107 //remove from the list of argv
108 if (--*argc>i) {
109 mch_memmove(&argv[i], &argv[i + 1],
110 (*argc - i) * sizeof(char *));
111 }
112 i--;
113 continue;
114 }
115
116 if (strcmp(argv[i],"--servername")==0) {
117 argServerName = new QString(argv[i+1]); // to get the serverName now
118 }
119#if QT_VERSION>+300
120 if (strcmp(argv[i],"-tip")==0 ) {
121 tip=2;
122 found=1;
123 }
124 if (strcmp(argv[i],"-notip")==0 ) {
125 tip=1;
126 found=1;
127 }
128#endif
129 if (strcmp(argv[i],"-black")==0 ) {
130 reverse=1;
131 found=1;
132 }
133 /* replaced by -black */
134/* if (strcmp(argv[i],"-rv")==0 ) {
135 reverse=1;
136 found=1;
137 }*/
138 if (strcmp(argv[i],"-font")==0 || strcmp(argv[i], "-fn")==0 ) {
139 startfont=new QString(argv[i+1]);
140 found=2;
141 }
142 if (strcmp(argv[i],"-geometry")==0 || strcmp (argv[i],"-geom")==0 ) {
143 found=2;
144 QString text(argv[i+1]);
145 QStringList list = QStringList::split(QChar('x'), text);
146 startsize = new QSize(list[0].toInt(),list[1].toInt());
147 }
148 if (strcmp (argv[i],"-display")==0 ) { //XXX: this does not work,
149 // too many -display options in main.c !
150 // ask Bram ...
151 gui_argv[gui_argc++] = strdup("--display");
152 gui_argv[gui_argc++] = argv[i+1];
153 found=0;
154 }
155 if (strcmp (argv[i],"--display")==0 ) {
156 gui_argv[gui_argc++] = argv[i];
157 gui_argv[gui_argc++] = argv[i+1];
158 found=2;
159 }
160 //KDE/Qt options with no args
161 if (strcmp(argv[i],"--help-kde")==0 || strcmp (argv[i],"--help-qt")==0
162 || strcmp(argv[i], "--help-all")==0
163 || strcmp(argv[i], "--reverse")==0
164 || strcmp(argv[i], "--author")==0
165// || strcmp(argv[i], "--version")==0 //disabled we need these for kcmvim
166// || strcmp(argv[i], "-v")==0
167 || strcmp(argv[i], "--license")==0
168 || strcmp(argv[i], "--cmap")==0
169 || strcmp(argv[i], "--nograb")==0
170 || strcmp(argv[i], "--dograb")==0
171 || strcmp(argv[i], "--sync")==0
172 || strcmp(argv[i], "--noxim")==0
173 || strcmp(argv[i], "--nocrashhandler")==0
174 || strcmp(argv[i], "--waitforwm")==0
175 ) {
176 gui_argv[gui_argc++] = argv[i];
177 found=1;
178 }
179 //this outputs KDE and Vim versions :)
180 if (strcmp(argv[i],"--version")==0
181 || strcmp (argv[i],"-v")==0
182 ) {
183 gui_argv[gui_argc++] = argv[i];
184 }
185
186
187 //KDE/Qt options with one arg
188 if ( strcmp(argv[i],"--session")==0
189 || strcmp(argv[i],"--ncols")==0
190 || strcmp(argv[i],"--bg")==0
191 || strcmp(argv[i],"--background")==0
192 || strcmp(argv[i],"--fg")==0
193 || strcmp(argv[i],"--foreground")==0
194 || strcmp(argv[i],"--btn")==0
195 || strcmp(argv[i],"--name")==0
196 || strcmp(argv[i],"--title")==0
197 || strcmp(argv[i],"--inputstyle")==0
198 || strcmp(argv[i],"--im")==0
199 || strcmp(argv[i],"--caption")==0
200 || strcmp(argv[i],"--icon")==0
201 || strcmp(argv[i],"--miniicon")==0
202 || strcmp(argv[i],"--config")==0
203 || strcmp(argv[i],"--dcopserver")==0
204 || strcmp(argv[i],"--style")==0
205 || strcmp(argv[i],"--geometry")==0
206 || strcmp(argv[i],"--smkey")==0
207 || strcmp(argv[i],"-smkey")==0
208 || strcmp(argv[i],"-session")==0
209 ) {
210 gui_argv[gui_argc++] = argv[i];
211 gui_argv[gui_argc++] = argv[i+1];
212 found=2;
213 }
214
215 //remove from the list of argv
216 if (found >= 1 && --*argc>i) {
217 mch_memmove(&argv[i], &argv[i + 1],
218 (*argc - i) * sizeof(char *));
219 i--;
220 }
221 }
222 KCmdLineArgs::init( gui_argc,gui_argv,"kvim", I18N_NOOP("Vim inside KDE"),VIM_VERSION_SHORT);
223}// }}}
224
225/****************************************************************************
226 * Focus handlers:
227 */
228
229/*
230 * Initialises time intervals for the cursor blinking
231 */
232 void
233gui_mch_set_blinking(long waittime, long on, long off)//{{{
234{
235 gui.w->set_blink_time( waittime, on, off );
236}//}}}
237
238/*
239 * Stop the cursor blinking. Show the cursor if it wasn't shown.
240 */
241 void
242gui_mch_stop_blink()//{{{
243{
244 gui.w->stop_cursor_blinking();
245}//}}}
246
247/*
248 * Start the cursor blinking. If it was already blinking, this restarts the
249 * waiting time and shows the cursor.
250 */
251 void
252gui_mch_start_blink()//{{{
253{
254 gui.w->start_cursor_blinking();
255}//}}}
256
257/*
258 * Check if the GUI can be started. Called before gvimrc is sourced.
259 * Return OK or FAIL.
260 */
261 int
262gui_mch_init_check(void)//{{{
263{
264 gui.dpy = qt_xdisplay();
265 return OK;
266}//}}}
267
268/*
269 * Initialise the X GUI. Create all the windows, set up all the call-backs etc.
270 * Returns OK for success, FAIL when the GUI can't be started.
271 */
272 int
273gui_mch_init()//{{{
274{
275 (void) new KApplication();
276 KApplication::kApplication()->dcopClient()->registerAs(KApplication::kApplication()->name(),false);
277// dbf("%s %s",KGlobal::locale()->language().latin1(),KLocale::defaultLanguage().latin1());
278
279 vmw = new VimMainWindow("KVim",0);
280 vmw->setFrameBorderWidth(0);
281 kapp->setMainWidget(vmw);
282 kapp->setTopWidget(vmw);
283
284 sbpool = new SBPool;
285
286#if QT_VERSION>=300
287 vmw->connect(kapp->clipboard(),SIGNAL(selectionChanged()),vmw,SLOT(clipboard_selection_update()));
288#endif
289 vmw->connect(kapp->clipboard(),SIGNAL(dataChanged()),vmw,SLOT(clipboard_data_update()));
290 clip_lose_selection(&clip_plus);
291 clip_lose_selection(&clip_star);
292
293 gui.in_focus = FALSE; // will be updated
294
295 if (reverse) {
296 gui.def_norm_pixel = gui_get_color((char_u *)"White");
297 gui.def_back_pixel = gui_get_color((char_u *)"Black");
298#if QT_VERSION>=300
299 gui.w->setEraseColor ( QColor(Qt::black) );
300#else
301 gui.w->setBackgroundColor ( QColor(Qt::black) );
302#endif
303 } else {
304 gui.def_norm_pixel = gui_get_color((char_u *)"Black");
305 gui.def_back_pixel = gui_get_color((char_u *)"White");
306#if QT_VERSION>=300
307 gui.w->setEraseColor ( QColor(Qt::white) );
308#else
309 gui.w->setBackgroundColor ( QColor(Qt::white) );
310#endif
311 }
312
313 gui.norm_pixel = gui.def_norm_pixel;
314 gui.back_pixel = gui.def_back_pixel;
315
316 gui.border_width = 1;
317 gui.border_offset = 1;//gui.border_width;
318 gui.scrollbar_width=SB_DEFAULT_WIDTH;
319 gui.scrollbar_height=SB_DEFAULT_WIDTH;
320
321 //gui.menu_height=vmw->menuBar()->height()+1;
322 //gui.toolbar_height=vmw->toolBar()->height();
323
324 return OK;
325}//}}}
326
327
328/*
329 * Called when the foreground or background color has been changed.
330 */
331 void
332gui_mch_new_colors()//{{{
333{
334 QColor rgb;
335 rgb.setRgb(gui.back_pixel);
336#if QT_VERSION>=300
337 gui.w->setEraseColor(rgb);
338#else
339 gui.w->setBackgroundColor(rgb);
340#endif
341}//}}}
342
343/*
344 * Open the GUI window which was created by a call to gui_mch_init().
345 */
346 int
347gui_mch_open()//{{{
348{
349 gui.dpy=qt_xdisplay();
350 set_normal_colors();
351
352 /* Check that none of the colors are the same as the background color */
353 gui_check_colors();
354
355 /* Get the colors for the highlight groups (gui_check_colors() might have
356 * changed them).
357 */
358 highlight_gui_started(); /* re-init colors and fonts */
359#ifdef FEAT_MENU
360 vmw->w->menu = new QPopupMenu(vmw);
361
362#if QT_VERSION>=300
363 vmw->w->menu->insertItem(SmallIcon("ktip"), i18n("&Tip of the day..."), vmw, SLOT(showTipOfTheDay()));
364 vmw->w->menu->insertSeparator();
365#endif
366 if (vmw->have_tearoff) vmw->w->menu->insertTearOffHandle(0,0);
367 vmw->w->menu->insertItem(i18n("&Report Bug ..."), vmw, SLOT(showBugReport()));
368 vmw->w->menu->insertSeparator();
369 vmw->w->menu->insertItem(SmallIcon("kvim"), i18n("&About KVim..."), vmw, SLOT(showAboutApplication()));
370 vmw->w->menu->insertItem(SmallIcon("about_kde"), i18n("About &KDE..."), vmw, SLOT(showAboutKDE()));
371 vmw->menuBar()->insertItem("&KVim", vmw->w->menu);
372#endif
373 if (startfont!=NULL)
374 gui_mch_init_font((char_u*)startfont->latin1(),0);
375
376 if (startsize!=NULL)
377 vmw->resize(startsize->width(), startsize->height());
378
379 gui_mch_update_codec();
380
381 if (kapp->isRestored())
382 if (KMainWindow::canBeRestored(1))
383 vmw->restore(1);
384
385 vmw->show();
386#if QT_VERSION>=300
387 if (tip==2) KTipDialog::showTip (vmw,QString::null,true);
388 else if (tip==0) KTipDialog::showTip (vmw);
389#endif
390
391 return OK;
392}//}}}
393
394 void
395gui_mch_exit(int rc)//{{{
396{
397 kapp->quit();
398}//}}}
399
400/*
401 * Get the position of the top left corner of the window.
402 */
403 int
404gui_mch_get_winpos(int *x, int *y)//{{{
405{
406 *x = vmw->x();
407 *y = vmw->y();
408 return OK;
409}//}}}
410
411/*
412 * Set the position of the top left corner of the window to the given
413 * coordinates.
414 */
415 void
416gui_mch_set_winpos(int x, int y)//{{{
417{
418 vmw->move(x,y);
419}//}}}
420
421/*
422 * Set the windows size.
423 * ->resize VimWidget
424 * ->resize vmw (block any events generated from here)
425 */
426void
427gui_mch_set_shellsize(int width, int height,//{{{
428 int min_width, int min_height,
429 int base_width, int base_height)
430{
431 //resize VimWidget
432 vmw->w->resize(width,height);
433
434 //resize vmw
435 int vheight, vwidth;
436 vheight = height;
437 vwidth = width;
438
439 if (gui.which_scrollbars[SBAR_LEFT]) vwidth+=gui.scrollbar_width;
440 if (gui.which_scrollbars[SBAR_RIGHT]) vwidth+=gui.scrollbar_width;
441 if (gui.which_scrollbars[SBAR_BOTTOM]) vheight+=gui.scrollbar_height;
442
443 if (vmw->menuBar()->isVisible() && vmw->menuBar()->isEnabled()
444#if QT_VERSION>=300
445 && !vmw->menuBar()->isTopLevelMenu()
446#endif
447 )
448 vheight += vmw->menuBar()->height();
449#ifdef FEAT_TOOLBAR
450 if (vmw->toolBar()->isVisible() && vmw->toolBar()->isEnabled() &&
451 (vmw->toolBar()->barPos()==KToolBar::Top ||
452 vmw->toolBar()->barPos()==KToolBar::Bottom))
453 vheight += vmw->toolBar()->height();
454
455 if (vmw->toolBar()->isVisible() && vmw->toolBar()->isEnabled() &&
456 (vmw->toolBar()->barPos()==KToolBar::Left ||
457 vmw->toolBar()->barPos()==KToolBar::Right))
458 vwidth += vmw->toolBar()->width();
459#endif
460 vmw->lock();
461 vmw->resize(vwidth,vheight);
462 gui_mch_update();
463 //size should be nearly perfect, update baseSize and sizeIncrement
464 vmw->setBaseSize(base_width,vmw->menuBar()->height()+1+vmw->toolBar()->height()+gui.char_height*2);
465 vmw->setSizeIncrement( ( ( int )( gui.char_width/2 )*2 ),gui.char_height);
466 vmw->unlock();
467}//}}}
468
469
470/*
471 * The screen size is used to make sure the initial window doesn't get bigger
472 * then the screen. This subtracts some room for menubar, toolbar and window
473 * decorations.
474 */
475 void
476gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)//{{{
477{
478 *screen_w = kapp->desktop()->width();
479 *screen_h = kapp->desktop()->height();
480}//}}}
481
482#if defined(FEAT_MENU) || defined(PROTO)
483 void
484gui_mch_enable_menu(int showit)//{{{
485{
486 if (showit)
487 vmw->menuBar()->show();
488 else
489 vmw->menuBar()->hide();
490 vmw->resize(vmw->width(),vmw->height());
491}//}}}
492#endif
493
494
495#if defined(FEAT_TOOLBAR) || defined(PROTO)
496 void
497gui_mch_show_toolbar(int showit)//{{{
498{
499 if (showit)
500 vmw->toolBar()->show();
501 else
502 vmw->toolBar()->hide();
503 vmw->resize(vmw->width(),vmw->height());
504}//}}}
505#endif
506
507/*
508 * Put up a font dialog and return the selected font name in allocated memory.
509 * "oldval" is the previous value.
510 * Return NULL when cancelled.
511 */
512
513char_u *gui_mch_font_dialog (char_u *oldval)//{{{
514{
515 QFont myFont( vmw->w->font() );
516 if (gui.fontname) {
517 gui.fontname=NULL;
518 }
519 int result = KFontDialog::getFont( myFont, true );
520 if ( result != KFontDialog::Accepted ) {
521 return NULL;
522 }
523// myFont.setFixedPitch(true);
524#if QT_VERSION>=300
525 QString n = myFont.toString();
526#else
527 QString n = KVimUtils::toString(&myFont);
528#endif
529 n.replace(QRegExp(","),"/");
530 gui.fontname = (char_u *)strdup((const char *)n);
531 n.replace(QRegExp(" "),"\\ ");
532 n=QString("To set this font as your default font for KVim, edit your ~/.gvimrc file and add the following lines : \nif has(\"gui_kde\")\nset guifont=")+n+QString("\nendif");// \n OR \n use the control center of KDE and choose the correct fixed font");
533
534 //display a message box which explains how to save your font settings
535 KMessageBox::information(vmw, n,"Font Selection", "kvimselectfont");
536
537 return vim_strsave(gui.fontname);
538}//}}}
539
540/*
541 * Initialise vim to use the font with the given name.
542 * Return FAIL if the font could not be loaded, OK otherwise.
543 */
544 int
545gui_mch_init_font(char_u * font_name, int fontset)//{{{
546{
547 QString fontname;
548 GuiFont font=NULL;
549
550 if (font_name==NULL) {
551#if 0
552#if QT_VERSION>=300
553 KConfig *base = KGlobal::config();
554#else
555 KConfigBase *base = KGlobal::config();
556#endif
557 base->setGroup("General");
558 if(!base->hasKey("fixed")) {
559 KMessageBox::error(KApplication::kApplication()->mainWidget(),"Cannot load default fixed font\n\nConfigure fonts in KDE Control Center.\n(Just click 'Choose...', 'OK' and then 'Apply')");
560 return FAIL;
561 }
562#if QT_VERSION>=300
563 QString f = base->readEntry("fixed");
564#else
565 QFont ft = base->readFontEntry("fixed", NULL);
566 QString f = KVimUtils::toString(&ft);
567#endif
568 font_name = (char_u*)strdup(f.latin1()); //latin1 ?
569#else
570 font_name = (char_u*)strdup("misc-fixed/10/-1/5/50/0/0/0/1/0");
571#endif
572 }
573 fontname = (const char *)font_name;
574/* fontname.replace(QRegExp("/"),",");
575 font = new QFont();
576 font->fromString( fontname );
577*/
578 gui_mch_free_font(gui.norm_font);
579#ifdef FEAT_XFONTSET
580 gui_mch_free_fontset(gui.fontset);
581 if (fontset)
582 font = gui_mch_get_fontset(font_name,TRUE,TRUE);
583#endif
584 if (font == NULL) {
585 font = gui_mch_get_font(font_name,FALSE);
586 gui.norm_font = font;
587#ifdef FEAT_XFONTSET
588 gui.fontset=NOFONTSET;
589#endif
590 }
591#ifdef FEAT_XFONTSET
592 else {
593 gui.fontset=font;
594 gui.norm_font=NOFONT;
595 }
596#endif
597
598 if (font == NULL)
599 return FAIL;
600
601 if (fontname.contains('*') && fontname.contains('-'))
602 return FAIL;
603
604 QFontMetrics f(*font);
605 gui.char_width = f.maxWidth();
606 gui.char_height = f.height()+p_linespace;
607 gui.char_ascent = f.ascent()+p_linespace/2;
608
609 //check values, just to make sure and avoid a crash
610 if (gui.char_width<=0) gui.char_width=8;
611 if (gui.char_height<=0) gui.char_height=1;
612
613 hl_set_font_name(font_name);
614
615 return OK;
616}//}}}
617
618 GuiFont
619gui_mch_get_font(char_u * name, int report_error)//{{{
620{
621 QString fontname((const char *)name);
622 if (!gui.in_use || name == NULL)
623 return NOFONT;
624 if (fontname.contains('*') && fontname.contains('-'))
625 return NOFONT; // XFLD names not allowed anymore
626 QFont *myFont = new QFont();
627 fontname.replace(QRegExp("/"),",");
628// myFont->setRawMode(TRUE);
629
630#if QT_VERSION>=300
631 myFont->fromString(fontname);
632#else
633 KVimUtils::fromString(myFont,fontname);
634#endif
635 myFont->setFixedPitch(true);
636 if (!myFont->fixedPitch()) dbf("Non fixed-width font");
637 return (GuiFont) myFont;
638}//}}}
639
640/*
641 * Set the current text font.
642 * Since we create all GC on demand, we use just gui.current_font to
643 * indicate the desired current font.
644 */
645 void
646gui_mch_set_font(GuiFont font)//{{{
647{
648 gui.current_font=font;
649 gui.w->painter->setFont( *(gui.current_font) );
650}//}}}
651
652/*
653 * If a font is not going to be used, free its structure.
654 */
655 void
656gui_mch_free_font(GuiFont font)//{{{
657{
658 if (font)
659 delete font; // this is a QFont , we can delete it :)
660}//}}}
661
662GuiFontset gui_mch_get_fontset (char_u *name, int report_error, int fixed_width)
663{
664 return (GuiFontset)gui_mch_get_font(name,report_error);
665}
666
667void gui_mch_set_fontset (GuiFontset fontset)
668{
669 gui_mch_set_font((GuiFont)fontset);
670}
671
672void gui_mch_free_fontset (GuiFontset fontset)
673{
674 if (fontset)
675 delete fontset;
676}
677
678void gui_mch_settitle (char_u *title, char_u *icon)//{{{
679{
680 if (!gui.in_use) /* can't do this when GUI not running */
681 return;
682 vmw->setPlainCaption((const char *)title);
683 QPixmap p((const char *)icon);
684 vmw->setIcon(p); //FIXME
685}//}}}
686
687/*
688 * Return the Pixel value (color) for the given color name. This routine was
689 * pretty much taken from example code in the Silicon Graphics OSF/Motif
690 * Programmer's Guide.
691 * Return -1 for error.
692 */
693 guicolor_T
694gui_mch_get_color(char_u * name)//{{{
695{
696 int i;
697 static char *(vimnames[][2]) =
698 {
699 /* A number of colors that some X11 systems don't have */
700 {"LightRed", "#FFA0A0"},
701 {"LightGreen", "#80FF80"},
702 {"LightMagenta", "#FFA0FF"},
703 {"DarkCyan", "#008080"},
704 {"DarkBlue", "#0000C0"},
705 {"DarkRed", "#C00000"},
706 {"DarkMagenta", "#C000C0"},
707 {"DarkGrey", "#C0C0C0"},
708 {NULL, NULL}
709 };
710
711 if (!gui.in_use) /* can't do this when GUI not running */
712 return (guicolor_T)(-1);
713
714 QColor _color((const char *)name);
715
716
717 if (_color.isValid()) {
718 //return (_color.red() << 16) + ((_color.green() << 8)) + (_color.blue());
719 return _color.rgb();
720 //return (guicolor_T) _color.pixel();
721 }
722
723 /* add a few builtin names */
724 for (i = 0;; ++i) {
725 if (vimnames[i][0] == NULL)
726 return (guicolor_T)(-1);
727 if (STRICMP(name, vimnames[i][0]) == 0) {
728 name = (char_u *) vimnames[i][1];
729 return gui_mch_get_color(name);
730 }
731 }
732
733 return (guicolor_T)(-1); // dead code, should not be reached..
734}//}}}
735
736/*
737 * Set the current text foreground color.
738 */
739 void
740gui_mch_set_fg_color(guicolor_T color)//{{{
741{
742 QColor rgb;
743 rgb.setRgb(color);
744 gui.w->painter->setPen( rgb );
745}//}}}
746
747/*
748 * Set the current text background color.
749 */
750 void
751gui_mch_set_bg_color(guicolor_T color)//{{{
752{
753 QColor rgb;
754 rgb.setRgb(color);
755 gui.w->painter->setBackgroundColor(rgb);
756}//}}}
757
758/*
759 * Use the blank mouse pointer or not.
760 *
761 * hide: TRUE = use blank ptr, FALSE = use parent ptr
762 */
763 void
764gui_mch_mousehide(int hide)//{{{
765{
766 if (hide == gui.pointer_hidden) return;
767 //#ifdef FEAT_MOUSESHAPE
768 // if( !hide) mch_set_mouse_shape(last_shape);
769 //#else
770# if (QT_VERSION<300)
771 gui.w->setCursor((hide)?BlankCursor:ArrowCursor);
772# else
773 gui.w->setCursor((hide)?Qt::BlankCursor:Qt::ArrowCursor);
774# endif
775 //#endif
776 gui.pointer_hidden = hide;
777}//}}}
778
779 void
780gui_mch_update_codec()
781{
782#ifdef FEAT_MBYTE
783 if (!gui.in_use) return;
784 vmw->codec = QTextCodec::codecForName((const char *)p_enc);
785 if (vmw->codec==NULL)
786 vmw->codec = QTextCodec::codecForName(KVimUtils::convertEncodingName(QString((const char*)p_enc)));
787 if (vmw->codec==NULL)
788 vmw->codec = QTextCodec::codecForLocale();
789#else
790 vmw->codec = QTextCodec::codecForLocale();
791#endif
792 if (vmw->codec==NULL)
793 vmw->codec = QTextCodec::codecForName("ISO-8859-1"); //fallback
794}
795
796 void
797gui_mch_draw_string(int row, int col, char_u * s, int len, int flags)//{{{
798{
799 QString text = vmw->codec->toUnicode((const char *)s,len);
800 gui.w->draw_string( TEXT_X(col), TEXT_Y(row), text, text.length(), flags );
801}//}}}
802
803#if defined(FEAT_TITLE) || defined(PROTO)
804/*
805 * Return the text window-id and display. Only required for X-based GUI's
806 */
807 int
808gui_get_x11_windis(Window * win, Display ** dis)//{{{
809{
810 *win = /*vmw*/gui.w->winId();
811 *dis = qt_xdisplay();
812 return OK;
813}//}}}
814#endif
815
816 void
817gui_mch_beep()//{{{
818{
819 kapp->beep();
820}//}}}
821
822 void
823gui_mch_flash(int msec)//{{{
824{
825 gui.w->flash();
826}//}}}
827
828/*
829 * Invert a rectangle from row r, column c, for nr rows and nc columns.
830 */
831 void
832gui_mch_invert_rectangle(int r, int c, int nr, int nc)//{{{
833{
834 bitBlt (
835 gui.w,
836 FILL_X(c), FILL_Y(r),
837 gui.w,
838 FILL_X(c), FILL_Y(r),
839 (nc) * gui.char_width,
840 (nr) * gui.char_height,
841 Qt::NotROP, // raster Operation
842 true ); // ignoreMask
843}//}}}
844
845/*
846 * Iconify the GUI window.
847 */
848 void
849gui_mch_iconify()//{{{
850{
851 vmw->showMinimized();
852}//}}}
853
854/*
855 * Draw a cursor without focus.
856 */
857 void
858gui_mch_draw_hollow_cursor(guicolor_T color)//{{{
859{
860 QPainter p(gui.w);
861 p.setPen( color );
862
863 p.drawRect(FILL_X(gui.col), FILL_Y(gui.row), gui.char_width - 1, gui.char_height - 1 );
864
865 p.end();
866}//}}}
867
868/*
869 * Draw part of a cursor, "w" pixels wide, and "h" pixels high, using
870 * color "color".
871 */
872 void
873gui_mch_draw_part_cursor(int w, int h, guicolor_T color)//{{{
874{
875 QPainter p(gui.w);
876 p.setPen( color );
877 p.fillRect(
878 FILL_X(gui.col),
879 FILL_Y(gui.row) + gui.char_height - h +1,
880 w, h-2, QColor( color, color));
881 p.drawRect(FILL_X(gui.col),FILL_Y(gui.row) + gui.char_height - h + (int)p_linespace / 2,
882 w, h - (int)p_linespace );
883
884}//}}}
885
886
887/*
888 * Catch up with any queued X11 events. This may put keyboard input into the
889 * input buffer, call resize call-backs, trigger timers etc. If there is
890 * nothing in the X11 event queue (& no timers pending), then we return
891 * immediately.
892 */
893 void
894gui_mch_update()//{{{
895{
896 kapp->processEvents();
897}//}}}
898
899
900/*
901 * GUI input routine called by gui_wait_for_chars(). Waits for a character
902 * from the keyboard.
903 * wtime == -1 Wait forever.
904 * wtime == 0 This should never happen.
905 * wtime > 0 Wait wtime milliseconds for a character.
906 * Returns OK if a character was found to be available within the given time,
907 * or FAIL otherwise.
908 */
909 int
910gui_mch_wait_for_chars(long wtime)//{{{
911{
912 // malte@kde.org's gift to KVim ;), thanks to him :) for this hard to find bug
913 if (wtime>0) {
914 gui.w->wait( wtime );
915 while ( vim_is_input_buf_empty() && !gui.w->wait_done )
916 kapp->processOneEvent();
917 return vim_is_input_buf_empty() ? FAIL : OK;
918 } else
919 while (vim_is_input_buf_empty() ) {
920 kapp->processOneEvent();
921 }
922
923 return OK;
924}//}}}
925
926
927/****************************************************************************
928 * Output drawing routines.
929 ****************************************************************************/
930
931
932/* Flush any output to the screen */
933 void
934gui_mch_flush()//{{{
935{
936 kapp->flushX();
937}//}}}
938
939/*
940 * Clear a rectangular region of the screen from text pos (row1, col1) to
941 * (row2, col2) inclusive.
942 */
943 void
944gui_mch_clear_block(int row1, int col1, int row2, int col2)//{{{
945{
946 gui.w->erase (FILL_X(col1), FILL_Y(row1),
947 (col2 - col1 + 1) * gui.char_width+ (col2 == Columns - 1),
948 (row2 - row1 + 1) * gui.char_height );
949}//}}}
950
951 void
952gui_mch_clear_all(void)//{{{
953{
954 gui.w->erase();
955}//}}}
956
957
958/*
959 * Delete the given number of lines from the given row, scrolling up any
960 * text further down within the scroll region.
961 */
962 void
963gui_mch_delete_lines(int row, int num_lines)//{{{
964{
965 if (num_lines <= 0)
966 return;
967
968 if (row + num_lines > gui.scroll_region_bot) {
969 /* Scrolled out of region, just blank the lines out */
970 gui_clear_block(row, gui.scroll_region_left, gui.scroll_region_bot, gui.scroll_region_right);
971 } else {
972 bitBlt (
973 gui.w,
974 FILL_X(gui.scroll_region_left), FILL_Y(row),
975 gui.w,
976 FILL_X(gui.scroll_region_left), FILL_Y(row + num_lines),
977 gui.char_width * (gui.scroll_region_right -gui.scroll_region_left + 1) + 1,
978 gui.char_height * (gui.scroll_region_bot - row - num_lines + 1),
979 Qt::CopyROP, // raster Operation
980 true ); // ignoreMask
981
982 /* Update gui.cursor_row if the cursor scrolled or copied over */
983 if (gui.cursor_row >= row) {
984 if (gui.cursor_row < row + num_lines)
985 gui.cursor_is_valid = FALSE;
986 else if (gui.cursor_row <= gui.scroll_region_bot)
987 gui.cursor_row -= num_lines;
988 }
989
990 gui_clear_block(gui.scroll_region_bot - num_lines + 1, gui.scroll_region_left,
991 gui.scroll_region_bot, gui.scroll_region_right);
992
993 }
994}//}}}
995
996/*
997 * Insert the given number of lines before the given row, scrolling down any
998 * following text within the scroll region.
999 */
1000 void
1001gui_mch_insert_lines(int row, int num_lines)//{{{
1002{
1003 if (num_lines <= 0)
1004 return;
1005
1006 if (row + num_lines > gui.scroll_region_bot) {
1007 /* Scrolled out of region, just blank the lines out */
1008 gui_clear_block(row, gui.scroll_region_left, gui.scroll_region_bot, gui.scroll_region_right - 1);
1009 } else {
1010 bitBlt (
1011 gui.w,
1012 FILL_X(gui.scroll_region_left), FILL_Y(row + num_lines),
1013 gui.w,
1014 FILL_X(gui.scroll_region_left), FILL_Y(row),
1015 gui.char_width * ( gui.scroll_region_right - gui.scroll_region_left + 1 ) + 1,
1016 gui.char_height * (gui.scroll_region_bot - row - num_lines + 1),
1017 Qt::CopyROP, // raster Operation
1018 true ); // ignoreMask
1019
1020 /* Update gui.cursor_row if the cursor scrolled or copied over */
1021 if (gui.cursor_row >= gui.row) {
1022 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
1023 gui.cursor_row += num_lines;
1024 else if (gui.cursor_row <= gui.scroll_region_bot)
1025 gui.cursor_is_valid = FALSE;
1026 }
1027
1028 gui_clear_block(row, gui.scroll_region_left, row + num_lines - 1, gui.scroll_region_right);
1029 }
1030}//}}}
1031
1032/*
1033 * X Selection stuff, for cutting and pasting text to other windows.
1034 */
1035 void
1036clip_mch_request_selection(VimClipboard *cbd)//{{{
1037{
1038#if QT_VERSION>=300
1039 if (cbd==&clip_star) kapp->clipboard()->setSelectionMode(true);
1040#endif
1041 QString selection = kapp->clipboard()->text();
1042
1043 QCString unistring = vmw->codec->fromUnicode(selection);
1044 clip_yank_selection(MCHAR,(char_u *)(const char*)unistring,(long) unistring.length(),cbd);
1045#if QT_VERSION>=300
1046 if (cbd==&clip_star) kapp->clipboard()->setSelectionMode(false);
1047#endif
1048}//}}}
1049
1050 void
1051clip_mch_lose_selection(VimClipboard *cbd)//{{{
1052{
1053 //Don't need to do anything here
1054 gui_mch_update();
1055}//}}}
1056
1057/*
1058 * Check whatever we allready own the selection.
1059 */
1060 int
1061clip_mch_own_selection(VimClipboard *cbd)//{{{
1062{
1063 if (kapp->clipboard()->ownsSelection())
1064 return OK;
1065 else {
1066#if QT_VERSION>=300
1067 kapp->clipboard()->setSelectionMode(true);
1068#endif
1069 return OK;
1070 }
1071}//}}}
1072
1073/*
1074 * Send the current selection to the clipboard.
1075 */
1076void
1077clip_mch_set_selection(VimClipboard *cbd){//{{{
1078 char_u *data;
1079 long_u length;
1080
1081 clip_get_selection(cbd);
1082 if(clip_convert_selection(&data,&length,cbd)<0) return;
1083
1084 QString selection((const char *) data);
1085 //We must turncate the string because it is not
1086 // null terminated
1087 selection.truncate((uint) length);
1088
1089#if QT_VERSION>=300
1090 if (cbd==&clip_star) kapp->clipboard()->setSelectionMode(true);
1091#endif
1092 kapp->clipboard()->setText(selection);
1093#if QT_VERSION>=300
1094 kapp->clipboard()->setSelectionMode(false);
1095#endif
1096}//}}}
1097
1098
1099#if defined(FEAT_MENU) || defined(PROTO)
1100/*
1101 * Make a menu item appear either active or not active (grey or not grey).
1102 */
1103 void
1104gui_mch_menu_grey(vimmenu_T * menu, int grey)//{{{
1105{
1106 if ( !menu || !menu->parent || !menu->parent->widget ) return;
1107 menu->parent->widget->setItemEnabled((int)menu, !grey);
1108 gui_mch_update();
1109}//}}}
1110
1111/*
1112 * Make menu item hidden or not hidden.
1113 */
1114 void
1115gui_mch_menu_hidden(vimmenu_T * menu, int hidden)//{{{
1116{
1117 //FIXME: cannot be fixed AFAIK
1118 gui_mch_menu_grey(menu,hidden); // it's hard to remove an item in a QPopupMenu
1119}//}}}
1120
1121/*
1122 * This is called after setting all the menus to grey/hidden or not.
1123 */
1124 void
1125gui_mch_draw_menubar()//{{{
1126{
1127 // nothing to do under kde
1128}//}}}
1129#endif
1130
1131/*
1132 * Scrollbar stuff.
1133 */
1134 void
1135gui_mch_enable_scrollbar(scrollbar_T * sb, int flag)//{{{
1136{
1137 if (!sb->w) return;
1138 int width = gui.w->width();
1139 int height = gui.w->height();
1140 int neww = vmw->width();
1141 int newh = vmw->height();
1142
1143 if (gui.which_scrollbars[SBAR_LEFT]) width += gui.scrollbar_width;
1144 if (gui.which_scrollbars[SBAR_RIGHT]) width += gui.scrollbar_width;
1145 if (gui.which_scrollbars[SBAR_BOTTOM]) height += gui.scrollbar_height;
1146
1147 if (vmw->menuBar()->isVisible() && vmw->menuBar()->isEnabled()
1148#if QT_VERSION>=300
1149 && !vmw->menuBar()->isTopLevelMenu()
1150#endif
1151 )
1152 height += vmw->menuBar()->height();
1153#ifdef FEAT_TOOLBAR
1154 if (vmw->toolBar()->isVisible() && vmw->toolBar()->isEnabled() &&
1155 (vmw->toolBar()->barPos()==KToolBar::Top ||
1156 vmw->toolBar()->barPos()==KToolBar::Bottom))
1157 height += vmw->toolBar()->height();
1158
1159 if (vmw->toolBar()->isVisible() && vmw->toolBar()->isEnabled() &&
1160 (vmw->toolBar()->barPos()==KToolBar::Left ||
1161 vmw->toolBar()->barPos()==KToolBar::Right))
1162 width += vmw->toolBar()->width();
1163#endif
1164 if ( abs(vmw->width() - width)>5 && (sb->type==SBAR_LEFT || sb->type==SBAR_RIGHT) )
1165 neww=width;
1166 if (abs(vmw->height() - height)>5 && (sb->type==SBAR_BOTTOM) )
1167 newh=height;
1168
1169 if (flag)
1170 sb->w->show();
1171 else
1172 sb->w->hide();
1173 gui_mch_update();
1174 vmw->lock();
1175 vmw->resize(neww,newh);
1176 vmw->unlock();
1177 gui_mch_update();
1178}//}}}
1179
1180/*
1181 * Return the RGB value of a pixel as "#RRGGBB".
1182 */
1183 long_u
1184gui_mch_get_rgb(guicolor_T pixel)//{{{
1185{
1186// QColor c(pixel,pixel);
1187// return (c.red() << 16) + ((c.green() << 8)) + (c.blue());
1188 return pixel; // funny no ? it looks like with Qt we can always use directly the rgb value (i hope i don't break colors again ;p)
1189}//}}}
1190
1191/*
1192 * Get current y mouse coordinate in text window.
1193 * Return -1 when unknown.
1194 */
1195 int
1196gui_mch_get_mouse_x(void)//{{{
1197{
1198 return vmw->mapFromGlobal( QCursor::pos() ).x();
1199}//}}}
1200
1201 int
1202gui_mch_get_mouse_y(void)//{{{
1203{
1204 return vmw->mapFromGlobal( QCursor::pos() ).y();
1205}//}}}
1206
1207 void
1208gui_mch_setmouse(int x, int y)//{{{
1209{
1210 QCursor::setPos( vmw->mapToGlobal( QPoint(x,y)) );
1211}//}}}
1212
1213#if defined(FEAT_MOUSESHAPE) || defined(PROTO)
1214#if QT_VERSION>=300
1215static int mshape_ids[] = {//{{{
1216 Qt::ArrowCursor, /* arrow */
1217 Qt::BlankCursor, /* blank */
1218 Qt::IbeamCursor, /* beam */
1219 Qt::SizeVerCursor, /* updown */
1220 Qt::SplitHCursor, /* udsizing */
1221 Qt::SizeHorCursor, /* leftright */
1222 Qt::SizeHorCursor, /* lrsizing */
1223 Qt::WaitCursor, /* busy */
1224 Qt::ForbiddenCursor, /* no */
1225 Qt::CrossCursor, /* crosshair */
1226 Qt::PointingHandCursor, /* hand1 */
1227 Qt::PointingHandCursor, /* hand2 */
1228 Qt::ArrowCursor, /* pencil */
1229 Qt::WhatsThisCursor, /* question */
1230 Qt::ArrowCursor, /* right-arrow */
1231 Qt::UpArrowCursor, /* up-arrow */
1232 Qt::ArrowCursor /* last one */
1233};//}}}
1234#else
1235static int mshape_ids[] = {//{{{
1236 ArrowCursor, /* arrow */
1237 BlankCursor, /* blank */
1238 IbeamCursor, /* beam */
1239 SizeVerCursor, /* updown */
1240 SplitHCursor, /* udsizing */
1241 SizeHorCursor, /* leftright */
1242 SizeHorCursor, /* lrsizing */
1243 WaitCursor, /* busy */
1244 ForbiddenCursor, /* no */
1245 CrossCursor, /* crosshair */
1246 PointingHandCursor, /* hand1 */
1247 PointingHandCursor, /* hand2 */
1248 ArrowCursor, /* pencil */
1249 ArrowCursor, /* question */
1250 ArrowCursor, /* right-arrow */
1251 UpArrowCursor, /* up-arrow */
1252 ArrowCursor /* last one */
1253};//}}}
1254#endif
1255
1256 void
1257mch_set_mouse_shape (int shape)//{{{
1258{
1259 int id;
1260
1261 if (shape == MSHAPE_HIDE || gui.pointer_hidden)
1262#if QT_VERSION>=300
1263 gui.w->setCursor(Qt::BlankCursor);
1264#else
1265 gui.w->setCursor(BlankCursor);
1266#endif
1267 else
1268 {
1269 if (shape >= MSHAPE_NUMBERED)
1270 {
1271 id = shape - MSHAPE_NUMBERED;
1272 /* if (id >= GDK_NUM_GLYPHS)
1273 id = GDK_LEFT_PTR;
1274 else
1275 id &= ~1;*/ /* they are always even (why?) */
1276 id &= -1;
1277 }
1278 else
1279 id = mshape_ids[shape];
1280
1281 gui.w->setCursor(id);
1282 }
1283 if (shape != MSHAPE_HIDE)
1284 last_shape = shape;
1285}//}}}
1286#endif
1287
1288 int
1289gui_mch_adjust_charsize ()//{{{
1290{
1291 QFont f(*(gui.current_font));
1292 QFontMetrics fm (f);
1293 gui.char_height = fm.height() + p_linespace;
1294 //gui.char_height = fm.ascent() + fm.descent() + p_linespace;
1295 gui.char_ascent = fm.ascent() + p_linespace/2;
1296
1297 return OK;
1298}//}}}
1299
1300 void
1301gui_mch_set_foreground ()//{{{
1302{
1303 KWin::setActiveWindow(vmw->winId());
1304}//}}}
1305
1306
1307