/* vi:set ts=8 sts=4 sw=4: * * VIM - Vi IMproved by Bram Moolenaar * * Do ":help uganda" in Vim to read copying and usage conditions. * Do ":help credits" in Vim to see a list of people who contributed. */ /* * Porting to KDE(2) was done by * * (C) 2000 by Thomas Capricelli * * Please visit http://freehackers.org/kvim for other vim- or * kde-related coding. * * $Id$ * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if (QT_VERSION>=300) #include #include #endif #include #include #include #include #include #include "gui_kde_wid.h" extern "C" { #include "vim.h" #include "version.h" } #include /* * global variable for KDE, we can't put them in Gui, cause there are C++ types */ VimMainWindow *vmw = 0; SBPool *sbpool = 0; QString *argServerName = 0; #ifdef FEAT_MOUSESHAPE /* The last set mouse pointer shape is remembered, to be used when it goes * from hidden to not hidden. */ static int last_shape = 0; #endif /* * Arguments handled by KDE internally. */ #if QT_VERSION>=300 static int tip = 0; // 1 no dialog, 0 use it if enabled in conf, // 2 force the tip #endif static int reverse = 0; // 0 bg : white, 1 : bg : black QString *startfont; QSize *startsize; static int gui_argc = 0; static char **gui_argv = NULL; /* * Parse the GUI related command-line arguments. Any arguments used are * deleted from argv, and *argc is decremented accordingly. This is called * when vim is started, whether or not the GUI has been started. */ void gui_mch_prepare(int *argc, char **argv)// {{{ { // copy args for KDE/Qt gui_argc = 0; // this one is not really good as all options are not for KDE/Qt ... gui_argv = (char **)lalloc((long_u)(*argc * sizeof(char *)), FALSE); if (gui_argv == NULL) return; gui_argv[gui_argc++] = argv[0]; int found = 0; for (int i = 1; i < *argc ; i++) { if (found != 2) found = 0; else { found = 0; // remove from the list of argv if (--*argc > i) { mch_memmove(&argv[i], &argv[i + 1], (*argc - i) * sizeof(char *)); } i--; continue; } if (strcmp(argv[i], "--servername") == 0) { argServerName = new QString(argv[i+1]); // to get the serverName now } #if QT_VERSION>+300 if (strcmp(argv[i], "-tip") == 0 ) { tip = 2; found = 1; } if (strcmp(argv[i], "-notip") == 0 ) { tip = 1; found = 1; } #endif if (strcmp(argv[i], "-black") == 0 ) { reverse = 1; found = 1; } /* replaced by -black */ /* if (strcmp(argv[i], "-rv") == 0 ) * { reverse = 1; found = 1; }*/ if (strcmp(argv[i], "-font") == 0 || strcmp(argv[i], "-fn") == 0) { startfont = new QString(argv[i+1]); found = 2; } if (strcmp(argv[i], "-geometry") == 0 || strcmp(argv[i], "-geom") == 0) { found = 2; QString text(argv[i + 1]); QStringList list = QStringList::split(QChar('x'), text); startsize = new QSize(list[0].toInt(), list[1].toInt()); } if (strcmp(argv[i], "-display") == 0) //XXX: this does not work, // too many -display options in main.c ! // ask Bram ... { gui_argv[gui_argc++] = strdup("--display"); gui_argv[gui_argc++] = argv[i+1]; found = 0; } if (strcmp(argv[i], "--display") == 0 ) { gui_argv[gui_argc++] = argv[i]; gui_argv[gui_argc++] = argv[i+1]; found = 2; } //KDE/Qt options with no args if (strcmp(argv[i], "--help-kde") == 0 || strcmp(argv[i], "--help-qt") == 0 || strcmp(argv[i], "--help-all") == 0 || strcmp(argv[i], "--reverse") == 0 || strcmp(argv[i], "--author") == 0 // || strcmp(argv[i], "--version") == 0 //disabled we need these for kcmvim // || strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--license") == 0 || strcmp(argv[i], "--cmap") == 0 || strcmp(argv[i], "--nograb") == 0 || strcmp(argv[i], "--dograb") == 0 || strcmp(argv[i], "--sync") == 0 || strcmp(argv[i], "--noxim") == 0 || strcmp(argv[i], "--nocrashhandler") == 0 || strcmp(argv[i], "--waitforwm") == 0 ) { gui_argv[gui_argc++] = argv[i]; found = 1; } //this outputs KDE and Vim versions :) if (strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-v") == 0) { gui_argv[gui_argc++] = argv[i]; } // KDE/Qt options with one arg if (strcmp(argv[i], "--session") == 0 || strcmp(argv[i], "--ncols") == 0 || strcmp(argv[i], "--bg") == 0 || strcmp(argv[i], "--background") == 0 || strcmp(argv[i], "--fg") == 0 || strcmp(argv[i], "--foreground") == 0 || strcmp(argv[i], "--btn") == 0 || strcmp(argv[i], "--name") == 0 || strcmp(argv[i], "--title") == 0 || strcmp(argv[i], "--inputstyle") == 0 || strcmp(argv[i], "--im") == 0 || strcmp(argv[i], "--caption") == 0 || strcmp(argv[i], "--icon") == 0 || strcmp(argv[i], "--miniicon") == 0 || strcmp(argv[i], "--config") == 0 || strcmp(argv[i], "--dcopserver") == 0 || strcmp(argv[i], "--style") == 0 || strcmp(argv[i], "--geometry") == 0 || strcmp(argv[i], "--smkey") == 0 || strcmp(argv[i], "-smkey") == 0 || strcmp(argv[i], "-session") == 0 ) { gui_argv[gui_argc++] = argv[i]; gui_argv[gui_argc++] = argv[i + 1]; found = 2; } // remove from the list of argv if (found >= 1 && --*argc > i) { mch_memmove(&argv[i], &argv[i + 1], (*argc - i) * sizeof(char *)); i--; } } KCmdLineArgs::init(gui_argc, gui_argv, argv[0], I18N_NOOP("KVim"), I18N_NOOP("Vim inside KDE"), VIM_VERSION_SHORT); }// }}} /**************************************************************************** * Focus handlers: */ /* * Initialises time intervals for the cursor blinking */ void gui_mch_set_blinking(long waittime, long on, long off)//{{{ { gui.w->set_blink_time(waittime, on, off); }//}}} /* * Stop the cursor blinking. Show the cursor if it wasn't shown. */ void gui_mch_stop_blink()//{{{ { gui.w->stop_cursor_blinking(); }//}}} /* * Start the cursor blinking. If it was already blinking, this restarts the * waiting time and shows the cursor. */ void gui_mch_start_blink()//{{{ { gui.w->start_cursor_blinking(); }//}}} #ifdef FEAT_MZSCHEME void mzscheme_kde_start_timer()//{{{ { gui.w->enable_mzscheme_threads(); }//}}} void mzscheme_kde_stop_timer()//{{{ { gui.w->disable_mzscheme_threads(); }//}}} #endif /* * Check if the GUI can be started. Called before gvimrc is sourced. * Return OK or FAIL. */ int gui_mch_init_check(void)//{{{ { gui.dpy = qt_xdisplay(); return OK; }//}}} /* * Initialise the X GUI. Create all the windows, set up all the call-backs etc. * Returns OK for success, FAIL when the GUI can't be started. */ int gui_mch_init()//{{{ { (void) new KApplication(); KApplication::kApplication()->dcopClient()->registerAs( KApplication::kApplication()->name(), false); // dbf("%s %s", KGlobal::locale()->language().latin1(), KLocale::defaultLanguage().latin1()); vmw = new VimMainWindow("KVim", 0); vmw->setFrameBorderWidth(0); kapp->setMainWidget(vmw); kapp->setTopWidget(vmw); sbpool = new SBPool; #if QT_VERSION>=300 vmw->connect(kapp->clipboard(), SIGNAL(selectionChanged()), vmw, SLOT(clipboard_selection_update())); #endif vmw->connect(kapp->clipboard(), SIGNAL(dataChanged()), vmw, SLOT(clipboard_data_update())); clip_lose_selection(&clip_plus); clip_lose_selection(&clip_star); gui.in_focus = FALSE; // will be updated if (reverse) { gui.def_norm_pixel = gui_get_color((char_u *)"White"); gui.def_back_pixel = gui_get_color((char_u *)"Black"); #if QT_VERSION>=300 gui.w->setEraseColor(QColor(Qt::black)); #else gui.w->setBackgroundColor(QColor(Qt::black)); #endif } else { gui.def_norm_pixel = gui_get_color((char_u *)"Black"); gui.def_back_pixel = gui_get_color((char_u *)"White"); #if QT_VERSION>=300 gui.w->setEraseColor(QColor(Qt::white)); #else gui.w->setBackgroundColor(QColor(Qt::white)); #endif } gui.norm_pixel = gui.def_norm_pixel; gui.back_pixel = gui.def_back_pixel; gui.border_width = 1; gui.border_offset = 1;//gui.border_width; gui.scrollbar_width = SB_DEFAULT_WIDTH; gui.scrollbar_height = SB_DEFAULT_WIDTH; //gui.menu_height = vmw->menuBar()->height()+1; //gui.toolbar_height = vmw->toolBar()->height(); return OK; }//}}} /* * Called when the foreground or background color has been changed. */ void gui_mch_new_colors()//{{{ { QColor rgb; rgb.setRgb(gui.back_pixel); #if QT_VERSION>=300 gui.w->setEraseColor(rgb); #else gui.w->setBackgroundColor(rgb); #endif }//}}} /* * Open the GUI window which was created by a call to gui_mch_init(). */ int gui_mch_open()//{{{ { gui.dpy = qt_xdisplay(); set_normal_colors(); /* Check that none of the colors are the same as the background color */ gui_check_colors(); /* Get the colors for the highlight groups (gui_check_colors() might have * changed them). */ highlight_gui_started(); /* re-init colors and fonts */ #ifdef FEAT_MENU vmw->w->menu = new QPopupMenu(vmw); #if QT_VERSION>=300 vmw->w->menu->insertItem(SmallIcon("ktip"), i18n("&Tip of the day..."), vmw, SLOT(showTipOfTheDay())); vmw->w->menu->insertSeparator(); #endif if (vmw->have_tearoff) vmw->w->menu->insertTearOffHandle(0, 0); vmw->w->menu->insertItem(i18n("&Report Bug ..."), vmw, SLOT(showBugReport())); vmw->w->menu->insertSeparator(); vmw->w->menu->insertItem(SmallIcon("kvim"), i18n("&About KVim..."), vmw, SLOT(showAboutApplication())); vmw->w->menu->insertItem(SmallIcon("about_kde"), i18n("About &KDE..."), vmw, SLOT(showAboutKDE())); vmw->menuBar()->insertItem("&KVim", vmw->w->menu); #endif if (startfont != NULL) gui_mch_init_font((char_u*)startfont->latin1(), FALSE); if (startsize != NULL) vmw->resize(startsize->width(), startsize->height()); gui_mch_update_codec(); if (kapp->isRestored()) if (KMainWindow::canBeRestored(1)) vmw->restore(1); vmw->show(); #if QT_VERSION>=300 if (tip == 2) KTipDialog::showTip(vmw, QString::null, true); else if (tip == 0) KTipDialog::showTip(vmw); #endif return OK; }//}}} void gui_mch_exit(int rc)//{{{ { kapp->quit(); }//}}} /* * Get the position of the top left corner of the window. */ int gui_mch_get_winpos(int *x, int *y)//{{{ { *x = vmw->x(); *y = vmw->y(); return OK; }//}}} /* * Set the position of the top left corner of the window to the given * coordinates. */ void gui_mch_set_winpos(int x, int y)//{{{ { vmw->move(x, y); }//}}} /* * Set the windows size. * ->resize VimWidget * ->resize vmw (block any events generated from here) */ void gui_mch_set_shellsize(int width, int height,//{{{ int min_width, int min_height, int base_width, int base_height) { //resize VimWidget vmw->w->resize(width, height); //resize vmw int vheight, vwidth; vheight = height; vwidth = width; if (gui.which_scrollbars[SBAR_LEFT]) vwidth += gui.scrollbar_width; if (gui.which_scrollbars[SBAR_RIGHT]) vwidth += gui.scrollbar_width; if (gui.which_scrollbars[SBAR_BOTTOM]) vheight += gui.scrollbar_height; if (vmw->menuBar()->isVisible() && vmw->menuBar()->isEnabled() #if QT_VERSION>=300 && !vmw->menuBar()->isTopLevelMenu() #endif ) vheight += vmw->menuBar()->height(); #ifdef FEAT_TOOLBAR if (vmw->toolBar()->isVisible() && vmw->toolBar()->isEnabled() && (vmw->toolBar()->barPos() == KToolBar::Top || vmw->toolBar()->barPos() == KToolBar::Bottom)) vheight += vmw->toolBar()->height(); if (vmw->toolBar()->isVisible() && vmw->toolBar()->isEnabled() && (vmw->toolBar()->barPos() == KToolBar::Left || vmw->toolBar()->barPos() == KToolBar::Right)) vwidth += vmw->toolBar()->width(); #endif vmw->lock(); vmw->resize(vwidth, vheight); gui_mch_update(); //size should be nearly perfect, update baseSize and sizeIncrement vmw->setBaseSize(base_width, vmw->menuBar()->height() + 1 + vmw->toolBar()->height() + gui.char_height * 2); vmw->setSizeIncrement((( int )(gui.char_width / 2) * 2), gui.char_height); vmw->unlock(); }//}}} /* * The screen size is used to make sure the initial window doesn't get bigger * then the screen. This subtracts some room for menubar, toolbar and window * decorations. */ void gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)//{{{ { *screen_w = kapp->desktop()->width(); *screen_h = kapp->desktop()->height(); }//}}} #if defined(FEAT_MENU) || defined(PROTO) void gui_mch_enable_menu(int showit)//{{{ { if (showit) vmw->menuBar()->show(); else vmw->menuBar()->hide(); vmw->resize(vmw->width(), vmw->height()); }//}}} #endif #if defined(FEAT_TOOLBAR) || defined(PROTO) void gui_mch_show_toolbar(int showit)//{{{ { if (showit) vmw->toolBar()->show(); else vmw->toolBar()->hide(); vmw->resize(vmw->width(), vmw->height()); }//}}} #endif /* * Put up a font dialog and return the selected font name in allocated memory. * "oldval" is the previous value. * Return NULL when cancelled. */ char_u * gui_mch_font_dialog(char_u *oldval)//{{{ { QFont myFont(vmw->w->font()); if (gui.fontname) gui.fontname = NULL; int result = KFontDialog::getFont(myFont, true); if (result != KFontDialog::Accepted) return NULL; // myFont.setFixedPitch(true); #if QT_VERSION>=300 QString n = myFont.toString(); #else QString n = KVimUtils::toString(&myFont); #endif n.replace(QRegExp(","), "/"); gui.fontname = (char_u *)strdup((const char *)n); n.replace(QRegExp(" "), "\\ "); 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"); //display a message box which explains how to save your font settings KMessageBox::information(vmw, n, "Font Selection", "kvimselectfont"); return vim_strsave(gui.fontname); }//}}} /* * Initialise vim to use the font with the given name. * Return FAIL if the font could not be loaded, OK otherwise. */ int gui_mch_init_font(char_u * font_name, int fontset)//{{{ { QString fontname; GuiFont font = NULL; if (font_name == NULL) { #if 0 #if QT_VERSION>=300 KConfig *base = KGlobal::config(); #else KConfigBase *base = KGlobal::config(); #endif base->setGroup("General"); if (!base->hasKey("fixed")) { 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')"); return FAIL; } #if QT_VERSION>=300 QString f = base->readEntry("fixed"); #else QFont ft = base->readFontEntry("fixed", NULL); QString f = KVimUtils::toString(&ft); #endif font_name = (char_u*)strdup(f.latin1()); //latin1 ? #else font_name = (char_u*)strdup("misc-fixed/10/-1/5/50/0/0/0/1/0"); #endif } fontname = (const char *)font_name; /* fontname.replace(QRegExp("/"), ","); font = new QFont(); font->fromString( fontname ); */ #ifdef FEAT_XFONTSET if (fontset) font = gui_mch_get_fontset(font_name, TRUE, TRUE); if (font == NULL) #endif font = gui_mch_get_font(font_name, FALSE); if (font == NULL) return FAIL; if (fontname.contains('*') && fontname.contains('-')) return FAIL; gui_mch_free_font(gui.norm_font); #ifdef FEAT_XFONTSET gui_mch_free_fontset(gui.fontset); gui.fontset = NOFONTSET; if (fontset) { gui.fontset = font; gui.norm_font = NOFONT; } else #endif gui.norm_font = font; /* Compute the width of the character cell. Some fonts include * double-width characters. Use the width of ASCII characters to find * out if this is so. */ QFontMetrics f(*font); int width_max = 0; for (char c = 32; c < 127; c++) if (width_max < f.width((QChar)c)) width_max = f.width((QChar)c); if (width_max <= f.maxWidth() / 2) width_max = f.maxWidth() / 2; gui.char_width = width_max; gui.char_height = f.height() + p_linespace; gui.char_ascent = f.ascent() + p_linespace; //check values, just to make sure and avoid a crash if (gui.char_width <= 0) gui.char_width = 8; if (gui.char_height <= 0) gui.char_height = 1; hl_set_font_name(font_name); vmw->w->setFont(*font); return OK; }//}}} GuiFont gui_mch_get_font(char_u * name, int report_error)//{{{ { QString fontname((const char *)name); if (!gui.in_use || name == NULL) return NOFONT; if (fontname.contains('*') && fontname.contains('-')) return NOFONT; // XFLD names not allowed anymore QFont *myFont = new QFont(); fontname.replace(QRegExp("/"), ","); // myFont->setRawMode(TRUE); #if QT_VERSION>=300 myFont->fromString(fontname); #else KVimUtils::fromString(myFont, fontname); #endif myFont->setFixedPitch(true); if (!myFont->fixedPitch()) dbf("Non fixed-width font"); return (GuiFont) myFont; }//}}} #if defined(FEAT_EVAL) || defined(PROTO) /* * Return the name of font "font" in allocated memory. * Don't know how to get the actual name, thus use the provided name. */ char_u * gui_mch_get_fontname(GuiFont font, char_u *name)//{{{ { if (name == NULL) return NULL; return vim_strsave(name); }//}}} #endif /* * Set the current text font. * Since we create all GC on demand, we use just gui.current_font to * indicate the desired current font. */ void gui_mch_set_font(GuiFont font)//{{{ { gui.current_font = font; gui.w->painter->setFont(*(gui.current_font)); }//}}} /* * If a font is not going to be used, free its structure. */ void gui_mch_free_font(GuiFont font)//{{{ { if (font) delete font; // this is a QFont , we can delete it :) }//}}} GuiFontset gui_mch_get_fontset(char_u *name, int report_error, int fixed_width) { return (GuiFontset)gui_mch_get_font(name, report_error); } void gui_mch_set_fontset(GuiFontset fontset) { gui_mch_set_font((GuiFont)fontset); } void gui_mch_free_fontset(GuiFontset fontset) { if (fontset) delete fontset; } void gui_mch_settitle(char_u *title, char_u *icon)//{{{ { if (!gui.in_use) /* can't do this when GUI not running */ return; vmw->setPlainCaption((const char *)title); QPixmap p((const char *)icon); vmw->setIcon(p); //FIXME }//}}} /* * Return the Pixel value (color) for the given color name. This routine was * pretty much taken from example code in the Silicon Graphics OSF/Motif * Programmer's Guide. * Return -1 for error. */ guicolor_T gui_mch_get_color(char_u * name)//{{{ { int i; static char *(vimnames[][2]) = { /* A number of colors that some X11 systems don't have */ {"LightRed", "#FFA0A0"}, {"LightGreen", "#80FF80"}, {"LightMagenta", "#FFA0FF"}, {"DarkCyan", "#008080"}, {"DarkBlue", "#0000C0"}, {"DarkRed", "#C00000"}, {"DarkMagenta", "#C000C0"}, {"DarkGrey", "#C0C0C0"}, {NULL, NULL} }; if (!gui.in_use) /* can't do this when GUI not running */ return (guicolor_T)(-1); QColor _color((const char *)name); if (_color.isValid()) { // return (_color.red() << 16) + ((_color.green() << 8)) // + (_color.blue()); return _color.rgb(); // return (guicolor_T) _color.pixel(); } /* add a few builtin names */ for (i = 0;; ++i) { if (vimnames[i][0] == NULL) return (guicolor_T)(-1); if (STRICMP(name, vimnames[i][0]) == 0) { name = (char_u *) vimnames[i][1]; return gui_mch_get_color(name); } } return (guicolor_T)(-1); // dead code, should not be reached.. }//}}} /* * Set the current text foreground color. */ void gui_mch_set_fg_color(guicolor_T color)//{{{ { QColor rgb; rgb.setRgb(color); gui.w->painter->setPen(rgb); }//}}} /* * Set the current text background color. */ void gui_mch_set_bg_color(guicolor_T color)//{{{ { QColor rgb; rgb.setRgb(color); gui.w->painter->setBackgroundColor(rgb); }//}}} /* * Set the current text special color. */ void gui_mch_set_sp_color(guicolor_T color)//{{{ { /* TODO */ }//}}} /* * Use the blank mouse pointer or not. * * hide: TRUE = use blank ptr, FALSE = use parent ptr */ void gui_mch_mousehide(int hide)//{{{ { if (hide == gui.pointer_hidden) return; //#ifdef FEAT_MOUSESHAPE // if (!hide) mch_set_mouse_shape(last_shape); //#else # if (QT_VERSION<300) gui.w->setCursor((hide)?BlankCursor:ArrowCursor); # else gui.w->setCursor((hide)?Qt::BlankCursor:Qt::ArrowCursor); # endif //#endif gui.pointer_hidden = hide; }//}}} void gui_mch_update_codec() { #ifdef FEAT_MBYTE if (!gui.in_use) return; vmw->codec = QTextCodec::codecForName((const char *)p_enc); if (vmw->codec == NULL) vmw->codec = QTextCodec::codecForName( KVimUtils::convertEncodingName(QString((const char*)p_enc))); if (vmw->codec == NULL) vmw->codec = QTextCodec::codecForLocale(); #else vmw->codec = QTextCodec::codecForLocale(); #endif if (vmw->codec == NULL) vmw->codec = QTextCodec::codecForName("ISO-8859-1"); //fallback } void gui_mch_draw_string(int row, int col, char_u * s, int len, int flags)//{{{ { QString text = vmw->codec->toUnicode((const char *)s, len); gui.w->draw_string(TEXT_X(col), TEXT_Y(row), text, text.length(), flags); }//}}} #if defined(FEAT_TITLE) || defined(PROTO) /* * Return the text window-id and display. Only required for X-based GUI's */ int gui_get_x11_windis(Window * win, Display ** dis)//{{{ { *win = /*vmw*/gui.w->winId(); *dis = qt_xdisplay(); return OK; }//}}} #endif void gui_mch_beep()//{{{ { kapp->beep(); }//}}} void gui_mch_flash(int msec)//{{{ { gui.w->flash(); }//}}} /* * Invert a rectangle from row r, column c, for nr rows and nc columns. */ void gui_mch_invert_rectangle(int r, int c, int nr, int nc)//{{{ { bitBlt(gui.w, FILL_X(c), FILL_Y(r), gui.w, FILL_X(c), FILL_Y(r), (nc) * gui.char_width, (nr) * gui.char_height, Qt::NotROP, // raster Operation true); // ignoreMask }//}}} /* * Iconify the GUI window. */ void gui_mch_iconify()//{{{ { vmw->showMinimized(); }//}}} /* * Draw a cursor without focus. */ void gui_mch_draw_hollow_cursor(guicolor_T color)//{{{ { QPainter p(gui.w); p.setPen(color); p.drawRect(FILL_X(gui.col), FILL_Y(gui.row), gui.char_width - 1, gui.char_height - 1); p.end(); }//}}} /* * Draw part of a cursor, "w" pixels wide, and "h" pixels high, using * color "color". */ void gui_mch_draw_part_cursor(int w, int h, guicolor_T color)//{{{ { QPainter p(gui.w); p.setPen(color); p.fillRect( #ifdef FEAT_RIGHTLEFT /* vertical line should be on the right of current point */ CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w : #endif FILL_X(gui.col), FILL_Y(gui.row) + gui.char_height - h + 1, w, h - 2, QColor( color, color)); p.drawRect( #ifdef FEAT_RIGHTLEFT /* vertical line should be on the right of current point */ CURSOR_BAR_RIGHT ? FILL_X(gui.col + 1) - w : #endif FILL_X(gui.col), FILL_Y(gui.row) + gui.char_height - h + (int)p_linespace / 2, w, h - (int)p_linespace); }//}}} /* * Catch up with any queued X11 events. This may put keyboard input into the * input buffer, call resize call-backs, trigger timers etc. If there is * nothing in the X11 event queue (& no timers pending), then we return * immediately. */ void gui_mch_update()//{{{ { kapp->processEvents(); }//}}} /* * GUI input routine called by gui_wait_for_chars(). Waits for a character * from the keyboard. * wtime == -1 Wait forever. * wtime == 0 This should never happen. * wtime > 0 Wait wtime milliseconds for a character. * Returns OK if a character was found to be available within the given time, * or FAIL otherwise. */ int gui_mch_wait_for_chars(long wtime)//{{{ { // malte@kde.org's gift to KVim ;), thanks to him :) for this hard to find bug if (wtime > 0) { gui.w->wait(wtime); while (vim_is_input_buf_empty() && !gui.w->wait_done) kapp->processOneEvent(); return vim_is_input_buf_empty() ? FAIL : OK; } else while (vim_is_input_buf_empty()) kapp->processOneEvent(); return OK; }//}}} /**************************************************************************** * Output drawing routines. ****************************************************************************/ /* Flush any output to the screen */ void gui_mch_flush()//{{{ { kapp->flushX(); }//}}} /* * Clear a rectangular region of the screen from text pos (row1, col1) to * (row2, col2) inclusive. */ void gui_mch_clear_block(int row1, int col1, int row2, int col2)//{{{ { gui.w->erase(FILL_X(col1), FILL_Y(row1), (col2 - col1 + 1) * gui.char_width + (col2 == Columns - 1), (row2 - row1 + 1) * gui.char_height); }//}}} void gui_mch_clear_all(void)//{{{ { gui.w->erase(); }//}}} /* * Delete the given number of lines from the given row, scrolling up any * text further down within the scroll region. */ void gui_mch_delete_lines(int row, int num_lines)//{{{ { if (num_lines <= 0) return; if (row + num_lines > gui.scroll_region_bot) { /* Scrolled out of region, just blank the lines out */ gui_clear_block(row, gui.scroll_region_left, gui.scroll_region_bot, gui.scroll_region_right); } else { bitBlt(gui.w, FILL_X(gui.scroll_region_left), FILL_Y(row), gui.w, FILL_X(gui.scroll_region_left), FILL_Y(row + num_lines), gui.char_width * (gui.scroll_region_right - gui.scroll_region_left + 1) + 1, gui.char_height * (gui.scroll_region_bot - row - num_lines + 1), Qt::CopyROP, // raster Operation true); // ignoreMask /* Update gui.cursor_row if the cursor scrolled or copied over */ if (gui.cursor_row >= row) { if (gui.cursor_row < row + num_lines) gui.cursor_is_valid = FALSE; else if (gui.cursor_row <= gui.scroll_region_bot) gui.cursor_row -= num_lines; } gui_clear_block(gui.scroll_region_bot - num_lines + 1, gui.scroll_region_left, gui.scroll_region_bot, gui.scroll_region_right); } }//}}} /* * Insert the given number of lines before the given row, scrolling down any * following text within the scroll region. */ void gui_mch_insert_lines(int row, int num_lines)//{{{ { if (num_lines <= 0) return; if (row + num_lines > gui.scroll_region_bot) { /* Scrolled out of region, just blank the lines out */ gui_clear_block(row, gui.scroll_region_left, gui.scroll_region_bot, gui.scroll_region_right - 1); } else { bitBlt(gui.w, FILL_X(gui.scroll_region_left), FILL_Y(row + num_lines), gui.w, FILL_X(gui.scroll_region_left), FILL_Y(row), gui.char_width * ( gui.scroll_region_right - gui.scroll_region_left + 1 ) + 1, gui.char_height * (gui.scroll_region_bot - row - num_lines + 1), Qt::CopyROP, // raster Operation true); // ignoreMask /* Update gui.cursor_row if the cursor scrolled or copied over */ if (gui.cursor_row >= gui.row) { if (gui.cursor_row <= gui.scroll_region_bot - num_lines) gui.cursor_row += num_lines; else if (gui.cursor_row <= gui.scroll_region_bot) gui.cursor_is_valid = FALSE; } gui_clear_block(row, gui.scroll_region_left, row + num_lines - 1, gui.scroll_region_right); } }//}}} /* * X Selection stuff, for cutting and pasting text to other windows. */ void clip_mch_request_selection(VimClipboard *cbd)//{{{ { #if QT_VERSION>=300 if (cbd == &clip_star) kapp->clipboard()->setSelectionMode(true); #endif QString selection = kapp->clipboard()->text(); QCString unistring = vmw->codec->fromUnicode(selection); clip_yank_selection(MCHAR, (char_u *)(const char*)unistring, (long)unistring.length(), cbd); #if QT_VERSION>=300 if (cbd == &clip_star) kapp->clipboard()->setSelectionMode(false); #endif }//}}} void clip_mch_lose_selection(VimClipboard *cbd)//{{{ { // Don't need to do anything here gui_mch_update(); }//}}} /* * Check whatever we allready own the selection. */ int clip_mch_own_selection(VimClipboard *cbd)//{{{ { if (kapp->clipboard()->ownsSelection()) return OK; else { #if QT_VERSION>=300 kapp->clipboard()->setSelectionMode(true); #endif return OK; } }//}}} /* * Send the current selection to the clipboard. */ void clip_mch_set_selection(VimClipboard *cbd)//{{{ { char_u *data; long_u length; clip_get_selection(cbd); if (clip_convert_selection(&data, &length, cbd) < 0) return; QString selection((const char *)data); // We must turncate the string because it is not // null terminated selection.truncate((uint) length); #if QT_VERSION>=300 if (cbd == &clip_star) kapp->clipboard()->setSelectionMode(true); #endif kapp->clipboard()->setText(selection); #if QT_VERSION>=300 kapp->clipboard()->setSelectionMode(false); #endif }//}}} #if defined(FEAT_MENU) || defined(PROTO) /* * Make a menu item appear either active or not active (grey or not grey). */ void gui_mch_menu_grey(vimmenu_T * menu, int grey)//{{{ { if (!menu || !menu->parent || !menu->parent->widget) return; menu->parent->widget->setItemEnabled((long)menu, !grey); gui_mch_update(); }//}}} /* * Make menu item hidden or not hidden. */ void gui_mch_menu_hidden(vimmenu_T * menu, int hidden)//{{{ { // FIXME: cannot be fixed AFAIK // it's hard to remove an item in a QPopupMenu gui_mch_menu_grey(menu, hidden); }//}}} /* * This is called after setting all the menus to grey/hidden or not. */ void gui_mch_draw_menubar()//{{{ { // nothing to do under kde }//}}} #endif /* * Scrollbar stuff. */ void gui_mch_enable_scrollbar(scrollbar_T *sb, int flag)//{{{ { if (!sb->w) return; int width = gui.w->width(); int height = gui.w->height(); int neww = vmw->width(); int newh = vmw->height(); if (gui.which_scrollbars[SBAR_LEFT]) width += gui.scrollbar_width; if (gui.which_scrollbars[SBAR_RIGHT]) width += gui.scrollbar_width; if (gui.which_scrollbars[SBAR_BOTTOM]) height += gui.scrollbar_height; if (vmw->menuBar()->isVisible() && vmw->menuBar()->isEnabled() #if QT_VERSION>=300 && !vmw->menuBar()->isTopLevelMenu() #endif ) height += vmw->menuBar()->height(); #ifdef FEAT_TOOLBAR if (vmw->toolBar()->isVisible() && vmw->toolBar()->isEnabled() && (vmw->toolBar()->barPos() == KToolBar::Top || vmw->toolBar()->barPos() == KToolBar::Bottom)) height += vmw->toolBar()->height(); if (vmw->toolBar()->isVisible() && vmw->toolBar()->isEnabled() && (vmw->toolBar()->barPos() == KToolBar::Left || vmw->toolBar()->barPos() == KToolBar::Right)) width += vmw->toolBar()->width(); #endif if (abs(vmw->width() - width) > 5 && (sb->type == SBAR_LEFT || sb->type == SBAR_RIGHT)) neww = width; if (abs(vmw->height() - height) > 5 && (sb->type == SBAR_BOTTOM)) newh = height; if (flag) sb->w->show(); else sb->w->hide(); gui_mch_update(); vmw->lock(); vmw->resize(neww, newh); vmw->unlock(); gui_mch_update(); }//}}} /* * Return the RGB value of a pixel as "#RRGGBB". */ long_u gui_mch_get_rgb(guicolor_T pixel)//{{{ { // QColor c(pixel, pixel); // return (c.red() << 16) + ((c.green() << 8)) + (c.blue()); 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) }//}}} /* * Get current mouse coordinates in text window. */ void gui_mch_getmouse(int *x, int *y)//{{{ { *x = vmw->mapFromGlobal(QCursor::pos()).x(); *y = vmw->mapFromGlobal(QCursor::pos()).y(); }//}}} void gui_mch_setmouse(int x, int y)//{{{ { QCursor::setPos(vmw->mapToGlobal(QPoint(x, y))); }//}}} #if defined(FEAT_MOUSESHAPE) || defined(PROTO) #if QT_VERSION>=300 static int mshape_ids[] = {//{{{ Qt::ArrowCursor, /* arrow */ Qt::BlankCursor, /* blank */ Qt::IbeamCursor, /* beam */ Qt::SizeVerCursor, /* updown */ Qt::SplitHCursor, /* udsizing */ Qt::SizeHorCursor, /* leftright */ Qt::SizeHorCursor, /* lrsizing */ Qt::WaitCursor, /* busy */ Qt::ForbiddenCursor, /* no */ Qt::CrossCursor, /* crosshair */ Qt::PointingHandCursor, /* hand1 */ Qt::PointingHandCursor, /* hand2 */ Qt::ArrowCursor, /* pencil */ Qt::WhatsThisCursor, /* question */ Qt::ArrowCursor, /* right-arrow */ Qt::UpArrowCursor, /* up-arrow */ Qt::ArrowCursor /* last one */ };//}}} #else static int mshape_ids[] = {//{{{ ArrowCursor, /* arrow */ BlankCursor, /* blank */ IbeamCursor, /* beam */ SizeVerCursor, /* updown */ SplitHCursor, /* udsizing */ SizeHorCursor, /* leftright */ SizeHorCursor, /* lrsizing */ WaitCursor, /* busy */ ForbiddenCursor, /* no */ CrossCursor, /* crosshair */ PointingHandCursor, /* hand1 */ PointingHandCursor, /* hand2 */ ArrowCursor, /* pencil */ ArrowCursor, /* question */ ArrowCursor, /* right-arrow */ UpArrowCursor, /* up-arrow */ ArrowCursor /* last one */ };//}}} #endif void mch_set_mouse_shape (int shape)//{{{ { int id; if (shape == MSHAPE_HIDE || gui.pointer_hidden) #if QT_VERSION>=300 gui.w->setCursor(Qt::BlankCursor); #else gui.w->setCursor(BlankCursor); #endif else { if (shape >= MSHAPE_NUMBERED) { id = shape - MSHAPE_NUMBERED; /* if (id >= GDK_NUM_GLYPHS) id = GDK_LEFT_PTR; else id &= ~1;*/ /* they are always even (why?) */ id &= -1; } else id = mshape_ids[shape]; gui.w->setCursor(id); } if (shape != MSHAPE_HIDE) last_shape = shape; }//}}} #endif /* * Adjust gui.char_height (after 'linespace' was changed). */ int gui_mch_adjust_charheight ()//{{{ { QFont f(*(gui.current_font)); QFontMetrics fm(f); gui.char_height = fm.height() + p_linespace; //gui.char_height = fm.ascent() + fm.descent() + p_linespace; gui.char_ascent = fm.ascent() + p_linespace / 2; return OK; }//}}} void gui_mch_set_foreground ()//{{{ { KWin::activateWindow(vmw->winId()); }//}}}