コード例 #1
0
ファイル: GuiOptionMenu.cpp プロジェクト: dellison/APILPraat
void structGuiOptionMenu:: f_addOption (const wchar_t *text) {
	#if gtk
		gtk_combo_box_append_text (GTK_COMBO_BOX (d_widget), Melder_peekWcsToUtf8 (text));
	#elif motif
		GuiMenuItem menuItem = Thing_new (GuiMenuItem);
		menuItem -> d_widget = XtVaCreateManagedWidget (Melder_peekWcsToUtf8 (text), xmToggleButtonWidgetClass, d_widget, NULL);
		XtAddCallback (menuItem -> d_widget, XmNvalueChangedCallback, cb_optionChanged, (XtPointer) this);
		Collection_addItem (d_options, menuItem);
	#endif
}
コード例 #2
0
ファイル: Graphics_image.cpp プロジェクト: Crisil/praat
void Graphics_imageFromFile (Graphics me, const wchar_t *relativeFileName, double x1, double x2, double y1, double y2) {
	if (my screen) {
		_GraphicsScreen_imageFromFile (static_cast <GraphicsScreen> (me), relativeFileName, x1, x2, y1, y2);
	}
	if (my recording) {
		char *txt_utf8 = Melder_peekWcsToUtf8 (relativeFileName);
		int length = strlen (txt_utf8) / sizeof (double) + 1;
		op (IMAGE_FROM_FILE, 5 + length); put (x1); put (x2); put (y1); put (y2); sput (txt_utf8, length)
	}
コード例 #3
0
ファイル: Thing.cpp プロジェクト: alekstorm/tala
void * _Thing_check (I, void *klas, const char *fileName, int line) {
	Thing me = (structThing*)void_me;   /* NOT the macro `iam (Thing);' because that would be recursive. */
	if (! me) Melder_fatal ("(_Thing_check:) NULL object passed to a function\n"
		"in file %.100s at line %d.", fileName, line);
	Thing_Table table = my methods;
	while (table != klas && table != NULL) table = table -> _parent;
	if (! table)
		Melder_fatal ("(_Thing_check:) Object of wrong class (%.50s) passed to a function\n"
				"in file %.100s at line %d.", Melder_peekWcsToUtf8 (our _className), fileName, line);
	return me;
}
コード例 #4
0
ファイル: GuiCheckButton.cpp プロジェクト: dellison/APILPraat
GuiCheckButton GuiCheckButton_create (GuiForm parent, int left, int right, int top, int bottom,
	const wchar_t *buttonText, void (*valueChangedCallback) (void *boss, GuiCheckButtonEvent event), void *valueChangedBoss, unsigned long flags)
{
	GuiCheckButton me = Thing_new (GuiCheckButton);
	my d_shell = parent -> d_shell;
	my d_parent = parent;
	my d_valueChangedCallback = valueChangedCallback;
	my d_valueChangedBoss = valueChangedBoss;
	#if gtk
		my d_widget = gtk_check_button_new_with_label (Melder_peekWcsToUtf8 (buttonText));
		_GuiObject_setUserData (my d_widget, me);
		my v_positionInForm (my d_widget, left, right, top, bottom, parent);
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (my d_widget), (flags & GuiCheckButton_SET) != 0);
		if (flags & GuiCheckButton_INSENSITIVE) {
			my f_setSensitive (false);
		}
		g_signal_connect (G_OBJECT (my d_widget), "destroy", G_CALLBACK (_GuiGtkCheckButton_destroyCallback), me);
		my d_valueChangedHandlerId = g_signal_connect (GTK_TOGGLE_BUTTON (my d_widget), "toggled", G_CALLBACK (_GuiGtkCheckButton_valueChangedCallback), me);
	#elif cocoa
	#elif win
		my d_widget = _Gui_initializeWidget (xmToggleButtonWidgetClass, parent -> d_widget, buttonText);
		_GuiObject_setUserData (my d_widget, me);
		my d_widget -> isRadioButton = false;
		my d_widget -> window = CreateWindow (L"button", _GuiWin_expandAmpersands (buttonText),
			WS_CHILD | BS_AUTOCHECKBOX | WS_CLIPSIBLINGS,
			my d_widget -> x, my d_widget -> y, my d_widget -> width, my d_widget -> height,
			my d_widget -> parent -> window, (HMENU) 1, theGui.instance, NULL);
		SetWindowLongPtr (my d_widget -> window, GWLP_USERDATA, (LONG_PTR) my d_widget);
		SetWindowFont (my d_widget -> window, GetStockFont (ANSI_VAR_FONT), FALSE);
		my v_positionInForm (my d_widget, left, right, top, bottom, parent);
		if (flags & GuiCheckButton_SET) {
			Button_SetCheck (my d_widget -> window, BST_CHECKED);
		}
		if (flags & GuiCheckButton_INSENSITIVE) {
			my f_setSensitive (false);
		}
	#elif mac
		my d_widget = _Gui_initializeWidget (xmToggleButtonWidgetClass, parent -> d_widget, buttonText);
		_GuiObject_setUserData (my d_widget, me);
		my d_widget -> isRadioButton = false;
		CreateCheckBoxControl (my d_widget -> macWindow, & my d_widget -> rect, NULL,
			(flags & GuiCheckButton_SET) != 0, true, & my d_widget -> nat.control.handle);
		Melder_assert (my d_widget -> nat.control.handle != NULL);
		SetControlReference (my d_widget -> nat.control.handle, (long) my d_widget);
		my d_widget -> isControl = true;
		_GuiNativeControl_setFont (my d_widget, 0, 13);
		_GuiNativeControl_setTitle (my d_widget);
		my v_positionInForm (my d_widget, left, right, top, bottom, parent);
		if (flags & GuiCheckButton_INSENSITIVE) {
			my f_setSensitive (false);
		}
	#endif
	return me;
}
コード例 #5
0
wchar_t * Melder_getenv (const wchar_t *variableName) {
	#if defined (macintosh) || defined (UNIX) || defined (__MINGW32__)
		return Melder_peekUtf8ToWcs (getenv (Melder_peekWcsToUtf8 (variableName)));
	#elif defined (_WIN32)
		static wchar_t buffer [11] [255];
		static int ibuffer = 0;
		if (++ ibuffer == 11) ibuffer = 0;
		long n = GetEnvironmentVariableW (variableName, buffer [ibuffer], 255);
		if (n == ERROR_ENVVAR_NOT_FOUND) return NULL;
		return & buffer [ibuffer] [0];
	#endif
}
コード例 #6
0
ファイル: GuiMenu.cpp プロジェクト: alekstorm/tala
GuiObject GuiMenuBar_addMenu2 (GuiObject bar, const wchar_t *title, long flags, GuiObject *menuTitle) {
	GuiObject menu;
	*menuTitle = gtk_menu_item_new_with_label (Melder_peekWcsToUtf8 (title));
	menu = gtk_menu_new ();
	GtkAccelGroup *ag = (GtkAccelGroup*)(GTK_IS_MENU_BAR (bar) ? g_object_get_data (G_OBJECT (bar), "accel-group") : gtk_menu_get_accel_group (GTK_MENU (bar)));
	gtk_menu_set_accel_group (GTK_MENU (menu), ag);
	if (flags & GuiMenu_INSENSITIVE)
		gtk_widget_set_sensitive (menu, FALSE);
	gtk_menu_item_set_submenu (GTK_MENU_ITEM (*menuTitle), menu);
	gtk_menu_shell_append (GTK_MENU_SHELL (bar), *menuTitle);
	gtk_widget_show (menu);
	gtk_widget_show (*menuTitle);
	return menu;
}
コード例 #7
0
ファイル: GuiOptionMenu.cpp プロジェクト: dellison/APILPraat
void structGuiOptionMenu :: f_setValue (int value) {
	#if gtk
		gtk_combo_box_set_active (GTK_COMBO_BOX (d_widget), value - 1);
	#elif cocoa
	#elif motif
		for (int i = 1; i <= d_options -> size; i ++) {
			GuiMenuItem menuItem = static_cast <GuiMenuItem> (d_options -> item [i]);
			XmToggleButtonSetState (menuItem -> d_widget, i == value, False);
			if (i == value) {
				XtVaSetValues (d_xmCascadeButton, XmNlabelString, Melder_peekWcsToUtf8 (menuItem -> d_widget -> name), NULL);
			}
		}
	#endif
	d_value = value;
}
コード例 #8
0
ファイル: GuiMenu.cpp プロジェクト: alekstorm/tala
GuiObject GuiMenuBar_addMenu3 (GuiObject parent, const wchar_t *title, long flags, GuiObject *button) {
	GuiObject menu;
	menu = gtk_menu_new ();
	*button = gtk_button_new_with_label (Melder_peekWcsToUtf8 (title));
	g_signal_connect_object (G_OBJECT (*button), "event",
		GTK_SIGNAL_FUNC (button_press), G_OBJECT (menu), G_CONNECT_SWAPPED);
	g_object_set_data (G_OBJECT (menu), "button", *button);
	if (flags & GuiMenu_INSENSITIVE)
		gtk_widget_set_sensitive (menu, FALSE);
	gtk_menu_attach_to_widget (GTK_MENU (menu), *button, NULL);
	/* TODO: Free button? */
	gtk_container_add (GTK_CONTAINER (parent), *button);
	gtk_widget_show (menu);
	gtk_widget_show (*button);
	return menu;
}
コード例 #9
0
ファイル: GuiOptionMenu.cpp プロジェクト: dellison/APILPraat
static void cb_optionChanged (GuiObject w, XtPointer void_me, XtPointer call) {
	iam (GuiOptionMenu);
	(void) call;
	for (int i = 1; i <= my d_options -> size; i ++) {
		GuiMenuItem item = static_cast <GuiMenuItem> (my d_options -> item [i]);
		if (item -> d_widget == w) {
			XtVaSetValues (my d_xmCascadeButton, XmNlabelString, Melder_peekWcsToUtf8 (item -> d_widget -> name), NULL);
			XmToggleButtonSetState (item -> d_widget, TRUE, FALSE);
			if (Melder_debug == 11) {
				Melder_warning (i, " \"", item -> d_widget -> name, "\"");
			}
		} else {
			XmToggleButtonSetState (item -> d_widget, FALSE, FALSE);
		}
	}
}
コード例 #10
0
void Melder_system (const wchar_t *command) {
	#if defined (macintosh) || defined (UNIX)
		if (system (Melder_peekWcsToUtf8 (command)) != 0)
			Melder_throw ("System command failed.");
	#elif defined (_WIN32)
		STARTUPINFO siStartInfo;
		PROCESS_INFORMATION piProcInfo;
		wchar_t *comspec = Melder_getenv (L"COMSPEC");   // e.g. "C:\WINDOWS\COMMAND.COM" or "C:\WINNT\windows32\cmd.exe"
		if (comspec == NULL) {
			comspec = Melder_getenv (L"ComSpec");
		}
		MelderString buffer = { 0 };
		if (comspec != NULL) {
			MelderString_copy (& buffer, comspec);
		} else {
			OSVERSIONINFOEX osVersionInfo;
			memset (& osVersionInfo, 0, sizeof (OSVERSIONINFOEX));
			osVersionInfo. dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
			if (! GetVersionEx ((OSVERSIONINFO *) & osVersionInfo)) {
				osVersionInfo. dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
				if (! GetVersionEx ((OSVERSIONINFO *) & osVersionInfo))
					Melder_throw ("System command cannot find system version.");
			}
			switch (osVersionInfo. dwPlatformId) {
				case VER_PLATFORM_WIN32_NT: {
					MelderString_copy (& buffer, L"cmd.exe");
				} break; case VER_PLATFORM_WIN32_WINDOWS: {
					MelderString_copy (& buffer, L"command.com");
				} break; default: {
					MelderString_copy (& buffer, L"command.com");
				}
			}
		}
		MelderString_append (& buffer, L" /c ", command);
        memset (& siStartInfo, 0, sizeof (siStartInfo));
        siStartInfo. cb = sizeof (siStartInfo);
		if (! CreateProcess (NULL, buffer.string, NULL, NULL, TRUE, 0, NULL, NULL, & siStartInfo, & piProcInfo))
			Melder_throw ("Cannot create subprocess.");
		WaitForSingleObject (piProcInfo. hProcess, -1);
		CloseHandle (piProcInfo. hProcess);
		CloseHandle (piProcInfo. hThread);
	#endif
}
/*
	BSD systems provide ftruncate, several others supply chsize, and a few
	may provide a (possibly undocumented) fcntl option F_FREESP. Under MS-DOS,
	you can sometimes use write(fd, "", 0). However, there is no portable
	solution, nor a way to delete blocks at the beginning.
*/
static void MelderFile_truncate (MelderFile me, long size) {
#if defined(_WIN32)

	HANDLE hFile;
	DWORD fdwAccess = GENERIC_READ | GENERIC_WRITE, fPos;
	DWORD fdwShareMode = 0; /* File cannot be shared */
	LPSECURITY_ATTRIBUTES lpsa = NULL;
	DWORD fdwCreate = OPEN_EXISTING;
	LARGE_INTEGER fileSize;

	MelderFile_close (me);

	hFile = CreateFileW (my path, fdwAccess, fdwShareMode, lpsa, fdwCreate,
	                     FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE) {
		Melder_throw ("Can't open file ", MelderFile_messageName (me), ".");
	}

	// Set current file pointer to position 'size'

	fileSize.LowPart = size;
	fileSize.HighPart = 0; /* Limit the file size to 2^32 - 2 bytes */
	fPos = SetFilePointer (hFile, fileSize.LowPart, &fileSize.HighPart, FILE_BEGIN);
	if (fPos == 0xFFFFFFFF) {
		Melder_throw ("Can't set the position at size ", size, "for file ", 	MelderFile_messageName (me), ".");
	}

	// Limit the file size as the current position of the file pointer.

	SetEndOfFile (hFile);
	CloseHandle (hFile);

#elif defined(linux) || defined(macintosh)

	MelderFile_close (me);
	if (truncate (Melder_peekWcsToUtf8 (my path), size) == -1) Melder_throw ("Truncating failed for file ",
		        MelderFile_messageName (me), " (", Melder_peekUtf8ToWcs (strerror (errno)), ").");
#else
	Melder_throw ("Don't know what to do.");
#endif
}
コード例 #12
0
ファイル: GuiButton.cpp プロジェクト: georgiee/lip-sync-lpc
				return true;
			}
			return false;
		}
	#else
	#endif
