Beispiel #1
0
void vte_init(void)
{
	if (vte_info.have_vte == FALSE)
	{	/* vte_info.have_vte can be false even if VTE is compiled in, think of command line option */
		geany_debug("Disabling terminal support");
		return;
	}

	if (!EMPTY(vte_info.lib_vte))
	{
		module = g_module_open(vte_info.lib_vte, G_MODULE_BIND_LAZY);
	}
#ifdef VTE_MODULE_PATH
	else
	{
		module = g_module_open(VTE_MODULE_PATH, G_MODULE_BIND_LAZY);
	}
#endif

	if (module == NULL)
	{
		gint i;
		const gchar *sonames[] = {
#if GTK_CHECK_VERSION(3, 0, 0)
			"libvte2_90.so", "libvte2_90.so.9",
#else
			"libvte.so", "libvte.so.4", "libvte.so.8", "libvte.so.9",
#endif
			NULL
		};

		for (i = 0; sonames[i] != NULL && module == NULL; i++)
		{
			module = g_module_open(sonames[i], G_MODULE_BIND_LAZY);
		}
	}

	if (module == NULL)
	{
		vte_info.have_vte = FALSE;
		geany_debug("Could not load libvte.so, embedded terminal support disabled");
		return;
	}
	else
	{
		vf = g_new0(struct VteFunctions, 1);
		if (vte_register_symbols(module))
			vte_info.have_vte = TRUE;
		else
		{
			vte_info.have_vte = FALSE;
			g_free(vf);
			/* FIXME: is closing the module safe? see vte_close() and test on FreeBSD */
			/*g_module_close(module);*/
			module = NULL;
			return;
		}
	}

	create_vte();

	/* setup the F10 menu override (so it works before the widget is first realised). */
	override_menu_key();
}
Beispiel #2
0
/* (Unix domain) socket support to replace the old FIFO code
 * (taken from Sylpheed, thanks)
 * Returns the created socket, -1 if an error occurred or -2 if another socket exists and files
 * were sent to it. */
