kashida

Get help using and writing Nisus Writer Pro macros.
User avatar
kamran
Posts: 15
Joined: 2009-06-16 09:48:02

kashida

Post by kamran »

I am looking for a way to auto insert kashida (tatweel) in frasi/arabic. Help.
User avatar
martin
Official Nisus Person
Posts: 5227
Joined: 2002-07-11 17:14:10
Location: San Diego, CA
Contact:

Re: kashida

Post by martin »

The macro code to insert a tatweel character (unicode code point U+0640) is:

Code: Select all

Type Text "ـ"
Or if you prefer:

Code: Select all

Type Text "\u0640"
User avatar
kamran
Posts: 15
Joined: 2009-06-16 09:48:02

Re: kashida

Post by kamran »

Thank you Martin and Hamid.

I guess I should have emphasized AUTO insertion. In the olden/classic days, there was a ruler macro (I think) that could be used to randomly insert kashida to balance the lines. I was/am hoping if someone has done something similar for Nisus Pro. Thanks.
User avatar
Hamid
Posts: 777
Joined: 2007-01-17 03:25:42

Re: kashida

Post by Hamid »

In NWE/NWP there is nothing which corresponds to Forced Justify Tab of NW Classic. This feature is crucial for justifying symmetrically two hemistichs of Arabic/Persian poetry on a single line.
I made this feature request a long time ago.

In the meantime you can try the Format:Kern:Loosen menu.
User avatar
kamran
Posts: 15
Joined: 2009-06-16 09:48:02

Re: kashida

Post by kamran »

Thanks, Hamid. May be it is time to learn perl :)
User avatar
martin
Official Nisus Person
Posts: 5227
Joined: 2002-07-11 17:14:10
Location: San Diego, CA
Contact:

Re: kashida

Post by martin »

Hamid is right, there's no way to automatically force kashidas for a single line. However, they should appear for justified text that has wrapped to the next line.
User avatar
kamran
Posts: 15
Joined: 2009-06-16 09:48:02

Re: kashida

Post by kamran »

But, Martin, if you wrap-justify poetry to next line, someone is bound to come looking for you with a hatchet!
User avatar
martin
Official Nisus Person
Posts: 5227
Joined: 2002-07-11 17:14:10
Location: San Diego, CA
Contact:

Re: kashida

Post by martin »

haha, sorry I wasn't thinking about your safety :P Consider me freshly educated.
User avatar
kamran
Posts: 15
Joined: 2009-06-16 09:48:02

Re: kashida

Post by kamran »

Now that I have dodged the hatchet...

I have no idea how nisus macros work or written - but this is what I would like to do:

for selected text,
(a) find maximum width of line from the ruler (between the margins or between two tabs) - in points?,
(b) for each line in selection (marked by tabs or paragraph mark at end) (1) find its length, (2) while insertion of a character (kashida) will not make the line wrap over, insert kashida at the first possible insertion point (kashida can only be inserted after certain characters), (3) then at the next possible insertion point, (4) loop over the line if necessary, (5) endwhile

Is that easy to do?
User avatar
martin
Official Nisus Person
Posts: 5227
Joined: 2002-07-11 17:14:10
Location: San Diego, CA
Contact:

Re: kashida

Post by martin »

There's definitely no way to do that now, though the idea is quite interesting. I'll file some enhancement requests that would allow the writing of such a macro, thanks.
User avatar
Hamid
Posts: 777
Joined: 2007-01-17 03:25:42

Re: kashida

Post by Hamid »

Here is an example to show how kerning, both Tighten and Loosen as appropriate, can be used to workaround this layout problem.
The following screenshot shows Layout 1 entered without kerning, and Layout 2 with kerning applied:
Attachments
kerning.png
kerning.png (26.08 KiB) Viewed 19902 times
User avatar
kamran
Posts: 15
Joined: 2009-06-16 09:48:02

Re: kashida

Post by kamran »

Thanks, Hamid.