#endif

GuiObject GuiButton_create (GuiObject parent, int left, int right, int top, int bottom,
	const wchar_t *buttonText, void (*activateCallback) (void *boss, GuiButtonEvent event), void *activateBoss, unsigned long flags)
{
	GuiButton me = Melder_calloc_f (struct structGuiButton, 1);
	my activateCallback = activateCallback;
	my activateBoss = activateBoss;
	#if gtk
		my widget = gtk_button_new_with_label (Melder_peekWcsToUtf8 (buttonText));
		_GuiObject_setUserData (my widget, me);
//		_GuiObject_position (my widget, left, right, top, bottom);

		// TODO: use gtk_box_pack_start(GTK_BOX(parent), my widget, FALSE, FALSE, ?)
		if (parent)
			gtk_container_add (GTK_CONTAINER (parent), GTK_WIDGET (my widget));
		if (flags & GuiButton_DEFAULT || flags & GuiButton_ATTRACTIVE) {
			GTK_WIDGET_SET_FLAGS (my widget, GTK_CAN_DEFAULT);
			GtkWidget *shell = gtk_widget_get_toplevel (GTK_WIDGET (my widget));
			gtk_window_set_default (GTK_WINDOW (shell), GTK_WIDGET (my widget));
		} else if (1) {
			gtk_button_set_focus_on_click (GTK_BUTTON (my widget), false);
			GTK_WIDGET_UNSET_FLAGS (my widget, GTK_CAN_DEFAULT);
		}
		g_signal_connect (G_OBJECT (my widget), "destroy",
TextGrid TextGrid_readFromTIMITLabelFile (MelderFile file, int phnFile) {
	try {
		double dt = 1.0 / 16000; /* 1 / (TIMIT samplingFrequency) */
		double xmax = dt;
		autofile f = Melder_fopen (file, "r");

		// Ending time will only be known after all labels have been read.
		// We start with a sufficiently long duration (one hour) and correct this later.

		autoTextGrid me = TextGrid_create (0, 3600, L"wrd", 0);
		IntervalTier timit = (IntervalTier) my tiers -> item[1];
		long linesRead = 0;
		char line[200], label[200];
		while (fgets (line, 199, f)) {
			long it1, it2;
			linesRead++;
			if (sscanf (line, "%ld%ld%s", &it1, &it2, label) != 3) {
				Melder_throw ("Incorrect number of items.");
			}
			if (it1 < 0 || it2 <= it1) {
				Melder_throw (L"Incorrect time at line ", linesRead);
			}
			xmax = it2 * dt;
			double xmin = it1 * dt;
			long ni = timit -> intervals -> size - 1;
			if (ni < 1) {
				ni = 1;
				// Some files do not start with a first line "0 <number2> h#".
				// Instead they start with "<number1> <number2> h#", where number1 > 0.
				// We override number1 with 0. */

				if (xmin > 0 && phnFile) {
					xmin = 0;
				}
			}
			TextInterval interval = (TextInterval) timit -> intervals -> item[ni];
			if (xmin < interval -> xmax && linesRead > 1) {
				xmin = interval -> xmax;
				Melder_warning (L"File \"", MelderFile_messageName (file), L"\": Start time set to previous end "
				                 "time for label at line ", Melder_integer (linesRead), L".");
			}
			// standard: new TextInterval
			const char *labelstring = (strncmp (label, "h#", 2) ? label : TIMIT_DELIMITER);
			IntervalTier_add (timit, xmin, xmax, Melder_peekUtf8ToWcs (labelstring));
		}

		// Now correct the end times, based on last read interval.
		// (end time was set to large value!)

		if (timit -> intervals -> size < 2) {
			Melder_throw ("Empty TextGrid");
		}
		Collection_removeItem (timit -> intervals, timit -> intervals -> size);
		TextInterval interval = (TextInterval) timit -> intervals -> item[timit -> intervals -> size];
		timit -> xmax = interval -> xmax;
		my xmax = xmax;
		if (phnFile) { // Create tier 2 with IPA symbols
			autoIntervalTier ipa = Data_copy (timit);
			Thing_setName (ipa.peek(), L"ipa");
			// First change the data in ipa
			for (long i = 1; i <= ipa -> intervals -> size; i++) {
				interval = (TextInterval) timit -> intervals -> item[i];

				TextInterval_setText ( (TextInterval) ipa -> intervals -> item[i],
				                       Melder_peekUtf8ToWcs (timitLabelToIpaLabel (Melder_peekWcsToUtf8 (interval -> text))));
			}
			Collection_addItem (my tiers, ipa.transfer()); // Then: add to collection
			Thing_setName (timit, L"phn");  // rename wrd
		}
		f.close (file);
		return me.transfer();
	} catch (MelderError) {
		Melder_throw ("TextGrid not read from file ", file, ".");
	}
}
コード例 #14
0
ファイル: GuiMenu.cpp プロジェクト: alekstorm/tala
GuiObject GuiMenu_addItem (GuiObject menu, const wchar_t *title, long flags,
	void (*commandCallback) (GuiObject, XtPointer, XtPointer), const void *closure)
{
	Boolean toggle = flags & (GuiMenu_CHECKBUTTON | GuiMenu_RADIO_FIRST | GuiMenu_RADIO_NEXT | GuiMenu_TOGGLE_ON) ? True : False;
	GuiObject button;
	int accelerator = flags & 127;
	Melder_assert (title != NULL);
	if (toggle) {
		if (flags & (GuiMenu_RADIO_FIRST)) group = NULL;
		if (flags & (GuiMenu_RADIO_FIRST | GuiMenu_RADIO_NEXT)) {
			button = gtk_radio_menu_item_new_with_label (group, Melder_peekWcsToUtf8 (title));
			group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (button));
			//Melder_casual ("Created a radio menu item with title %ls, group %ld", title, group);
		} else {
			button = gtk_check_menu_item_new_with_label (Melder_peekWcsToUtf8 (title));
		}
	} else {
		button = gtk_menu_item_new_with_label (Melder_peekWcsToUtf8 (title));
	}
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), button);
	Melder_assert (button != NULL);
	if (flags & GuiMenu_INSENSITIVE)
		GuiObject_setSensitive (button, false);
	if (flags & GuiMenu_TOGGLE_ON)
		gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (button), TRUE);
	if (accelerator) {
		/*
		 * For printable characters, the Command key is assumed.
		 */
		if (accelerator >= 32)
			flags |= GuiMenu_COMMAND;
		
		static const guint acceleratorKeys [] = { 0,
			GDK_Left, GDK_Right, GDK_Up, GDK_Down, GDK_Pause, GDK_Delete, GDK_Insert, GDK_BackSpace,
			GDK_Tab, GDK_Return, GDK_Home, GDK_End, GDK_Return, GDK_Page_Up, GDK_Page_Down, GDK_Escape,
			GDK_F1, GDK_F2, GDK_F3, GDK_F4, GDK_F5, GDK_F6, GDK_F7, GDK_F8, GDK_F9, GDK_F10, GDK_F11, GDK_F12,
			0, 0, 0 };

		int modifiers = 0;
		if (flags & GuiMenu_COMMAND) modifiers |= GDK_CONTROL_MASK;
		if (flags & GuiMenu_SHIFT)   modifiers |= GDK_SHIFT_MASK;
		if (flags & GuiMenu_OPTION)  modifiers |= GDK_MOD1_MASK;

		guint key;
		if (accelerator < 32) {
			key = acceleratorKeys [accelerator];
		} else {
			// gdk key symbols in the ASCII range are equal to ASCII
			key = accelerator;
		}

		GtkAccelGroup *ag = gtk_menu_get_accel_group (GTK_MENU (menu));

		if (key != 0)
			gtk_widget_add_accelerator (button, toggle ? "toggled" : "activate",
				ag, key, (GdkModifierType)modifiers, GTK_ACCEL_VISIBLE);
	}
	#if mac
		if (flags & GuiMenu_ATTRACTIVE) {
			//Melder_casual ("attractive!");
			SetItemStyle (button -> nat.entry.handle, button -> nat.entry.item, bold);
		}
	#endif
	if (commandCallback != NULL) {
		gulong handlerId = g_signal_connect (G_OBJECT (button),
			toggle ? "toggled" : "activate",
			G_CALLBACK (commandCallback), (gpointer) closure);
		g_object_set_data (G_OBJECT (button), "handlerId", (gpointer) handlerId);
		g_object_set_data (G_OBJECT (button), "commandCallback", (gpointer) commandCallback);
		g_object_set_data (G_OBJECT (button), "commandClosure", (gpointer) closure);
	} else {
		gtk_widget_set_sensitive (button, FALSE);
	}
	gtk_widget_show (button);

	return button;
}
コード例 #15
0
ファイル: Printer.cpp プロジェクト: alekstorm/tala
int Printer_print (void (*draw) (void *boss, Graphics g), void *boss) {
	#if defined (UNIX)
		structMelderFile tempFile = { 0 };
		char tempPath_utf8 [] = "/tmp/picXXXXXX";
		close (mkstemp (tempPath_utf8));
		Melder_pathToFile (Melder_peekUtf8ToWcs (tempPath_utf8), & tempFile);
		thePrinter. graphics = Graphics_create_postscriptjob (& tempFile, thePrinter. resolution,
			thePrinter. spots, thePrinter. paperSize, thePrinter. orientation, thePrinter. magnification);
		if (! thePrinter. graphics) return Melder_error1 (L"Cannot create temporary PostScript file for printing.");
		draw (boss, thePrinter. graphics);
		forget (thePrinter. graphics);
		char command [500];
		sprintf (command, Melder_peekWcsToUtf8 (Site_getPrintCommand ()), tempPath_utf8);
		system (command);
		MelderFile_delete (& tempFile);
	#elif defined (_WIN32)
		int postScriptCode = POSTSCRIPT_PASSTHROUGH;
		DOCINFO docInfo;
		DEVMODE *devMode;
		initPrinter ();
		if (! theWinPrint. hDevMode) {
			memset (& theWinPrint, 0, sizeof (PRINTDLG));
			theWinPrint. lStructSize = sizeof (PRINTDLG);
			theWinPrint. Flags = PD_RETURNDEFAULT;
			if (! PrintDlg (& theWinPrint)) return Melder_error1 (L"Cannot initialize printer.");
		}
		if (Melder_backgrounding) {
			theWinPrint. Flags = PD_RETURNDEFAULT | PD_RETURNDC;
			if (! PrintDlg (& theWinPrint) || theWinPrint. hDC == NULL) {
				return Melder_error1 (L"Cannot print from a script on this computer.");
			}
		} else {
			theWinPrint. Flags &= ~ PD_RETURNDEFAULT;
			theWinPrint. Flags |= PD_RETURNDC;
			if (! PrintDlg (& theWinPrint)) return 1;
		}
		theWinDC = theWinPrint. hDC;
		thePrinter. postScript = thePrinter. allowDirectPostScript &&
			Escape (theWinDC, QUERYESCSUPPORT, sizeof (int), (LPSTR) & postScriptCode, NULL);
		/*
		 * The HP colour inkjet printer returns in dmFields:
		 * 0, 1, 8, 9, 10, 11, 12, 13, 14, 15, 23, 24, 25, 26 = DM_ORIENTATION |
		 *    DM_PAPERSIZE | DM_COPIES | DM_DEFAULTSOURCE | DM_PRINTQUALITY |
		 *    DM_COLOR | DM_DUPLEX | DM_YRESOLUTION | DM_TTOPTION | DM_COLLATE |
		 *    DM_ICMMETHOD | DM_ICMINTENT | DM_MEDIATYPE | DM_DITHERTYPE
		 */
		devMode = * (DEVMODE **) theWinPrint. hDevMode;
		thePrinter. resolution = devMode -> dmFields & DM_YRESOLUTION ? devMode -> dmYResolution :
			devMode -> dmFields & DM_PRINTQUALITY ?
			( devMode -> dmPrintQuality > 0 ? devMode -> dmPrintQuality : 300 ) : 300;
		if (devMode -> dmFields & DM_PAPERWIDTH) {
			thePrinter. paperWidth = devMode -> dmPaperWidth * thePrinter. resolution / 254;
			thePrinter. paperHeight = devMode -> dmPaperLength * thePrinter. resolution / 254;
		} else if (devMode -> dmFields & DM_PAPERSIZE) {
			static struct { float width, height; } sizes [] = { { 0, 0 }, { 8.5, 11 }, { 8.5, 11 }, { 11, 17 },
				{ 17, 11 }, { 8.5, 14 }, { 5.5, 8.5 }, { 7.25, 10.5 }, { 297/25.4, 420/25.4 },
				{ 210/25.4, 297/25.4 }, { 210/25.4, 297/25.4 }, { 148.5/25.4, 210/25.4 },
				{ 250/25.4, 354/25.4 }, { 182/25.4, 257/25.4 }, { 8.5, 13 },
				{ 215/25.4, 275/25.4 }, { 10, 14 }, { 11, 17 }, { 8.5, 11 }, { 3.875, 8.875 },
				{ 4.125, 9.5 }, { 4.5, 10.375 } };
			int paperSize = devMode -> dmPaperSize;
			if (paperSize <= 0 || paperSize > 21) paperSize = 1;
			thePrinter. paperWidth = sizes [paperSize]. width * thePrinter. resolution;
			thePrinter. paperHeight = sizes [paperSize]. height * thePrinter. resolution;
			if (devMode -> dmOrientation == DMORIENT_LANDSCAPE) {
				long dummy = thePrinter. paperWidth;
				thePrinter. paperWidth = thePrinter. paperHeight;
				thePrinter. paperHeight = dummy;
			}
		} else {
			thePrinter. paperWidth = 1000;
			thePrinter. paperHeight = 1000;
		}
		EnableWindow ((HWND) XtWindow (theCurrentPraatApplication -> topShell), FALSE);
		SetAbortProc (theWinDC, AbortFunc);
		memset (& docInfo, 0, sizeof (DOCINFO));
		docInfo. cbSize = sizeof (DOCINFO);
		docInfo. lpszDocName = L"Praatjes";
		docInfo. lpszOutput = NULL;
		if (thePrinter. postScript) {
			StartDoc (theWinDC, & docInfo);
			StartPage (theWinDC);
			initPostScriptPage ();
			thePrinter. graphics = Graphics_create_postscriptprinter ();
			if (! thePrinter. graphics) return Melder_error1 (L"Cannot open printer.");
			draw (boss, thePrinter. graphics);
			forget (thePrinter. graphics);
			exitPostScriptPage ();
			EndPage (theWinDC);
			EndDoc (theWinDC);
		} else {
			StartDoc (theWinDC, & docInfo);
			StartPage (theWinDC);
			thePrinter. graphics = Graphics_create_screenPrinter (NULL, (unsigned long) theWinDC);
			if (! thePrinter. graphics) return Melder_error1 (L"Cannot open printer.");
			draw (boss, thePrinter. graphics);
			forget (thePrinter. graphics);
			if (EndPage (theWinDC) < 0) {
				Melder_error1 (L"Cannot print page.");
			} else {
				EndDoc (theWinDC);
			}
		}
		EnableWindow ((HWND) XtWindow (theCurrentPraatApplication -> topShell), TRUE);
		DeleteDC (theWinDC), theWinDC = NULL;
	#elif defined (macintosh)
		Boolean result;
		initPrinter ();
		if (Melder_backgrounding) {
			PMSessionValidatePageFormat (theMacPrintSession, theMacPageFormat, & result);
			PMSessionValidatePrintSettings (theMacPrintSession, theMacPrintSettings, & result);
		} else {
			Boolean accepted;
			PMSessionPrintDialog (theMacPrintSession, theMacPrintSettings, theMacPageFormat, & accepted);
			if (! accepted) return 1;   /* Normal cancelled return. */
		}
		PMSessionValidatePageFormat (theMacPrintSession, theMacPageFormat, & result);
		PMSessionValidatePrintSettings (theMacPrintSession, theMacPrintSettings, & result);
		PMResolution res;
		PMGetResolution (theMacPageFormat, & res);
		thePrinter. resolution = res. hRes;
		PMGetAdjustedPaperRect (theMacPageFormat, & paperSize);
		thePrinter. paperWidth = paperSize. right - paperSize. left;
		thePrinter. paperHeight = paperSize. bottom - paperSize. top;
		Boolean isPostScriptDriver = FALSE;
		//PMSessionIsDocumentFormatSupported (theMacPrintSession,
		//	kPMDocumentFormatPICTPS, & isPostScriptDriver);
		CFArrayRef supportedFormats;
		PMSessionGetDocumentFormatGeneration (theMacPrintSession, & supportedFormats);
		CFIndex numberOfSupportedFormats = CFArrayGetCount (supportedFormats);
		if (Melder_debug == 21) {
			MelderInfo_open ();
			MelderInfo_writeLine1 (L"Supported document formats:");
		}
		for (CFIndex i = 0; i < numberOfSupportedFormats; i ++) {
			CFStringRef supportedFormat = CFArrayGetValueAtIndex (supportedFormats, i);
			if (CFStringCompare (supportedFormat, kPMDocumentFormatPICTPS, 0) == 0) {
				isPostScriptDriver = TRUE;
			}
			if (Melder_debug == 21) {
				MelderInfo_writeLine3 (Melder_integer (i), L": ",
					Melder_peekUtf8ToWcs (CFStringGetCStringPtr (supportedFormat, kCFStringEncodingUTF8)));
			}
		}
		if (Melder_debug == 21) {
			MelderInfo_close ();
		}
		CFRelease (supportedFormats);
		isPostScriptDriver = FALSE;   // OVERRIDE, because from 10.4 on we have something better: we'll be sending PDF
		thePrinter. postScript = thePrinter. allowDirectPostScript && isPostScriptDriver;
		if (thePrinter. postScript) {
			CFStringRef strings [1];
			strings [0] = kPMGraphicsContextQuickdraw;
			CFArrayRef array = CFArrayCreate (kCFAllocatorDefault, (const void **) strings, 1, & kCFTypeArrayCallBacks);
			OSStatus err = PMSessionSetDocumentFormatGeneration (theMacPrintSession, kPMDocumentFormatPICTPS, array, NULL);
			CFRelease (array);
			if (err != 0) {
				return Melder_error2 (L"PMSessionSetDocumentFormatGeneration: error ", Melder_integer (err));
			}
		}
		PMOrientation orientation;
		PMGetOrientation (theMacPageFormat, & orientation);
		thePrinter. orientation = orientation == kPMLandscape ||
			orientation == kPMReverseLandscape ? kGraphicsPostscript_orientation_LANDSCAPE : kGraphicsPostscript_orientation_PORTRAIT;
		PMSessionBeginDocument (theMacPrintSession, theMacPrintSettings, theMacPageFormat);
		PMSessionBeginPage (theMacPrintSession, theMacPageFormat, NULL);
		PMSessionGetGraphicsContext (theMacPrintSession, kPMGraphicsContextQuickdraw, (void **) & theMacPort);
		/*
		 * On PostScript, the point (0, 0) is the bottom left corner of the paper, which is fine.
		 * On the screen, however, the point (0, 0) is the top left corner of the writable page.
		 * Since we want paper-related margins, not writable-page-related margins,
		 * we require that this point gets the coordinates (250, 258) or so,
		 * so that the top left corner of the paper gets coordinates (0, 0).
		 * The "left" and "top" attributes of rPaper are negative values (e.g. -250 and -258),
		 * so multiply them by -1.
		 *
		 * Under Carbon, the port has to be set inside the page.
		 */
		SetPort (theMacPort);
		if (! thePrinter. postScript) SetOrigin (- paperSize. left, - paperSize. top);
		if (thePrinter. postScript) {
			if (! openPostScript ()) error1 (L"Cannot print PostScript.")
			thePrinter. graphics = Graphics_create_postscriptprinter ();
			if (! thePrinter. graphics) goto end;
			draw (boss, thePrinter. graphics);
			forget (thePrinter. graphics);
			closePostScript ();
		} else {
			thePrinter. graphics = Graphics_create_screenPrinter (NULL, (unsigned long) theMacPort);
			draw (boss, thePrinter. graphics);
			forget (thePrinter. graphics);
		}
	end:
		if (theMacPort) {
			PMSessionEndPage (theMacPrintSession);
			PMSessionEndDocument (theMacPrintSession);
			theMacPort = NULL;
		}
	#endif
	iferror return 0;
	return 1;
}