gint socket_init(gint argc, gchar **argv)
{
	gint sock;
#ifdef G_OS_WIN32
	HANDLE hmutex;
	HWND hwnd;
	socket_init_win32();
	hmutex = CreateMutexA(NULL, FALSE, "AGK");
	if (! hmutex)
	{
		geany_debug("cannot create Mutex\n");
		return -1;
	}
	if (GetLastError() != ERROR_ALREADY_EXISTS)
	{
		/* To support multiple instances with different configuration directories (as we do on
		 * non-Windows systems) we would need to use different port number s but it might be
		 * difficult to get a port number which is unique for a configuration directory (path)
		 * and which is unused. This port number has to be guessed by the first and new instance
		 * and the only data is the configuration directory path.
		 * For now we use one port number, that is we support only one instance at all. */
		sock = socket_fd_open_inet(REMOTE_CMD_PORT);
		if (sock < 0)
			return 0;
		return sock;
	}

	sock = socket_fd_connect_inet(REMOTE_CMD_PORT);
	if (sock < 0)
		return -1;
#else
	gchar *display_name = gdk_get_display();
	const gchar *hostname = g_get_host_name();
	gchar *p;

	if (display_name == NULL)
		display_name = g_strdup("NODISPLAY");

	/* these lines are taken from dcopc.c in kdelibs */
	if ((p = strrchr(display_name, '.')) > strrchr(display_name, ':') && p != NULL)
		*p = '\0';
	/* remove characters that may not be acceptable in a filename */
	for (p = display_name; *p; p++)
	{
		if (*p == ':' || *p == '/')
			*p = '_';
	}

	if (socket_info.file_name == NULL)
		socket_info.file_name = g_strdup_printf("%s%cgeany_socket_%s_%s",
			app->configdir, G_DIR_SEPARATOR, hostname, display_name);

	g_free(display_name);

	/* check whether the real user id is the same as this of the socket file */
	check_socket_permissions();

	sock = socket_fd_connect_unix(socket_info.file_name);
	if (sock < 0)
	{
		remove_socket_link_full(); /* deletes the socket file and the symlink */
		return socket_fd_open_unix(socket_info.file_name);
	}
#endif

	/* remote command mode, here we have another running instance and want to use it */

#ifdef G_OS_WIN32
	/* first we send a request to retrieve the window handle and focus the window */
	socket_fd_write_all(sock, "window\n", 7);
	if (socket_fd_read(sock, (gchar *)&hwnd, sizeof(hwnd)) == sizeof(hwnd))
		SetForegroundWindow(hwnd);
#endif
	/* now we send the command line args */
	if (argc > 1)
	{
		send_open_command(sock, argc, argv);
	}

	if (cl_options.list_documents)
	{
		socket_get_document_list(sock);
	}

	socket_fd_close(sock);
	return -2;
}
Beispiel #3
0
static gint get_page_count(GtkPrintContext *context, DocInfo *dinfo)
{
	gdouble width, height;
	gint layout_h;
	gint i, j, lines_left;
	gchar *line_buf;

	if (dinfo == NULL)
		return -1;

	width = gtk_print_context_get_width(context);
	height = gtk_print_context_get_height(context);

	if (printing_prefs.print_line_numbers)
		/* remove line number margin space from overall width */
		width -= dinfo->max_line_number_margin * dinfo->font_width;

	pango_layout_set_width(dinfo->layout, width * PANGO_SCALE);

	/* add test text to get line height */
	pango_layout_set_text(dinfo->layout, "Test 1", -1);
	pango_layout_get_size(dinfo->layout, NULL, &layout_h);
	if (layout_h <= 0)
	{
		geany_debug("Invalid layout_h (%d). Falling back to default height (%d)",
			layout_h, 100 * PANGO_SCALE);
		layout_h = 100 * PANGO_SCALE;
	}
	dinfo->line_height = (gdouble)layout_h / PANGO_SCALE;
	dinfo->lines_per_page = ceil((height - dinfo->line_height) / dinfo->line_height);
#ifdef GEANY_PRINT_DEBUG
	geany_debug("max lines_per_page: %d", dinfo->lines_per_page);
#endif
	if (printing_prefs.print_page_numbers)
		dinfo->lines_per_page -= 2;
	if (printing_prefs.print_page_header)
		dinfo->lines_per_page -= 3;

	lines_left = dinfo->lines_per_page;

	i = 0;
	for (j = 0; j < dinfo->lines; j++)
	{
		gint lines = 1;
		gint line_width;

		line_buf = sci_get_line(dinfo->doc->editor->sci, j);
		line_width = (g_utf8_strlen(line_buf, -1) + 1) * dinfo->font_width;
		if (line_width > width)
			lines = ceil(line_width / width);
#ifdef GEANY_PRINT_DEBUG
		if (lines != 1) geany_debug("%d %d", j+1, lines);
#endif

		while (lines_left < lines)
		{
			lines -= lines_left;
			lines_left = dinfo->lines_per_page;
			i++;
		}
		lines_left -= lines;
		g_free(line_buf);
	}

	return i + 1;
}
Beispiel #4
0
static void draw_page(GtkPrintOperation *operation, GtkPrintContext *context,
					  gint page_nr, gpointer user_data)
{
	DocInfo *dinfo = user_data;
	GeanyEditor *editor;
	cairo_t *cr;
	gdouble width, height;
	gdouble x, y;
	/*gint layout_h;*/
	gint count;
	GString *str;

	if (dinfo == NULL || page_nr >= dinfo->n_pages)
		return;

	editor = dinfo->doc->editor;

	if (dinfo->n_pages > 0)
	{
		gdouble fraction = (page_nr + 1) / (gdouble) dinfo->n_pages;
		gchar *text = g_strdup_printf(_("Page %d of %d"), page_nr, dinfo->n_pages);
		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(main_widgets.progressbar), fraction);
		gtk_progress_bar_set_text(GTK_PROGRESS_BAR(main_widgets.progressbar), text);
		g_free(text);
	}