Use of kerning is nice, but manual. In the similar vein, one could insert the Kashida manually as well - and that is what I currently do .

Martin:

Perhaps I was too ambitious :) . How about

For selected text

for each line delimited by a paragraph mark
if (line has not wrapped over)
(1) Move insertion point after the NEXT character in a <list of possible unicode ranges: u0628, u062a-e, 0633-a, etc.>
(2) If insertion point at the paragraph mark, move to the beginning of line and do (1)
(3) Insert "\u0640"
else
undo last Insert "\u0640"
endif
endfor
User avatar
martin
Official Nisus Person
Posts: 5227
Joined: 2002-07-11 17:14:10
Location: San Diego, CA
Contact:

Re: kashida

Post by martin »

Thanks for the more detailed list of steps, but the problem is checking whether or not the line has wrapped. There's currently no way for a macro to check that state. I'll file it as something we should add, thanks!
User avatar
kamran
Posts: 15
Joined: 2009-06-16 09:48:02

Re: kashida

Post by kamran »

No instant gratification? seriously, thanks for listening - let me know when it happens.
User avatar
martin
Official Nisus Person
Posts: 5227
Joined: 2002-07-11 17:14:10
Location: San Diego, CA
Contact:

Re: kashida

Post by martin »

It should now be possible to write such a macro using NWP 1.3. Here's one that does so for English text by inserting spaces between words. It always works on the last line of the current paragraph:

Code: Select all

$insertChar = " "
$insertAfterPattern = ' '
$clearPattern = ' {2,}'
$clearReplacement = ' '

# check to make sure we have a text selection with some text in it
$sel = TextSelection.active
If ! $sel
	Exit
End
$text = $sel.text
If 0 == $text.length
	Exit
End
$loc = $sel.location
If $loc >= $text.length
	$loc = $text.length - 1
End

# find last line in the paragraph
$paraRange = $text.rangeOfParagraphAtIndex($loc)
$lineRange = $paraRange
$nextAt = $paraRange.location
While $nextAt < $paraRange.bound
	$lineRange = $text.rangeOfLineAtIndex($nextAt)
	$nextAt = $lineRange.bound
End

# remove all insertions from the last time the macro was run
TextSelection.setActiveRange($lineRange)
Replace All $clearPattern, $clearReplacement, 'EsS'
$lineRange = $text.rangeOfLineAtIndex($lineRange.location)

# expand the line by inserting the character until the line wraps over
$lastInsertedRange = Range.new($lineRange.location, 0)
$expectedLineLen = $lineRange.length
While $lineRange.length == $expectedLineLen
	# find the next valid insertion location
	$scanRange = Range.newWithLocationAndBound($lastInsertedRange.bound, $lineRange.bound)
	TextSelection.setActiveRange($scanRange)
	$found = Find Next $insertAfterPattern, 'Es'
	If ! $found
		If $scanRange.location != $lineRange.location
			TextSelection.setActiveRange($lineRange)
			$found = Find Next $insertAfterPattern, 'Es'
		End
		If ! $found
			Die "No suitable place to insert the '$insertChar' character."
		End
	End
	
	# insert the character and adjust line info
	Select End
	Insert Text $insertChar
	$lastInsertedRange = TextSelection.activeRange
	$expectedLineLen += $insertChar.length
	$lineRange = $text.rangeOfLineAtIndex($lineRange.location)
End

# delete the insertion that pushed us over the edge of the line
$text.deleteInRange($lastInsertedRange)
For Arabic, you'd just want to change the top part. I don't know all the characters it's legal to insert a kashida after, so I've just used the few you gave me so far:

Code: Select all

$insertChar = "\u0640"
$insertAfterPattern = '[\u0628\u062a-\u062e\u0633-\u063a]'
$clearPattern = $insertChar
$clearReplacement = ''
If you let me know the rest of the Arabic characters, I'd like to add them and post the full macro in our repository. Thanks!
Post Reply