blob: 77a7f807cb02de22c7d142be697ee8e53a69499a [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
Bram Moolenaar5eb86f92004-07-26 12:53:41 +000048#include "gui_kde_wid.h"
Bram Moolenaar843ee412004-06-30 16:16:41 +000049
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 }
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000115
Bram Moolenaar843ee412004-06-30 16:16:41 +0000116 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 }
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000185
Bram Moolenaar843ee412004-06-30 16:16:41 +0000186
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 }
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000214
Bram Moolenaar843ee412004-06-30 16:16:41 +0000215 //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
Bram Moolenaar2df6dcc2004-07-12 15:53:54 +0000257#ifdef FEAT_MZSCHEME
258 void
259mzscheme_kde_start_timer()//{{{
260{
261 gui.w->enable_mzscheme_threads();
262}//}}}
263 void
264mzscheme_kde_stop_timer()//{{{
265{
266 gui.w->disable_mzscheme_threads();
267}//}}}
268#endif
269
Bram Moolenaar843ee412004-06-30 16:16:41 +0000270/*
271 * Check if the GUI can be started. Called before gvimrc is sourced.
272 * Return OK or FAIL.
273 */
274 int
275gui_mch_init_check(void)//{{{
276{
277 gui.dpy = qt_xdisplay();
278 return OK;
279}//}}}
280
281/*
282 * Initialise the X GUI. Create all the windows, set up all the call-backs etc.
283 * Returns OK for success, FAIL when the GUI can't be started.
284 */
285 int
286gui_mch_init()//{{{
287{
288 (void) new KApplication();
289 KApplication::kApplication()->dcopClient()->registerAs(KApplication::kApplication()->name(),false);
290// dbf("%s %s",KGlobal::locale()->language().latin1(),KLocale::defaultLanguage().latin1());
291
292 vmw = new VimMainWindow("KVim",0);
293 vmw->setFrameBorderWidth(0);
294 kapp->setMainWidget(vmw);
295 kapp->setTopWidget(vmw);
296
297 sbpool = new SBPool;
298
299#if QT_VERSION>=300
300 vmw->connect(kapp->clipboard(),SIGNAL(selectionChanged()),vmw,SLOT(clipboard_selection_update()));
301#endif
302 vmw->connect(kapp->clipboard(),SIGNAL(dataChanged()),vmw,SLOT(clipboard_data_update()));
303 clip_lose_selection(&clip_plus);
304 clip_lose_selection(&clip_star);
305
306 gui.in_focus = FALSE; // will be updated
307
308 if (reverse) {
309 gui.def_norm_pixel = gui_get_color((char_u *)"White");
310 gui.def_back_pixel = gui_get_color((char_u *)"Black");
311#if QT_VERSION>=300
312 gui.w->setEraseColor ( QColor(Qt::black) );
313#else
314 gui.w->setBackgroundColor ( QColor(Qt::black) );
315#endif
316 } else {
317 gui.def_norm_pixel = gui_get_color((char_u *)"Black");
318 gui.def_back_pixel = gui_get_color((char_u *)"White");
319#if QT_VERSION>=300
320 gui.w->setEraseColor ( QColor(Qt::white) );
321#else
322 gui.w->setBackgroundColor ( QColor(Qt::white) );
323#endif
324 }
325
326 gui.norm_pixel = gui.def_norm_pixel;
327 gui.back_pixel = gui.def_back_pixel;
328
329 gui.border_width = 1;
330 gui.border_offset = 1;//gui.border_width;
331 gui.scrollbar_width=SB_DEFAULT_WIDTH;
332 gui.scrollbar_height=SB_DEFAULT_WIDTH;
333
334 //gui.menu_height=vmw->menuBar()->height()+1;
335 //gui.toolbar_height=vmw->toolBar()->height();
336
337 return OK;
338}//}}}
339
340
341/*
342 * Called when the foreground or background color has been changed.
343 */
344 void
345gui_mch_new_colors()//{{{
346{
347 QColor rgb;
348 rgb.setRgb(gui.back_pixel);
349#if QT_VERSION>=300
350 gui.w->setEraseColor(rgb);
351#else
352 gui.w->setBackgroundColor(rgb);
353#endif
354}//}}}
355
356/*
357 * Open the GUI window which was created by a call to gui_mch_init().
358 */
359 int
360gui_mch_open()//{{{
361{
362 gui.dpy=qt_xdisplay();
363 set_normal_colors();
364
365 /* Check that none of the colors are the same as the background color */
366 gui_check_colors();
367
368 /* Get the colors for the highlight groups (gui_check_colors() might have
369 * changed them).
370 */
371 highlight_gui_started(); /* re-init colors and fonts */
372#ifdef FEAT_MENU
373 vmw->w->menu = new QPopupMenu(vmw);
374
375#if QT_VERSION>=300
376 vmw->w->menu->insertItem(SmallIcon("ktip"), i18n("&Tip of the day..."), vmw, SLOT(showTipOfTheDay()));
377 vmw->w->menu->insertSeparator();
378#endif
379 if (vmw->have_tearoff) vmw->w->menu->insertTearOffHandle(0,0);
380 vmw->w->menu->insertItem(i18n("&Report Bug ..."), vmw, SLOT(showBugReport()));
381 vmw->w->menu->insertSeparator();
382 vmw->w->menu->insertItem(SmallIcon("kvim"), i18n("&About KVim..."), vmw, SLOT(showAboutApplication()));
383 vmw->w->menu->insertItem(SmallIcon("about_kde"), i18n("About &KDE..."), vmw, SLOT(showAboutKDE()));
384 vmw->menuBar()->insertItem("&KVim", vmw->w->menu);
385#endif
386 if (startfont!=NULL)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +0000387 gui_mch_init_font((char_u*)startfont->latin1(), FALSE);
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000388
Bram Moolenaar843ee412004-06-30 16:16:41 +0000389 if (startsize!=NULL)
390 vmw->resize(startsize->width(), startsize->height());
391
392 gui_mch_update_codec();
393
394 if (kapp->isRestored())
395 if (KMainWindow::canBeRestored(1))
396 vmw->restore(1);
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000397
Bram Moolenaar843ee412004-06-30 16:16:41 +0000398 vmw->show();
399#if QT_VERSION>=300
400 if (tip==2) KTipDialog::showTip (vmw,QString::null,true);
401 else if (tip==0) KTipDialog::showTip (vmw);
402#endif
403
404 return OK;
405}//}}}
406
407 void
408gui_mch_exit(int rc)//{{{
409{
410 kapp->quit();
411}//}}}
412
413/*
414 * Get the position of the top left corner of the window.
415 */
416 int
417gui_mch_get_winpos(int *x, int *y)//{{{
418{
419 *x = vmw->x();
420 *y = vmw->y();
421 return OK;
422}//}}}
423
424/*
425 * Set the position of the top left corner of the window to the given
426 * coordinates.
427 */
428 void
429gui_mch_set_winpos(int x, int y)//{{{
430{
431 vmw->move(x,y);
432}//}}}
433
434/*
435 * Set the windows size.
436 * ->resize VimWidget
437 * ->resize vmw (block any events generated from here)
438 */
439void
440gui_mch_set_shellsize(int width, int height,//{{{
441 int min_width, int min_height,
442 int base_width, int base_height)
443{
444 //resize VimWidget
445 vmw->w->resize(width,height);
446
447 //resize vmw
448 int vheight, vwidth;
449 vheight = height;
450 vwidth = width;
451
452 if (gui.which_scrollbars[SBAR_LEFT]) vwidth+=gui.scrollbar_width;
453 if (gui.which_scrollbars[SBAR_RIGHT]) vwidth+=gui.scrollbar_width;
454 if (gui.which_scrollbars[SBAR_BOTTOM]) vheight+=gui.scrollbar_height;
455
456 if (vmw->menuBar()->isVisible() && vmw->menuBar()->isEnabled()
457#if QT_VERSION>=300
458 && !vmw->menuBar()->isTopLevelMenu()
459#endif
460 )
461 vheight += vmw->menuBar()->height();
462#ifdef FEAT_TOOLBAR
463 if (vmw->toolBar()->isVisible() && vmw->toolBar()->isEnabled() &&
464 (vmw->toolBar()->barPos()==KToolBar::Top ||
465 vmw->toolBar()->barPos()==KToolBar::Bottom))
466 vheight += vmw->toolBar()->height();
467
468 if (vmw->toolBar()->isVisible() && vmw->toolBar()->isEnabled() &&
469 (vmw->toolBar()->barPos()==KToolBar::Left ||
470 vmw->toolBar()->barPos()==KToolBar::Right))
471 vwidth += vmw->toolBar()->width();
472#endif
473 vmw->lock();
474 vmw->resize(vwidth,vheight);
475 gui_mch_update();
476 //size should be nearly perfect, update baseSize and sizeIncrement
477 vmw->setBaseSize(base_width,vmw->menuBar()->height()+1+vmw->toolBar()->height()+gui.char_height*2);
478 vmw->setSizeIncrement( ( ( int )( gui.char_width/2 )*2 ),gui.char_height);
479 vmw->unlock();
480}//}}}
481
482
483/*
484 * The screen size is used to make sure the initial window doesn't get bigger
485 * then the screen. This subtracts some room for menubar, toolbar and window
486 * decorations.
487 */
488 void
489gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)//{{{
490{
491 *screen_w = kapp->desktop()->width();
492 *screen_h = kapp->desktop()->height();
493}//}}}
494
495#if defined(FEAT_MENU) || defined(PROTO)
496 void
497gui_mch_enable_menu(int showit)//{{{
498{
499 if (showit)
500 vmw->menuBar()->show();
501 else
502 vmw->menuBar()->hide();
503 vmw->resize(vmw->width(),vmw->height());
504}//}}}
505#endif
506
507
508#if defined(FEAT_TOOLBAR) || defined(PROTO)
509 void
510gui_mch_show_toolbar(int showit)//{{{
511{
512 if (showit)
513 vmw->toolBar()->show();
514 else
515 vmw->toolBar()->hide();
516 vmw->resize(vmw->width(),vmw->height());
517}//}}}
518#endif
519
520/*
521 * Put up a font dialog and return the selected font name in allocated memory.
522 * "oldval" is the previous value.
523 * Return NULL when cancelled.
524 */
525
526char_u *gui_mch_font_dialog (char_u *oldval)//{{{
527{
528 QFont myFont( vmw->w->font() );
529 if (gui.fontname) {
530 gui.fontname=NULL;
531 }
532 int result = KFontDialog::getFont( myFont, true );
533 if ( result != KFontDialog::Accepted ) {
534 return NULL;
535 }
536// myFont.setFixedPitch(true);
537#if QT_VERSION>=300
538 QString n = myFont.toString();
539#else
540 QString n = KVimUtils::toString(&myFont);
541#endif
542 n.replace(QRegExp(","),"/");
543 gui.fontname = (char_u *)strdup((const char *)n);
544 n.replace(QRegExp(" "),"\\ ");
545 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");
546
547 //display a message box which explains how to save your font settings
548 KMessageBox::information(vmw, n,"Font Selection", "kvimselectfont");
549
550 return vim_strsave(gui.fontname);
551}//}}}
552
553/*
554 * Initialise vim to use the font with the given name.
555 * Return FAIL if the font could not be loaded, OK otherwise.
556 */
557 int
558gui_mch_init_font(char_u * font_name, int fontset)//{{{
559{
560 QString fontname;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +0000561 GuiFont font = NULL;
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000562
Bram Moolenaard8b0cf12004-12-12 11:33:30 +0000563 if (font_name == NULL)
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000564 {
Bram Moolenaar843ee412004-06-30 16:16:41 +0000565#if 0
566#if QT_VERSION>=300
567 KConfig *base = KGlobal::config();
568#else
569 KConfigBase *base = KGlobal::config();
570#endif
571 base->setGroup("General");
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000572 if (!base->hasKey("fixed")) {
Bram Moolenaar843ee412004-06-30 16:16:41 +0000573 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')");
574 return FAIL;
575 }
576#if QT_VERSION>=300
577 QString f = base->readEntry("fixed");
578#else
579 QFont ft = base->readFontEntry("fixed", NULL);
580 QString f = KVimUtils::toString(&ft);
581#endif
582 font_name = (char_u*)strdup(f.latin1()); //latin1 ?
583#else
584 font_name = (char_u*)strdup("misc-fixed/10/-1/5/50/0/0/0/1/0");
585#endif
586 }
587 fontname = (const char *)font_name;
588/* fontname.replace(QRegExp("/"),",");
589 font = new QFont();
590 font->fromString( fontname );
591*/
Bram Moolenaard8b0cf12004-12-12 11:33:30 +0000592#ifdef FEAT_XFONTSET
593 if (fontset)
594 font = gui_mch_get_fontset(font_name, TRUE, TRUE);
595 if (font == NULL)
596#endif
597 font = gui_mch_get_font(font_name, FALSE);
598
599 if (font == NULL)
600 return FAIL;
601 if (fontname.contains('*') && fontname.contains('-'))
602 return FAIL;
603
Bram Moolenaar843ee412004-06-30 16:16:41 +0000604 gui_mch_free_font(gui.norm_font);
605#ifdef FEAT_XFONTSET
606 gui_mch_free_fontset(gui.fontset);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +0000607 gui.fontset = NOFONTSET;
Bram Moolenaar843ee412004-06-30 16:16:41 +0000608 if (fontset)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +0000609 {
610 gui.fontset = font;
611 gui.norm_font = NOFONT;
612 }
613 else
Bram Moolenaar843ee412004-06-30 16:16:41 +0000614#endif
Bram Moolenaar843ee412004-06-30 16:16:41 +0000615 gui.norm_font = font;
Bram Moolenaar843ee412004-06-30 16:16:41 +0000616
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000617 /* Compute the width of the character cell. Some fonts include
618 * double-width characters. Use the width of ASCII characters to find
619 * out if this is so. */
Bram Moolenaar843ee412004-06-30 16:16:41 +0000620 QFontMetrics f(*font);
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000621 int width_max = 0;
622 for (char c = 32; c < 127; c++)
623 if (width_max < f.width((QChar)c))
624 width_max = f.width((QChar)c);
625 if (width_max <= f.maxWidth() / 2)
626 width_max = f.maxWidth() / 2;
627 gui.char_width = width_max;
Bram Moolenaar843ee412004-06-30 16:16:41 +0000628 gui.char_height = f.height()+p_linespace;
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000629 gui.char_ascent = f.ascent()+p_linespace;
630
Bram Moolenaar843ee412004-06-30 16:16:41 +0000631 //check values, just to make sure and avoid a crash
632 if (gui.char_width<=0) gui.char_width=8;
633 if (gui.char_height<=0) gui.char_height=1;
634
635 hl_set_font_name(font_name);
636
637 return OK;
638}//}}}
639
640 GuiFont
641gui_mch_get_font(char_u * name, int report_error)//{{{
642{
643 QString fontname((const char *)name);
644 if (!gui.in_use || name == NULL)
645 return NOFONT;
646 if (fontname.contains('*') && fontname.contains('-'))
647 return NOFONT; // XFLD names not allowed anymore
648 QFont *myFont = new QFont();
649 fontname.replace(QRegExp("/"),",");
650// myFont->setRawMode(TRUE);
651
652#if QT_VERSION>=300
653 myFont->fromString(fontname);
654#else
655 KVimUtils::fromString(myFont,fontname);
656#endif
657 myFont->setFixedPitch(true);
658 if (!myFont->fixedPitch()) dbf("Non fixed-width font");
659 return (GuiFont) myFont;
660}//}}}
661
662/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +0000663 * Return the name of font "font" in allocated memory.
664 * Don't know how to get the actual name, thus use the provided name.
665 */
666 char_u *
667gui_mch_get_fontname(font, name)
668 GuiFont font;
669 char_u *name;
670{
671 if (name == NULL)
672 return NULL;
673 return vim_strsave(name);
674}
675
676/*
Bram Moolenaar843ee412004-06-30 16:16:41 +0000677 * Set the current text font.
678 * Since we create all GC on demand, we use just gui.current_font to
679 * indicate the desired current font.
680 */
681 void
682gui_mch_set_font(GuiFont font)//{{{
683{
684 gui.current_font=font;
685 gui.w->painter->setFont( *(gui.current_font) );
686}//}}}
687
688/*
689 * If a font is not going to be used, free its structure.
690 */
691 void
692gui_mch_free_font(GuiFont font)//{{{
693{
694 if (font)
695 delete font; // this is a QFont , we can delete it :)
696}//}}}
697
698GuiFontset gui_mch_get_fontset (char_u *name, int report_error, int fixed_width)
699{
700 return (GuiFontset)gui_mch_get_font(name,report_error);
701}
702
703void gui_mch_set_fontset (GuiFontset fontset)
704{
705 gui_mch_set_font((GuiFont)fontset);
706}
707
708void gui_mch_free_fontset (GuiFontset fontset)
709{
710 if (fontset)
711 delete fontset;
712}
713
714void gui_mch_settitle (char_u *title, char_u *icon)//{{{
715{
716 if (!gui.in_use) /* can't do this when GUI not running */
717 return;
718 vmw->setPlainCaption((const char *)title);
719 QPixmap p((const char *)icon);
720 vmw->setIcon(p); //FIXME
721}//}}}
722
723/*
724 * Return the Pixel value (color) for the given color name. This routine was
725 * pretty much taken from example code in the Silicon Graphics OSF/Motif
726 * Programmer's Guide.
727 * Return -1 for error.
728 */
729 guicolor_T
730gui_mch_get_color(char_u * name)//{{{
731{
732 int i;
733 static char *(vimnames[][2]) =
734 {
735 /* A number of colors that some X11 systems don't have */
736 {"LightRed", "#FFA0A0"},
737 {"LightGreen", "#80FF80"},
738 {"LightMagenta", "#FFA0FF"},
739 {"DarkCyan", "#008080"},
740 {"DarkBlue", "#0000C0"},
741 {"DarkRed", "#C00000"},
742 {"DarkMagenta", "#C000C0"},
743 {"DarkGrey", "#C0C0C0"},
744 {NULL, NULL}
745 };
746
747 if (!gui.in_use) /* can't do this when GUI not running */
748 return (guicolor_T)(-1);
749
750 QColor _color((const char *)name);
751
752
753 if (_color.isValid()) {
754 //return (_color.red() << 16) + ((_color.green() << 8)) + (_color.blue());
755 return _color.rgb();
756 //return (guicolor_T) _color.pixel();
757 }
758
759 /* add a few builtin names */
760 for (i = 0;; ++i) {
761 if (vimnames[i][0] == NULL)
762 return (guicolor_T)(-1);
763 if (STRICMP(name, vimnames[i][0]) == 0) {
764 name = (char_u *) vimnames[i][1];
765 return gui_mch_get_color(name);
766 }
767 }
768
769 return (guicolor_T)(-1); // dead code, should not be reached..
770}//}}}
771
772/*
773 * Set the current text foreground color.
774 */
775 void
776gui_mch_set_fg_color(guicolor_T color)//{{{
777{
778 QColor rgb;
779 rgb.setRgb(color);
780 gui.w->painter->setPen( rgb );
781}//}}}
782
783/*
784 * Set the current text background color.
785 */
786 void
787gui_mch_set_bg_color(guicolor_T color)//{{{
788{
789 QColor rgb;
790 rgb.setRgb(color);
791 gui.w->painter->setBackgroundColor(rgb);
792}//}}}
793
794/*
795 * Use the blank mouse pointer or not.
796 *
797 * hide: TRUE = use blank ptr, FALSE = use parent ptr
798 */
799 void
800gui_mch_mousehide(int hide)//{{{
801{
802 if (hide == gui.pointer_hidden) return;
803 //#ifdef FEAT_MOUSESHAPE
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +0000804 // if (!hide) mch_set_mouse_shape(last_shape);
Bram Moolenaar843ee412004-06-30 16:16:41 +0000805 //#else
806# if (QT_VERSION<300)
807 gui.w->setCursor((hide)?BlankCursor:ArrowCursor);
808# else
809 gui.w->setCursor((hide)?Qt::BlankCursor:Qt::ArrowCursor);
810# endif
811 //#endif
812 gui.pointer_hidden = hide;
813}//}}}
814
815 void
816gui_mch_update_codec()
817{
818#ifdef FEAT_MBYTE
819 if (!gui.in_use) return;
820 vmw->codec = QTextCodec::codecForName((const char *)p_enc);
821 if (vmw->codec==NULL)
822 vmw->codec = QTextCodec::codecForName(KVimUtils::convertEncodingName(QString((const char*)p_enc)));
823 if (vmw->codec==NULL)
824 vmw->codec = QTextCodec::codecForLocale();
825#else
826 vmw->codec = QTextCodec::codecForLocale();
827#endif
828 if (vmw->codec==NULL)
829 vmw->codec = QTextCodec::codecForName("ISO-8859-1"); //fallback
830}
831
832 void
833gui_mch_draw_string(int row, int col, char_u * s, int len, int flags)//{{{
834{
835 QString text = vmw->codec->toUnicode((const char *)s,len);
836 gui.w->draw_string( TEXT_X(col), TEXT_Y(row), text, text.length(), flags );
837}//}}}
838
839#if defined(FEAT_TITLE) || defined(PROTO)
840/*
841 * Return the text window-id and display. Only required for X-based GUI's
842 */
843 int
844gui_get_x11_windis(Window * win, Display ** dis)//{{{
845{
846 *win = /*vmw*/gui.w->winId();
847 *dis = qt_xdisplay();
848 return OK;
849}//}}}
850#endif
851
852 void
853gui_mch_beep()//{{{
854{
855 kapp->beep();
856}//}}}
857
858 void
859gui_mch_flash(int msec)//{{{
860{
861 gui.w->flash();
862}//}}}
863
864/*
865 * Invert a rectangle from row r, column c, for nr rows and nc columns.
866 */
867 void
868gui_mch_invert_rectangle(int r, int c, int nr, int nc)//{{{
869{
870 bitBlt (
871 gui.w,
872 FILL_X(c), FILL_Y(r),
873 gui.w,
874 FILL_X(c), FILL_Y(r),
875 (nc) * gui.char_width,
876 (nr) * gui.char_height,
877 Qt::NotROP, // raster Operation
878 true ); // ignoreMask
879}//}}}
880
881/*
882 * Iconify the GUI window.
883 */
884 void
885gui_mch_iconify()//{{{
886{
887 vmw->showMinimized();
888}//}}}
889
890/*
891 * Draw a cursor without focus.
892 */
893 void
894gui_mch_draw_hollow_cursor(guicolor_T color)//{{{
895{
896 QPainter p(gui.w);
897 p.setPen( color );
898
899 p.drawRect(FILL_X(gui.col), FILL_Y(gui.row), gui.char_width - 1, gui.char_height - 1 );
900
901 p.end();
902}//}}}
903
904/*
905 * Draw part of a cursor, "w" pixels wide, and "h" pixels high, using
906 * color "color".
907 */
908 void
909gui_mch_draw_part_cursor(int w, int h, guicolor_T color)//{{{
910{
911 QPainter p(gui.w);
912 p.setPen( color );
913 p.fillRect(
914 FILL_X(gui.col),
915 FILL_Y(gui.row) + gui.char_height - h +1,
916 w, h-2, QColor( color, color));
917 p.drawRect(FILL_X(gui.col),FILL_Y(gui.row) + gui.char_height - h + (int)p_linespace / 2,
918 w, h - (int)p_linespace );
919
920}//}}}
921
922
923/*
924 * Catch up with any queued X11 events. This may put keyboard input into the
925 * input buffer, call resize call-backs, trigger timers etc. If there is
926 * nothing in the X11 event queue (& no timers pending), then we return
927 * immediately.
928 */
929 void
930gui_mch_update()//{{{
931{
932 kapp->processEvents();
933}//}}}
934
935
936/*
937 * GUI input routine called by gui_wait_for_chars(). Waits for a character
938 * from the keyboard.
939 * wtime == -1 Wait forever.
940 * wtime == 0 This should never happen.
941 * wtime > 0 Wait wtime milliseconds for a character.
942 * Returns OK if a character was found to be available within the given time,
943 * or FAIL otherwise.
944 */
945 int
946gui_mch_wait_for_chars(long wtime)//{{{
947{
948 // malte@kde.org's gift to KVim ;), thanks to him :) for this hard to find bug
949 if (wtime>0) {
950 gui.w->wait( wtime );
951 while ( vim_is_input_buf_empty() && !gui.w->wait_done )
952 kapp->processOneEvent();
953 return vim_is_input_buf_empty() ? FAIL : OK;
954 } else
955 while (vim_is_input_buf_empty() ) {
956 kapp->processOneEvent();
957 }
958
959 return OK;
960}//}}}
961
962
963/****************************************************************************
964 * Output drawing routines.
965 ****************************************************************************/
966
967
968/* Flush any output to the screen */
969 void
970gui_mch_flush()//{{{
971{
972 kapp->flushX();
973}//}}}
974
975/*
976 * Clear a rectangular region of the screen from text pos (row1, col1) to
977 * (row2, col2) inclusive.
978 */
979 void
980gui_mch_clear_block(int row1, int col1, int row2, int col2)//{{{
981{
982 gui.w->erase (FILL_X(col1), FILL_Y(row1),
983 (col2 - col1 + 1) * gui.char_width+ (col2 == Columns - 1),
984 (row2 - row1 + 1) * gui.char_height );
985}//}}}
986
987 void
988gui_mch_clear_all(void)//{{{
989{
990 gui.w->erase();
991}//}}}
992
993
994/*
995 * Delete the given number of lines from the given row, scrolling up any
996 * text further down within the scroll region.
997 */
998 void
999gui_mch_delete_lines(int row, int num_lines)//{{{
1000{
1001 if (num_lines <= 0)
1002 return;
1003
1004 if (row + num_lines > gui.scroll_region_bot) {
1005 /* Scrolled out of region, just blank the lines out */
1006 gui_clear_block(row, gui.scroll_region_left, gui.scroll_region_bot, gui.scroll_region_right);
1007 } else {
1008 bitBlt (
1009 gui.w,
1010 FILL_X(gui.scroll_region_left), FILL_Y(row),
1011 gui.w,
1012 FILL_X(gui.scroll_region_left), FILL_Y(row + num_lines),
1013 gui.char_width * (gui.scroll_region_right -gui.scroll_region_left + 1) + 1,
1014 gui.char_height * (gui.scroll_region_bot - row - num_lines + 1),
1015 Qt::CopyROP, // raster Operation
1016 true ); // ignoreMask
1017
1018 /* Update gui.cursor_row if the cursor scrolled or copied over */
1019 if (gui.cursor_row >= row) {
1020 if (gui.cursor_row < row + num_lines)
1021 gui.cursor_is_valid = FALSE;
1022 else if (gui.cursor_row <= gui.scroll_region_bot)
1023 gui.cursor_row -= num_lines;
1024 }
1025
1026 gui_clear_block(gui.scroll_region_bot - num_lines + 1, gui.scroll_region_left,
1027 gui.scroll_region_bot, gui.scroll_region_right);
1028
1029 }
1030}//}}}
1031
1032/*
1033 * Insert the given number of lines before the given row, scrolling down any
1034 * following text within the scroll region.
1035 */
1036 void
1037gui_mch_insert_lines(int row, int num_lines)//{{{
1038{
1039 if (num_lines <= 0)
1040 return;
1041
1042 if (row + num_lines > gui.scroll_region_bot) {
1043 /* Scrolled out of region, just blank the lines out */
1044 gui_clear_block(row, gui.scroll_region_left, gui.scroll_region_bot, gui.scroll_region_right - 1);
1045 } else {
1046 bitBlt (
1047 gui.w,
1048 FILL_X(gui.scroll_region_left), FILL_Y(row + num_lines),
1049 gui.w,
1050 FILL_X(gui.scroll_region_left), FILL_Y(row),
1051 gui.char_width * ( gui.scroll_region_right - gui.scroll_region_left + 1 ) + 1,
1052 gui.char_height * (gui.scroll_region_bot - row - num_lines + 1),
1053 Qt::CopyROP, // raster Operation
1054 true ); // ignoreMask
1055
1056 /* Update gui.cursor_row if the cursor scrolled or copied over */
1057 if (gui.cursor_row >= gui.row) {
1058 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
1059 gui.cursor_row += num_lines;
1060 else if (gui.cursor_row <= gui.scroll_region_bot)
1061 gui.cursor_is_valid = FALSE;
1062 }
1063
1064 gui_clear_block(row, gui.scroll_region_left, row + num_lines - 1, gui.scroll_region_right);
1065 }
1066}//}}}
1067
1068/*
1069 * X Selection stuff, for cutting and pasting text to other windows.
1070 */
1071 void
1072clip_mch_request_selection(VimClipboard *cbd)//{{{
1073{
1074#if QT_VERSION>=300
1075 if (cbd==&clip_star) kapp->clipboard()->setSelectionMode(true);
1076#endif
1077 QString selection = kapp->clipboard()->text();
1078
1079 QCString unistring = vmw->codec->fromUnicode(selection);
1080 clip_yank_selection(MCHAR,(char_u *)(const char*)unistring,(long) unistring.length(),cbd);
1081#if QT_VERSION>=300
1082 if (cbd==&clip_star) kapp->clipboard()->setSelectionMode(false);
1083#endif
1084}//}}}
1085
1086 void
1087clip_mch_lose_selection(VimClipboard *cbd)//{{{
1088{
1089 //Don't need to do anything here
1090 gui_mch_update();
1091}//}}}
1092
1093/*
1094 * Check whatever we allready own the selection.
1095 */
1096 int
1097clip_mch_own_selection(VimClipboard *cbd)//{{{
1098{
1099 if (kapp->clipboard()->ownsSelection())
1100 return OK;
1101 else {
1102#if QT_VERSION>=300
1103 kapp->clipboard()->setSelectionMode(true);
1104#endif
1105 return OK;
1106 }
1107}//}}}
1108
1109/*
1110 * Send the current selection to the clipboard.
1111 */
1112void
1113clip_mch_set_selection(VimClipboard *cbd){//{{{
1114 char_u *data;
1115 long_u length;
1116
1117 clip_get_selection(cbd);
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +00001118 if (clip_convert_selection(&data,&length,cbd)<0) return;
Bram Moolenaar843ee412004-06-30 16:16:41 +00001119
1120 QString selection((const char *) data);
1121 //We must turncate the string because it is not
1122 // null terminated
1123 selection.truncate((uint) length);
1124
1125#if QT_VERSION>=300
1126 if (cbd==&clip_star) kapp->clipboard()->setSelectionMode(true);
1127#endif
1128 kapp->clipboard()->setText(selection);
1129#if QT_VERSION>=300
1130 kapp->clipboard()->setSelectionMode(false);
1131#endif
1132}//}}}
1133
1134
1135#if defined(FEAT_MENU) || defined(PROTO)
1136/*
1137 * Make a menu item appear either active or not active (grey or not grey).
1138 */
1139 void
1140gui_mch_menu_grey(vimmenu_T * menu, int grey)//{{{
1141{
1142 if ( !menu || !menu->parent || !menu->parent->widget ) return;
1143 menu->parent->widget->setItemEnabled((int)menu, !grey);
1144 gui_mch_update();
1145}//}}}
1146
1147/*
1148 * Make menu item hidden or not hidden.
1149 */
1150 void
1151gui_mch_menu_hidden(vimmenu_T * menu, int hidden)//{{{
1152{
1153 //FIXME: cannot be fixed AFAIK
1154 gui_mch_menu_grey(menu,hidden); // it's hard to remove an item in a QPopupMenu
1155}//}}}
1156
1157/*
1158 * This is called after setting all the menus to grey/hidden or not.
1159 */
1160 void
1161gui_mch_draw_menubar()//{{{
1162{
1163 // nothing to do under kde
1164}//}}}
1165#endif
1166
1167/*
1168 * Scrollbar stuff.
1169 */
1170 void
1171gui_mch_enable_scrollbar(scrollbar_T * sb, int flag)//{{{
1172{
1173 if (!sb->w) return;
1174 int width = gui.w->width();
1175 int height = gui.w->height();
1176 int neww = vmw->width();
1177 int newh = vmw->height();
1178
1179 if (gui.which_scrollbars[SBAR_LEFT]) width += gui.scrollbar_width;
1180 if (gui.which_scrollbars[SBAR_RIGHT]) width += gui.scrollbar_width;
1181 if (gui.which_scrollbars[SBAR_BOTTOM]) height += gui.scrollbar_height;
Bram Moolenaar15d0a8c2004-09-06 17:44:46 +00001182
Bram Moolenaar843ee412004-06-30 16:16:41 +00001183 if (vmw->menuBar()->isVisible() && vmw->menuBar()->isEnabled()
1184#if QT_VERSION>=300
1185 && !vmw->menuBar()->isTopLevelMenu()
1186#endif
1187 )
1188 height += vmw->menuBar()->height();
1189#ifdef FEAT_TOOLBAR
1190 if (vmw->toolBar()->isVisible() && vmw->toolBar()->isEnabled() &&
1191 (vmw->toolBar()->barPos()==KToolBar::Top ||
1192 vmw->toolBar()->barPos()==KToolBar::Bottom))
1193 height += vmw->toolBar()->height();
1194
1195 if (vmw->toolBar()->isVisible() && vmw->toolBar()->isEnabled() &&
1196 (vmw->toolBar()->barPos()==KToolBar::Left ||
1197 vmw->toolBar()->barPos()==KToolBar::Right))
1198 width += vmw->toolBar()->width();
1199#endif
1200 if ( abs(vmw->width() - width)>5 && (sb->type==SBAR_LEFT || sb->type==SBAR_RIGHT) )
1201 neww=width;
1202 if (abs(vmw->height() - height)>5 && (sb->type==SBAR_BOTTOM) )
1203 newh=height;
1204
1205 if (flag)
1206 sb->w->show();
1207 else
1208 sb->w->hide();
1209 gui_mch_update();
1210 vmw->lock();
1211 vmw->resize(neww,newh);
1212 vmw->unlock();
1213 gui_mch_update();
1214}//}}}
1215
1216/*
1217 * Return the RGB value of a pixel as "#RRGGBB".
1218 */
1219 long_u
1220gui_mch_get_rgb(guicolor_T pixel)//{{{
1221{
1222// QColor c(pixel,pixel);
1223// return (c.red() << 16) + ((c.green() << 8)) + (c.blue());
1224 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)
1225}//}}}
1226
1227/*
1228 * Get current y mouse coordinate in text window.
1229 * Return -1 when unknown.
1230 */
1231 int
1232gui_mch_get_mouse_x(void)//{{{
1233{
1234 return vmw->mapFromGlobal( QCursor::pos() ).x();
1235}//}}}
1236
1237 int
1238gui_mch_get_mouse_y(void)//{{{
1239{
1240 return vmw->mapFromGlobal( QCursor::pos() ).y();
1241}//}}}
1242
1243 void
1244gui_mch_setmouse(int x, int y)//{{{
1245{
1246 QCursor::setPos( vmw->mapToGlobal( QPoint(x,y)) );
1247}//}}}
1248
1249#if defined(FEAT_MOUSESHAPE) || defined(PROTO)
1250#if QT_VERSION>=300
1251static int mshape_ids[] = {//{{{
1252 Qt::ArrowCursor, /* arrow */
1253 Qt::BlankCursor, /* blank */
1254 Qt::IbeamCursor, /* beam */
1255 Qt::SizeVerCursor, /* updown */
1256 Qt::SplitHCursor, /* udsizing */
1257 Qt::SizeHorCursor, /* leftright */
1258 Qt::SizeHorCursor, /* lrsizing */
1259 Qt::WaitCursor, /* busy */
1260 Qt::ForbiddenCursor, /* no */
1261 Qt::CrossCursor, /* crosshair */
1262 Qt::PointingHandCursor, /* hand1 */
1263 Qt::PointingHandCursor, /* hand2 */
1264 Qt::ArrowCursor, /* pencil */
1265 Qt::WhatsThisCursor, /* question */
1266 Qt::ArrowCursor, /* right-arrow */
1267 Qt::UpArrowCursor, /* up-arrow */
1268 Qt::ArrowCursor /* last one */
1269};//}}}
1270#else
1271static int mshape_ids[] = {//{{{
1272 ArrowCursor, /* arrow */
1273 BlankCursor, /* blank */
1274 IbeamCursor, /* beam */
1275 SizeVerCursor, /* updown */
1276 SplitHCursor, /* udsizing */
1277 SizeHorCursor, /* leftright */
1278 SizeHorCursor, /* lrsizing */
1279 WaitCursor, /* busy */
1280 ForbiddenCursor, /* no */
1281 CrossCursor, /* crosshair */
1282 PointingHandCursor, /* hand1 */
1283 PointingHandCursor, /* hand2 */
1284 ArrowCursor, /* pencil */
1285 ArrowCursor, /* question */
1286 ArrowCursor, /* right-arrow */
1287 UpArrowCursor, /* up-arrow */
1288 ArrowCursor /* last one */
1289};//}}}
1290#endif
1291
1292 void
1293mch_set_mouse_shape (int shape)//{{{
1294{
1295 int id;
1296
1297 if (shape == MSHAPE_HIDE || gui.pointer_hidden)
1298#if QT_VERSION>=300
1299 gui.w->setCursor(Qt::BlankCursor);
1300#else
1301 gui.w->setCursor(BlankCursor);
1302#endif
1303 else
1304 {
1305 if (shape >= MSHAPE_NUMBERED)
1306 {
1307 id = shape - MSHAPE_NUMBERED;
1308 /* if (id >= GDK_NUM_GLYPHS)
1309 id = GDK_LEFT_PTR;
1310 else
1311 id &= ~1;*/ /* they are always even (why?) */
1312 id &= -1;
1313 }
1314 else
1315 id = mshape_ids[shape];
1316
1317 gui.w->setCursor(id);
1318 }
1319 if (shape != MSHAPE_HIDE)
1320 last_shape = shape;
1321}//}}}
1322#endif
1323
1324 int
1325gui_mch_adjust_charsize ()//{{{
1326{
1327 QFont f(*(gui.current_font));
1328 QFontMetrics fm (f);
1329 gui.char_height = fm.height() + p_linespace;
1330 //gui.char_height = fm.ascent() + fm.descent() + p_linespace;
1331 gui.char_ascent = fm.ascent() + p_linespace/2;
1332
1333 return OK;
1334}//}}}
1335
1336 void
1337gui_mch_set_foreground ()//{{{
1338{
1339 KWin::setActiveWindow(vmw->winId());
1340}//}}}
1341
1342
1343