#ifdef GEANY_PRINT_DEBUG
	geany_debug("draw_page = %d, pages = %d, (real) lines_per_page = %d",
		page_nr, dinfo->n_pages, dinfo->lines_per_page);
#endif

	str = g_string_sized_new(256);
	cr = gtk_print_context_get_cairo_context(context);
	width = gtk_print_context_get_width(context);
	height = gtk_print_context_get_height(context);

	cairo_set_source_rgb(cr, 0, 0, 0);
#ifdef GEANY_PRINT_DEBUG
	cairo_set_line_width(cr, 0.2);
	cairo_rectangle(cr, 0, 0, width, height);
	cairo_stroke(cr);
#endif
	cairo_move_to(cr, 0, 0);

	pango_layout_set_width(dinfo->layout, width * PANGO_SCALE);
	pango_layout_set_alignment(dinfo->layout, PANGO_ALIGN_LEFT);
	pango_layout_set_ellipsize(dinfo->layout, FALSE);
	pango_layout_set_justify(dinfo->layout, FALSE);

	if (printing_prefs.print_page_header)
		add_page_header(dinfo, cr, width, page_nr);

	count = 0;	/* the actual line counter for the current page, might be different from
				 * dinfo->cur_line due to possible line breaks */
	while (count < dinfo->lines_per_page)
	{
		gchar c = 'a';
		gint style = -1;
		PangoAttrList *layout_attr;
		PangoAttribute *attr;
		gint colours[3] = { 0 };
		gboolean add_linenumber = TRUE;
		gboolean at_eol;

		while (count < dinfo->lines_per_page && c != '\0')
		{
			at_eol = FALSE;

			g_string_erase(str, 0, str->len); /* clear the string */

			/* line numbers */
			if (printing_prefs.print_line_numbers && add_linenumber)
			{
				/* if we had a wrapped line on the last page which needs to be continued, don't
				 * add a line number */
				if (dinfo->long_line)
				{
					add_linenumber = FALSE;
				}
				else
				{
					gchar *line_number = NULL;
					gint cur_line_number_margin = get_line_numbers_arity(dinfo->cur_line + 1);
					gchar *fill = g_strnfill(
						dinfo->max_line_number_margin - cur_line_number_margin - 1, ' ');

					line_number = g_strdup_printf("%s%d ", fill, dinfo->cur_line + 1);
					g_string_append(str, line_number);
					dinfo->cur_line++; /* increase document line */
					add_linenumber = FALSE;
					style = STYLE_LINENUMBER;
					c = 'a'; /* dummy value */
					g_free(fill);
					g_free(line_number);
				}
			}
			/* data */
			else
			{
				style = sci_get_style_at(dinfo->doc->editor->sci, dinfo->cur_pos);
				c = sci_get_char_at(dinfo->doc->editor->sci, dinfo->cur_pos);
				if (c == '\0' || style == -1)
				{	/* if c gets 0, we are probably out of document boundaries,
					 * so stop to break out of outer loop */
					count = dinfo->lines_per_page;
					break;
				}
				dinfo->cur_pos++;

				/* convert tabs to spaces which seems to be better than using Pango tabs */
				if (c == '\t')
				{
					gint tab_width = sci_get_tab_width(editor->sci);
					gchar *s = g_strnfill(tab_width, ' ');
					g_string_append(str, s);
					g_free(s);
				}
				/* don't add line breaks, they are handled manually below */
				else if (c == '\r' || c == '\n')
				{
					gchar c_next = sci_get_char_at(dinfo->doc->editor->sci, dinfo->cur_pos);
					at_eol = TRUE;
					if (c == '\r' && c_next == '\n')
						dinfo->cur_pos++; /* skip LF part of CR/LF */
				}
				else
				{
					g_string_append_c(str, c); /* finally add the character */

					/* handle UTF-8: since we add char by char (better: byte by byte), we need to
					 * keep UTF-8 characters together(e.g. two bytes for one character)
					 * the input is always UTF-8 and c is signed, so all non-Ascii
					 * characters are less than 0 and consist of all bytes less than 0.
					 * style doesn't change since it is only one character with multiple bytes. */
					while (c < 0)
					{
						c = sci_get_char_at(dinfo->doc->editor->sci, dinfo->cur_pos);
						if (c < 0)
						{	/* only add the byte when it is part of the UTF-8 character
							 * otherwise we could add e.g. a '\n' and it won't be visible in the
							 * printed document */
							g_string_append_c(str, c);
							dinfo->cur_pos++;
						}
					}
				}
			}

			if (! at_eol)
			{
				/* set text */
				pango_layout_set_text(dinfo->layout, str->str, -1);
				/* attributes */
				layout_attr = pango_attr_list_new();
				/* foreground colour */
				get_rgb_values(dinfo->styles[style][FORE], &colours[0], &colours[1], &colours[2]);
				attr = pango_attr_foreground_new(colours[0], colours[1], colours[2]);
				ADD_ATTR(layout_attr, attr);
				/* background colour */
				get_rgb_values(dinfo->styles[style][BACK], &colours[0], &colours[1], &colours[2]);
				attr = pango_attr_background_new(colours[0], colours[1], colours[2]);
				ADD_ATTR(layout_attr, attr);
				/* bold text */
				if (dinfo->styles[style][BOLD])
				{
					attr = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
					ADD_ATTR(layout_attr, attr);
				}
				/* italic text */
				if (dinfo->styles[style][ITALIC])
				{
					attr = pango_attr_style_new(PANGO_STYLE_ITALIC);
					ADD_ATTR(layout_attr, attr);
				}
				pango_layout_set_attributes(dinfo->layout, layout_attr);
				pango_layout_context_changed(dinfo->layout);
				pango_attr_list_unref(layout_attr);
			}

			cairo_get_current_point(cr, &x, &y);


			/* normal line break at eol character in document */
			if (at_eol)
			{
				/*pango_layout_get_size(dinfo->layout, NULL, &layout_h);*/
				/*cairo_move_to(cr, 0, y + (gdouble)layout_h / PANGO_SCALE);*/
				cairo_move_to(cr, 0, y + dinfo->line_height);

				count++;
				/* we added a new document line so request a new line number */
				add_linenumber = TRUE;
			}
			else
			{
				gint x_offset = 0;
				/* maybe we need to force a line break because of too long line */
				if (x >= (width - dinfo->font_width))
				{
					/* don't start the line at horizontal origin because we need to skip the
					 * line number margin */
					if (printing_prefs.print_line_numbers)
					{
						x_offset = (dinfo->max_line_number_margin + 1) * dinfo->font_width;
					}

					/*pango_layout_get_size(dinfo->layout, NULL, &layout_h);*/
					/*cairo_move_to(cr, x_offset, y + (gdouble)layout_h / PANGO_SCALE);*/
					/* this is faster but not exactly the same as above */
					cairo_move_to(cr, x_offset, y + dinfo->line_height);
					cairo_get_current_point(cr, &x, &y);
					count++;
				}
				if (count < dinfo->lines_per_page)
				{
					/* str->len is counted in bytes not characters, so use g_utf8_strlen() */
					x_offset = (g_utf8_strlen(str->str, -1) * dinfo->font_width);

					if (dinfo->long_line && count == 0)
					{
						x_offset = (dinfo->max_line_number_margin + 1) * dinfo->font_width;
						dinfo->long_line = FALSE;
					}

					pango_cairo_show_layout(cr, dinfo->layout);
					cairo_move_to(cr, x + x_offset, y);
				}
				else
				/* we are on a wrapped line but we are out of lines on this page, so continue
				 * the current line on the next page and remember to continue in current line */
					dinfo->long_line = TRUE;
			}
		}
	}

	if (printing_prefs.print_line_numbers)
	{	/* print a thin line between the line number margin and the data */
		gint y_start = 0;

		if (printing_prefs.print_page_header)
			y_start = (dinfo->line_height * 3) - 2;	/* "- 2": to connect the line number line to
													 * the page header frame */

		cairo_set_line_width(cr, 0.3);
		cairo_move_to(cr, (dinfo->max_line_number_margin * dinfo->font_width) + 1, y_start);
		cairo_line_to(cr, (dinfo->max_line_number_margin * dinfo->font_width) + 1,
			y + dinfo->line_height); /* y is last added line, we reuse it */
		cairo_stroke(cr);
	}

	if (printing_prefs.print_page_numbers)
	{
		gchar *line = g_strdup_printf("<small>- %d -</small>", page_nr + 1);
		pango_layout_set_markup(dinfo->layout, line, -1);
		pango_layout_set_alignment(dinfo->layout, PANGO_ALIGN_CENTER);
		cairo_move_to(cr, 0, height - dinfo->line_height);
		pango_cairo_show_layout(cr, dinfo->layout);
		g_free(line);

#ifdef GEANY_PRINT_DEBUG
		cairo_set_line_width(cr, 0.3);
		cairo_move_to(cr, 0, height - (1.25 * dinfo->line_height));
		cairo_line_to(cr, width - 1, height - (1.25 * dinfo->line_height));
		cairo_stroke(cr);
#endif
	}
	g_string_free(str, TRUE);
}
Beispiel #5
0
static gchar *encodings_convert_to_utf8_with_suggestion(const gchar *buffer, gsize size,
		const gchar *suggested_charset, gchar **used_encoding)
{
	const gchar *locale_charset = NULL;
	const gchar *charset;
	gchar *utf8_content;
	gboolean check_suggestion = suggested_charset != NULL;
	gboolean check_locale = FALSE;
	gint i, preferred_charset;

	if ((gint)size == -1)
	{
		size = strlen(buffer);
	}

	/* current locale is not UTF-8, we have to check this charset */
	check_locale = ! g_get_charset(&locale_charset);

	/* First check for preferred charset, if specified */
	preferred_charset = file_prefs.default_open_encoding;

	if (preferred_charset == encodings[GEANY_ENCODING_NONE].idx ||
		preferred_charset < 0 ||
		preferred_charset >= GEANY_ENCODINGS_MAX)
	{
		preferred_charset = -1;
	}

	/* -1 means "Preferred charset" */
	for (i = -1; i < GEANY_ENCODINGS_MAX; i++)
	{
		if (G_UNLIKELY(i == encodings[GEANY_ENCODING_NONE].idx))
			continue;

		if (check_suggestion)
		{
			check_suggestion = FALSE;
			charset = encodings_normalize_charset(suggested_charset);
			if (charset == NULL) /* we failed at normalizing suggested encoding, try it as is */
				charset = suggested_charset;
			i = -2; /* keep i below the start value to have it again at -1 on the next loop run */
		}
		else if (check_locale)
		{
			check_locale = FALSE;
			charset = locale_charset;
			i = -2; /* keep i below the start value to have it again at -1 on the next loop run */
		}
		else if (i == -1)
		{
			if (preferred_charset >= 0)
			{
				charset = encodings[preferred_charset].charset;
				geany_debug("Using preferred charset: %s", charset);
			}
			else
				continue;
		}
		else if (i >= 0)
			charset = encodings[i].charset;
		else /* in this case we have i == -2, continue to increase i and go ahead */
			continue;

		if (G_UNLIKELY(charset == NULL))
			continue;

		geany_debug("Trying to convert %" G_GSIZE_FORMAT " bytes of data from %s into UTF-8.",
			size, charset);
		utf8_content = encodings_convert_to_utf8_from_charset(buffer, size, charset, FALSE);

		if (G_LIKELY(utf8_content != NULL))
		{
			if (used_encoding != NULL)
			{
				if (G_UNLIKELY(*used_encoding != NULL))
				{
					geany_debug("%s:%d", __FILE__, __LINE__);
					g_free(*used_encoding);
				}
				*used_encoding = g_strdup(charset);
			}
			return utf8_content;
		}
	}

	return NULL;
}