Redesigning word selection interface
[sgc2.git] / MainPage.praat
blob10302aa774926d53244ec68a18430c508c3c5a4d
2 # SpeakGoodChinese 2.0
3
4 # Praat script handling buttons page
6 #     SpeakGoodChinese: MainPage.praat loads the code needed for the 
7 #     main, practice, page of SGC2 and the sound handling and recognition.
8 #     
9 #     Copyright (C) 2007-2010  R.J.J.H. van Son and 2010 the Netherlands Cancer Institute
10 #     The SpeakGoodChinese team are:
11 #     Guangqin Chen, Zhonyan Chen, Stefan de Koning, Eveline van Hagen, 
12 #     Rob van Son, Dennis Vierkant, David Weenink
13
14 #     This program is free software; you can redistribute it and/or modify
15 #     it under the terms of the GNU General Public License as published by
16 #     the Free Software Foundation; either version 2 of the License, or
17 #     (at your option) any later version.
18
19 #     This program is distributed in the hope that it will be useful,
20 #     but WITHOUT ANY WARRANTY; without even the implied warranty of
21 #     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 #     GNU General Public License for more details.
23
24 #     You should have received a copy of the GNU General Public License
25 #     along with this program; if not, write to the Free Software
26 #     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
27
28 # Includes at the bottom
30 ###############################################################
32 # Button Drawing Routines
34 ###############################################################
36 procedure DrawPrevious .color$ .x .y .size
37         demo '.color$'
38         .size *= 2/3
39         .fraction = 0
40         if sgc.numberOfDisplayedWords > 0
41                 .fraction = sgc.currentWordNum/sgc.numberOfDisplayedWords
42         endif
43         call drawProgressTriangle -1 .x .y .size .fraction '.color$' Green
44         .currentX = drawProgressTriangle.currentX
45         .endX = .currentX - 0.5
46         .lowY = .y - .size
47         .highY = .y + .size
48         .displayColor$ = .color$
49         if sgc.currentWordNum >= sgc.numberOfDisplayedWords
50                 .displayColor$ = "Green"
51         endif
52         demo Paint rectangle... '.displayColor$' '.currentX' '.endX' '.lowY' '.highY'
53 endproc
55 procedure DrawNext .color$ .x .y .size
56         demo '.color$'
57         .size *= 2/3
58         .fraction = 0
59         if sgc.numberOfDisplayedWords > 0
60                 .fraction = sgc.currentWordNum/sgc.numberOfDisplayedWords
61         endif
62         call drawProgressTriangle 1 .x .y .size .fraction '.color$' Green
63         .currentX = drawProgressTriangle.currentX
64         .endX = .currentX + 0.5
65         .lowY = .y - .size
66         .highY = .y + .size
67         .displayColor$ = .color$
68         if sgc.currentWordNum >= sgc.numberOfDisplayedWords
69                 .displayColor$ = "Green"
70         endif
71         demo Paint rectangle... '.displayColor$' '.currentX' '.endX' '.lowY' '.highY'
72 endproc
74 procedure DrawSelectWords .color$ .x .y .size
75         .currentFontSize = 48
76         .y -= .size/2 + 0.5
77         .maxHeight = 2*.size
78         call adjustFontSizeOnHeight 'defaultFont$' '.currentFontSize' '.maxHeight'
79         .currentFontSize = adjustFontSizeOnHeight.currentFontSize
80         call set_font_size '.currentFontSize'
81         demo Colour... '.color$'
82         demo Text... '.x' Centre '.y' Bottom \bu\bu\bu
83         call set_font_size 'defaultFontSize'
84 endproc
86 procedure DrawWordListUp .color$ .x .y .size
87     .xleft = .x - .size
88     .xright = .x + .size
89     .xmidleft = .x + 0.1
90     .xmidright = .x - 0.1
91     .ylow = .y
92     .yhigh = .y + .size
93         demo '.color$'
94         demo Line width... 3
95         demo Draw line... .xleft .ylow .xmidleft .yhigh
96         demo Draw line... .xright .ylow .xmidright .yhigh
97         demo Line width... 'defaultLineWidth'
98         demo Black
99 endproc
101 procedure DrawWordListDown .color$ .x .y .size
102     .xleft = .x - .size
103     .xright = .x + .size
104     .xmidleft = .x + 0.1
105     .xmidright = .x - 0.1
106     .yhigh = .y + .size
107     .ylow = .y
108         demo '.color$'
109         demo Line width... 3
110         demo Draw line... .xleft .yhigh .xmidleft .ylow
111         demo Draw line... .xright .yhigh .xmidright .ylow
112         demo Line width... 'defaultLineWidth'
113         demo Black
114 endproc
116 procedure drawTriangle .direction .x .y .size
117         # Make sure direction = +/- 1
118         if .direction = 0
119                 .direction = 1 
120         endif
121         .direction /= abs(.direction)
122         
123         .offset = 0.01
124         .currentHeight = .size
125         .currentX = .x - .direction*.size
126         
127         demo Line width... 2.0
129         while .currentHeight> 0
130                 .ystart = .y + .currentHeight
131                 .yend = .y - .currentHeight
132                 demo Draw line... .currentX .ystart .currentX .yend
133                 .currentHeight -= .offset *3/4
134                 .currentX += .direction*.offset * 1.5
135         endwhile
136         demo Line width... 'defaultLineWidth'
137 endproc
139 procedure drawProgressTriangle .direction .x .y .size .fraction .color1$ .color2$
140         # Make sure direction = +/- 1
141         if .direction = 0
142                 .direction = 1 
143         endif
144         .direction /= abs(.direction)
145         
146         .offset = 0.01
147         .currentHeight = .size
148         .startX = .x - .direction*.size
149         .currentX = .startX
150         
151         demo Line width... 2.0
153         while .currentHeight> 0
154                 # Implement progress bar in .color2$
155                 if .direction*(.currentX - .startX)/.size  <= 2*.fraction
156                         demo '.color2$'
157                 else
158                         demo '.color1$'
159                 endif
160                 
161                 .ystart = .y + .currentHeight
162                 .yend = .y - .currentHeight
163                 demo Draw line... .currentX .ystart .currentX .yend
164                 .currentHeight -= .offset *3/4
165                 .currentX += .direction*.offset * 1.5
166         endwhile
167         demo Line width... 'defaultLineWidth'
168         demo '.color1$'
169 endproc
171 ###############################################################
173 # Obligatory button Drawing Routines
175 # These MUST be defined
177 ###############################################################
179 procedure DrawRecord .color$ .x .y .size
180         .size /= 2
181     demo Paint circle... '.color$' '.x' '.y' '.size'
182 endproc
184 procedure DrawPlay .color$ .x .y .size
185         demo '.color$'
186         call drawTriangle 1 .x .y .size
187 endproc
189 procedure DrawQuit .color$ .x .y .size
190         demo Colour... '.color$'
191         .lineWidth = 0.5*.size**2
192         demo Line width... '.lineWidth'
193         .xstart = .x - .size
194         .ystart = .y + .size
195         .xend = .x + .size
196         .yend = .y - .size
197         demo Draw line... .xstart .ystart .xend .yend
198         .xstart = .x - .size
199         .ystart = .y - .size
200         .xend = .x + .size
201         .yend = .y + .size
202         demo Draw line... .xstart .ystart .xend .yend
203         demo Line width... 'defaultLineWidth'
204         demo Colour... Black
205 endproc
207 procedure DrawConfig .color$ .x .y .size
208         .size *= 1
209         .lineWidth = 0.4*.size
210         demo Arrow size... '.lineWidth'
211         .lineWidth = 0.4*.size**2
212         demo Line width... '.lineWidth'
213         .y += .size/2
214         .xstart = .x - .size
215         .xend = .x + .size
216         demo Draw arrow... .xstart .y .xend .y
217         demo Line width... 'defaultLineWidth'
218 endproc
220 procedure DrawRefresh .color$ .x .y .size
221         .lineWidth = 0.5*.size**2
222         .size /= 2
223         demo Line width... '.lineWidth'
224         demo Draw arc... '.x' '.y' '.size' 0 270
225         demo Line width... 'defaultLineWidth'
226 endproc
228 ###############################################################
230 # Button Processing Routines
232 ###############################################################
234 procedure processMainPageExample .clickX .clickY .pressed$
235         call generate_example
236 endproc
238 procedure processMainPagePrevious .clickX .clickY .pressed$
239         call clean_up_sound
240         call display_text Grey
241         call previous_word
242         # Draw the contour
243         call wipeArea 'wipeFeedbackArea$'
244         call init_window
245         call display_text Black
246         
247         sgc.failedAttempts = 0
248 endproc
250 procedure processMainPageNext .clickX .clickY .pressed$
251         call clean_up_sound
252         call display_text Grey
253         call next_word
254         call wipeArea 'wipeFeedbackArea$'
255         call init_window
256         # Draw the contour
257         call display_text Black
258 endproc
260 procedure processMainPageWordlistUp .clickX .clickY .pressed$
261         call wipeArea 'wipeFeedbackArea$'
262     call load_word_list "'localWordlistDir$'" -1
263         call init_window
264         call display_text Black
265 endproc
267 procedure processMainPageWordlistDown .clickX .clickY .pressed$
268         call wipeArea 'wipeFeedbackArea$'
269     call load_word_list "'localWordlistDir$'" 1
270         call init_window
271         call display_text Black
272 endproc
274 procedure processMainPageGRADE .clickX .clickY .pressed$
275         call setGrade '.pressed$'
276         # Redraw window
277         call init_window
278 endproc
280 procedure processMainPagePinYinArea .clickX .clickY .pressed$
281         # Redraw window
282         sgc.writeAll = 1
283         call display_text Red
284         sgc.writeAll = 0
285 endproc
287 # Select the words to practise. This is quite a complex piece of code
288 procedure processMainPageSelectWords .clickX .clickY .pressed$
289         .table$ = "MainPage"
290         .label$ = "SelectWords"
291     call Draw_button '.table$' '.label$' 1
293         # Panick button! No full UTF langauge is supported!
294         if config.language$ = "JA" or config.language$ = "ZH"
295                 beginPause: "WARNING: Language not supported!"
296                         comment: "This function is currently not available for your language"
297                         comment: "Please, switch to English if you need this function"
298                         comment: "We are very sorry and hope to enable your language soon"
299                 endPause: "Continue", 1
300                 goto SELECTWORDSFAIL
301         endif
302         
303         # Get help text
304         call findLabel '.table$' '.label$'
305         .row = findLabel.row
306         select Table '.table$'
307         .helpText$ = Get value... '.row' Helptext
308         call convert_praat_to_latin1 '.helpText$'
309         .helpText$ = convert_praat_to_latin1.text$
310    
311     # Implement Cancel
312     select sgc.currentWordlist
313     .tmpOriginalWordlist = Copy: "Original_'wordlist$'"
315         # Remove current list from All wordlists table
316         select sgc.allWordLists
317         .rowNum = Search column: "Name", wordlistName$
318         if .rowNum > 0
319                 .numRows = Get number of rows
320                 if .numRows > 1
321                         Remove row: .rowNum
322                 else
323                         Set string value: 1, "Name", "---"
324                 endif
325         endif
326     
327     # Set current word
328         select sgc.currentWordlist
329         sgc.numberOfWords = Get number of rows
330     .currentWord = sgc.currentWord
331     if .currentWord <= 0 or .currentWord > sgc.numberOfWords or config.shuffleLists
332                 .currentWord = 1
333         endif
334     
335         # The texts
336         call get_feedback_text 'config.language$' AddWordlist
337         call convert_praat_to_latin1 'get_feedback_text.text$'
338         .wordlistText$ = convert_praat_to_latin1.text$
339         call get_feedback_text 'config.language$' Part
340         call convert_praat_to_latin1 'get_feedback_text.text$'
341         .partText$ = convert_praat_to_latin1.text$
342         call get_feedback_text 'config.language$' Tones
343         call convert_praat_to_latin1 'get_feedback_text.text$'
344         .toneText$ = convert_praat_to_latin1.text$
345         call get_feedback_text 'config.language$' Cancel
346         call convert_praat_to_latin1 'get_feedback_text.text$'
347         .cancelText$ = convert_praat_to_latin1.text$
348         call get_feedback_text 'config.language$' Clear
349         call convert_praat_to_latin1 'get_feedback_text.text$'
350         .clearText$ = convert_praat_to_latin1.text$
351         call get_feedback_text 'config.language$' All
352         call convert_praat_to_latin1 'get_feedback_text.text$'
353         .allText$ = convert_praat_to_latin1.text$
354         call get_feedback_text 'config.language$' Apply
355         call convert_praat_to_latin1 'get_feedback_text.text$'
356         .applySelection$ = convert_praat_to_latin1.text$
357         call get_feedback_text 'config.language$' Next
358         call convert_praat_to_latin1 'get_feedback_text.text$'
359         .nextWord$ = convert_praat_to_latin1.text$
360         call get_feedback_text 'config.language$' Continue
361         call convert_praat_to_latin1 'get_feedback_text.text$'
362         .continueText$ = convert_praat_to_latin1.text$
363         call get_feedback_text 'config.language$' Show
364         call convert_praat_to_latin1 'get_feedback_text.text$'
365         .showText$ = convert_praat_to_latin1.text$
367         call get_evaluation_text 'config.language$' Pinyin
368         .pinyinText$ = get_evaluation_text.text$
369         
370         call get_evaluation_text 'config.language$' Character
371         .characterText$ = get_evaluation_text.text$
372         
373         call get_evaluation_text 'config.language$' Example
374         .exampleText$ = get_evaluation_text.text$
375         
376         call get_evaluation_text 'config.language$' Translation
377         .translationText$ = get_evaluation_text.text$
378         
379         call get_evaluation_text 'config.language$' ManualEntry
380         .manualEntryText$ = get_evaluation_text.text$
381         
382         # Get lesson names
383         select sgc.currentWordlist
384         .lessonCol = Get column index: "Lesson"
385         if .lessonCol <= 0
386                 Append column: "Lesson"
387                 .lessonCol = Get column index: "Lesson"
388                 .numRows = Get number of rows
389                 for .w to .numRows
390                         Set string value: .w, "Lesson", "-"
391                 endfor
392         endif
393         .lessonList$ = tab$
394         .numLessons = 0
395         .lessonName$ = ""
396         # All shown keeps track whether all words are shown
397         # If so, selecting a lesson is preceded by a Clear All
398         .allShown = 0
399         # Sort words for consistent selection interface
400         if config.shuffleLists
401                 # Allow subdivision in lessons
402                 if .lessonCol > 0
403                         Sort rows... Lesson Pinyin
404                 else
405                         Sort rows... Pinyin
406                 endif
407         endif           
408         if .lessonCol > 0
409                 for .i to sgc.numberOfWords
410                         .currentLesson$ = Get value: .i, "Lesson"
411                         .matchLesson$ = tab$+.currentLesson$+tab$
412                         if .currentLesson$ <> "" and .currentLesson$ <> "-" and .currentLesson$ <> "?" and index(.lessonList$, .matchLesson$) <= 0
413                                 .lessonList$ = .lessonList$ + .currentLesson$ + tab$
414                                 .numLessons += 1
415                                 .lessonName$['.numLessons'] = .currentLesson$
416                         endif
417                         .shown$ = Get value: .i, "Show"
418                         if .shown$ = "-"
419                                 .allShown = 0
420                         endif
421                 endfor
422         endif
423         
424         clicked = -1
425         .numWordsPerScreen = 15
426         while clicked <> 6 and clicked <> 1
427                 .lessonSelected = -1
428                 .toneSelected = -1
429                 .firstShown = -1
430                 
431                 select sgc.currentWordlist
432                 .lessonCol = Get column index: "Lesson"
433                 # Sort words for consistent selection interface
434         if config.shuffleLists
435                         # Allow subdivision in lessons
436                         if .numLessons > 1
437                                 Sort rows... Lesson Pinyin
438                         else
439                                 Sort rows... Pinyin
440                         endif
441         endif           
442                 .max = .numWordsPerScreen - 1
443                 if .currentWord + .max > sgc.numberOfWords
444                         .max = sgc.numberOfWords - .currentWord
445                 endif
446                 for .i from 0 to .numWordsPerScreen - 1
447                         if .i <= .max
448                                 .currentPinyin$ = Get value: .currentWord+.i, "Pinyin"
449                                 if index_regex(.currentPinyin$, "[0-9]") <= 0
450                                         call pinyin2numbers '.currentPinyin$'
451                                         .currentPinyin$ = replace_regex$(pinyin2numbers.intermediatePinyin$, ".+", "\l&", 0)
452                                         .currentPinyin$ = replace_regex$(.currentPinyin$, "[^a-zA-Z0-9]", "", 0)
453                                 endif
454                                 .pinyin$[.i] = .currentPinyin$
456                                 .character$[.i] = Get value: .currentWord+.i, "Character"
457                                 .lessonNum$[.i] = ""
458                                 if .numLessons > 1
459                                         .lessonNum$[.i] = Get value: .currentWord+.i, "Lesson"
460                                         .lessonNum$[.i] = " : " + .lessonNum$[.i]
461                                 endif
462                                 .showText$[.i] = .pinyin$['.i']
463                                 if .character$['.i'] <> "-"
464                                         .showText$[.i] = .pinyin$['.i']+" ("+.character$['.i']+.lessonNum$['.i']+")"
465                                 elsif .lessonNum$['.i'] <> ""
466                                         .showText$[.i] = .pinyin$['.i']+" ( -"+.lessonNum$['.i']+")"
467                                 endif
468                                 .showValueText$[.i] = Get value: .currentWord+.i, "Show"
469                                 if .showValueText$[.i] = "-"
470                                         .showValue[.i] = 0
471                                 else
472                                         .showValue[.i] = 1
473                                 endif
474                                 .showVariable$[.i] = .pinyin$[.i]
475                                 # This prevents some nasty attempts to use language elements as variables
476                                 if index_regex(.showVariable$[.i], "[^0-9r]$") or index_regex(.showVariable$[.i], "[0-9]") <= 0 
477                                         .showVariable$[.i] = .pinyin$[.i]+"0"
478                                 endif
479                                 .tmp$ = replace_regex$(.showVariable$[.i], "^(.+)$", "\l\1", 0)
480                                 .tmp$ = replace_regex$(.tmp$, "[^\w]", "_", 0)
481                                 '.tmp$' = .showValue[.i]
482                         else
483                                 .showText$[.i] = "-"
484                                 .showValue[.i] = 0
485                         endif
486                 endfor
488                 # The user text input window (beginPause .... endPause)
489                 beginPause(.helpText$)
490                         if sgc.allWordLists > 0
491                                 select sgc.allWordLists
492                                 .numWordlists = Get number of rows
493                                 optionMenu: .wordlistText$, 1
494                                         option: "---"
495                                         for .w to .numWordlists
496                                                 select sgc.allWordLists
497                                                 .wordListName$ = Get value: .w, "Name"
498                                                 option: .wordListName$
499                                         endfor
500                                         option: "*"+.manualEntryText$+"*"
501                         endif
502                         
503                         boolean (.showText$[0], .showValue[0])
504                         boolean (.showText$[1], .showValue[1])
505                         boolean (.showText$[2], .showValue[2])
506                         boolean (.showText$[3], .showValue[3])
507                         boolean (.showText$[4], .showValue[4])
508                         boolean (.showText$[5], .showValue[5])
509                         boolean (.showText$[6], .showValue[6])
510                         boolean (.showText$[7], .showValue[7])
511                         boolean (.showText$[8], .showValue[8])
512                         boolean (.showText$[9], .showValue[9])
513                         boolean (.showText$[10], .showValue[10])
514                         boolean (.showText$[11], .showValue[11])
515                         boolean (.showText$[12], .showValue[12])
516                         boolean (.showText$[13], .showValue[13])
517                         boolean (.showText$[14], .showValue[14])
518                         
519                         .selectMenu$ = .toneText$
520                         if .numLessons > 0
521                                 .selectMenu$ = .selectMenu$ + " " + .partText$
522                         endif
523                         optionMenu: .selectMenu$, 1
524                                 option: .toneText$
525                                 option: "0"
526                                 option: "1"
527                                 option: "2"
528                                 option: "3"
529                                 option: "4"
530                         
531                         # Display Lesson text if available
532                         if .numLessons > 0
533                                 option: "---"
534                                 .j = 0
535                                 for .j to .numLessons
536                                         option: .partText$+": "+.lessonName$['.j']
537                                 endfor
538                         endif
539                 clicked = endPause ("'.cancelText$'", "'.clearText$'", "'.allText$'", "'.applySelection$'", "'.nextWord$'", "'.continueText$'", 6, 1)
540                 
541                 select sgc.currentWordlist
542                 if clicked = 2
543                         for .i to sgc.numberOfWords
544                                 Set string value: .i, "Show", "-"
545                         endfor
546                         .allShown = 0
547                 elsif clicked = 3
548                         for .i to sgc.numberOfWords
549                                 Set string value: .i, "Show", "+"
550                         endfor
551                         .allShown = 1
552                 elsif clicked != 1
553                         # Handle added word lists
554                         .wordlistText$ = replace_regex$(.wordlistText$, "^(.)", "\l\1", 0)
555                         .wordlistText$ = replace_regex$(.wordlistText$, "[^\w]", "_", 0)
556                         .tmp$ = '.wordlistText$'$
557                         if .tmp$ <> "---" and sgc.allWordLists > 0
558                                 select sgc.currentWordlist
559                                 # Add current wordlist name as  a lesson name
560                                 .originalWordList = -1
561                                 .numRows = Get number of rows
562                                 for .w to .numRows
563                                         select sgc.currentWordlist
564                                         .currentLesson$ = Get value: .w, "Lesson"
565                                         if .currentLesson$ = "" or .currentLesson$ = "-"
566                                                 Set string value: .w, "Lesson", wordlist$
567                                         endif
568                                 endfor
569                                 
570                                 # Get and merge the selected list
571                                 # Enter words by hand
572                                 if .tmp$ = "*"+.manualEntryText$+"*"
573                                         .man_clicked = 3
574                                         .currentFilePath$ = .exampleText$
575                                         .manualText$ = .manualEntryText$
576                                         .manPinyin$ = .pinyinText$
577                                         .manCharacter$ = .characterText$
578                                         .manTranslation$ = .translationText$
579                                         .manSound$ = .currentFilePath$
580                                         .manLesson$ = .manualText$
581                                         while .man_clicked > 1
582                                                 beginPause: .manualEntryText$
583                                                         text: .pinyinText$, .manPinyin$
584                                                         text: .characterText$, .manCharacter$ 
585                                                         text: .translationText$, .manTranslation$ 
586                                                         text: .exampleText$, .manSound$
587                                                         text: .manualText$, .manualText$
588                                                 .man_clicked = endPause("'.cancelText$'", "'.exampleText$'", "'.continueText$'", 3, 1)
589                                                 if .man_clicked > 1
590                                                         .tmp$ = replace_regex$(.pinyinText$, "[^\w]", "_", 0)
591                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
592                                                         if '.tmp$'$ <> .pinyinText$ 
593                                                                 .manPinyin$ = '.tmp$'$
594                                                         else
595                                                                 # Quit
596                                                                 .man_clicked = 0
597                                                         endif
599                                                         .tmp$ = replace_regex$(.characterText$, "[^\w]", "_", 0)
600                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
601                                                         if '.tmp$'$ <> .characterText$ 
602                                                                 .manCharacter$ = '.tmp$'$
603                                                         else
604                                                                 .manCharacter$ = ""
605                                                         endif
606                                                         
607                                                         .tmp$ = replace_regex$(.translationText$, "[^\w]", "_", 0)
608                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
609                                                         if '.tmp$'$ <> .translationText$ 
610                                                                 .manTranslation$ = '.tmp$'$
611                                                         else
612                                                                 .manTranslation$ = ""
613                                                         endif
614                                                         
615                                                         .tmp$ = replace_regex$(.exampleText$, "[^\w]", "_", 0)
616                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
617                                                         if '.tmp$'$ <> .characterText$ and '.tmp$'$ <> ""
618                                                                 .manSound$ = '.tmp$'$
619                                                         endif
620                                                         
621                                                         .tmp$ = replace_regex$(.manualText$, "[^\w]", "_", 0)
622                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
623                                                         .manLesson$ = '.tmp$'$
624                                                         
625                                                         if .man_clicked = 2
626                                                                 .manSound$ = chooseReadFile$(.exampleText$);
627                                                         elsif .man_clicked = 3
628                                                                 # Clean up input string
629                                                                 .manPinyin$ = replace_regex$(.manPinyin$, "^[^a-z]+", "", 0)
630                                                                 .manPinyin$ = replace_regex$(.manPinyin$, "[^\w']", "", 0)
631                                                                 
632                                                                 select sgc.currentWordlist
633                                                                 Append row
634                                                                 .numRows = Get number of rows
635                                                                 if .manPinyin$ <> ""
636                                                                         Set string value: .numRows, "Pinyin", .manPinyin$
637                                                                         Set string value: .numRows, "Character", .manCharacter$
638                                                                         Set string value: .numRows, "Translation", .manTranslation$
639                                                                         Set string value: .numRows, "Sound", .manSound$
640                                                                         Set string value: .numRows, "Lesson", .manLesson$
641                                                                         Set string value: .numRows, "Show", "+"
642                                                                 endif
643                                                                 .manualText$ = .manualEntryText$
644                                                                 .manPinyin$ = .pinyinText$
645                                                                 .manCharacter$ = .characterText$
646                                                                 .manTranslation$ = .translationText$
647                                                                 .manSound$ = .currentFilePath$
648                                                                 .manLesson$ = .manualText$                                                      
649                                                         endif
650                                                 endif
651                                         endwhile                                        
652                                 else
653                                         # Existing lessons
654                                         select sgc.allWordLists
655                                         .wordlistNum = Search column: "Name", .tmp$
656                                         if .wordlistNum > 0
657                                                 .wordlistPath$ = Get value: .wordlistNum, "Directory"
658                                                 .wordlistPath$ = replace_regex$(.wordlistPath$, "[ ]", "&", 0)
659                                                 call read_wordlist "'.tmp$'" '.wordlistPath$'
660                                                 .newList = read_wordlist.wordlistID
661                                                 call merge_into_wordlist '.newList' '.tmp$'
662                                                 select .newList
663                                                 Remove
664                                                 # Add wordlistname to Lesson column
665                                                 select sgc.allWordLists
666                                                 .numRows = Get number of rows
667                                                 if .numRows > 1
668                                                         Remove row: .wordlistNum
669                                                 else
670                                                         Set string value: 1, "Name", "---"
671                                                 endif
672                                         endif
673                                 endif
674                                 # Gather Lesson names
675                                 select sgc.currentWordlist
676                                 Sort rows... Lesson Pinyin
677                                 if .lessonCol > 0
678                                         sgc.numberOfWords = Get number of rows
679                                         .lessonList$ = tab$
680                                         .numLessons = 0
681                                         .lessonName$ = ""
682                                         for .i to sgc.numberOfWords
683                                                 .currentLesson$ = Get value: .i, "Lesson"
684                                                 .matchLesson$ = tab$+.currentLesson$+tab$
685                                                 if .currentLesson$ <> "" and .currentLesson$ <> "-" and .currentLesson$ <> "?" and index(.lessonList$, .matchLesson$) <= 0
686                                                         .lessonList$ = .lessonList$ + .currentLesson$ + tab$
687                                                         .numLessons += 1
688                                                         .lessonName$['.numLessons'] = .currentLesson$
689                                                 endif
690                                                 .shown$ = Get value: .i, "Show"
691                                                 if .shown$ = "-"
692                                                         .allShown = 0
693                                                 endif
694                                         endfor
695                                 endif
696                         else                    
697                                 for .i from 0 to .max
698                                         .tmp$ = replace_regex$(.showVariable$['.i'], "^(.*)$", "\l\1", 0)
699                                         .tmp$ = replace_regex$(.tmp$, "[^\w]", "_", 0)
700                                         
701                                         .showValue['.i'] = '.tmp$'
702                                         .showWord$['.i'] = "-"
703                                         if .showValue['.i'] <> 0
704                                                 .showWord$['.i'] = "+"
705                                         endif
706                                         Set string value: .currentWord+.i, "Show", .showWord$['.i']
707                                 endfor
708                         endif
709                         
710                         select sgc.currentWordlist
711                         .tmp$ = replace_regex$(.selectMenu$, "^(.)", "\l\1", 0)
712                         .tmp$ = replace_regex$(.tmp$, "[^\w]", "_", 0)
713                         .toneSelected = '.tmp$' - 2
714                         if .toneSelected >= 0 and .toneSelected < 5
715                                 select sgc.currentWordlist
716                                 for .i to sgc.numberOfWords
717                                         .currentPinyin$ = Get value: .i, "Pinyin"
718                                         if index_regex(.currentPinyin$, "[0-9]") <= 0
719                                                 call pinyin2numbers '.currentPinyin$'
720                                                 .currentPinyin$ = replace_regex$(pinyin2numbers.intermediatePinyin$, ".+", "\l&", 0)
721                                                 .currentPinyin$ = replace_regex$(.currentPinyin$, "[^a-zA-Z0-9]", "", 0)
722                                         endif
723                                         .tmp$ = Get value: .i, "Show"
724                                         if .tmp$ <> "-" and index(.currentPinyin$, "'.toneSelected'") > 0
725                                                 Set string value: .i, "Show", "+"
726                                         else
727                                                 Set string value: .i, "Show", "-"
728                                                 .allShown = 0
729                                         endif
730                                 endfor
731                         elsif .toneSelected > 5
732                                 # .toneSelected = 5 is the Part text
733                                 .lessonSelected = .toneSelected - 5
734                                 if .lessonSelected > 0
735                                         .allShown = 1
736                                         .firstShown = -1
737                                         select sgc.currentWordlist
738                                         for .i to sgc.numberOfWords
739                                                 # Keep track of whether all are shown
740                                                 .shown$ = Get value: .i, "Show"
741                                                 if .shown$ = "-"
742                                                         .allShown = 0
743                                                 endif
744                                         endfor
746                                         for .i to sgc.numberOfWords
747                                                 # Lessons
748                                                 .currentLesson$ = Get value: .i, "Lesson"
749                                                 if .currentLesson$ = .lessonName$['.lessonSelected']
750                                                         Set string value: .i, "Show", "+"
751                                                 elsif .allShown = 1
752                                                         Set string value: .i, "Show", "-"
753                                                 endif
754                                         endfor
755                                         for .i to sgc.numberOfWords
756                                                 # Keep track of whether all are shown
757                                                 .shown$ = Get value: .i, "Show"
758                                                 if .firstShown <=0 and .shown$ <> "-"
759                                                         .firstShown = .i
760                                                 endif
761                                         endfor
762                                 endif
763                         endif
764                         
765                         if clicked = 4
766                                 if .currentWord <= 0
767                                         .currentWord = (sgc.numberOfWords div .numWordsPerScreen) * .numWordsPerScreen + 1
768                                 endif
769                         elsif clicked = 5
770                                 if .firstShown > 0
771                                         .currentWord = (.firstShown div .numWordsPerScreen) * .numWordsPerScreen + 1
772                                 endif
773                                 .currentWord += .numWordsPerScreen
774                                 if .currentWord > sgc.numberOfWords
775                                         .currentWord = 1
776                                 endif
777                         endif
778                 endif
779                 # Reset and go to the first selected word (can shuffle list)
780                 if clicked = 6
781                         sgc.currentWord = -1
782                         call next_word
783                         call init_window
784                 endif
785         endwhile
786         
787     # Implement Cancel
788     if clicked = 1
789                 select sgc.currentWordlist
790                 Remove
791                 select .tmpOriginalWordlist
792                 Copy: wordlist$
793                 sgc.currentWordlist = selected()
794         else
795                 # Set the values of the number of words shown   
796                 select sgc.currentWordlist
797                 .numWords = Get number of rows
798                 sgc.currentWordNum = 1
799                 sgc.numberOfDisplayedWords = 0
800                 sgc.currentWord = 0
801                 for .i to .numWords
802                         .show$ = Get value: .i, "Show"
803                         if .show$ = "+"
804                                 if sgc.currentWord < 1
805                                         sgc.currentWord = .i
806                                 endif
807                                 sgc.numberOfDisplayedWords += 1
808                         endif
809                 endfor
810         endif
811         select .tmpOriginalWordlist
812         Remove
814         label SELECTWORDSFAIL
815         
816     call Draw_button '.table$' '.label$' 0
817 endproc
819 ###############################################################
821 # Obligatory button Processing Routines
823 # These MUST be defined
825 ###############################################################
827 procedure processMainPageQuit .clickX .clickY .pressed$
828         call end_program
829 endproc
831 procedure processMainPageRefresh .clickX .clickY .pressed$
832         call clean_up_sound
833         call init_window
834 endproc
836 procedure processMainPageConfig .clickX .clickY .pressed$
837         call config_page
838 endproc
840 procedure processMainPageHelp .clickX .clickY .pressed$
841         call help_loop 'buttons$' init_window
842 endproc
844 procedure processMainPagePlay .clickX .clickY .pressed$
845         .table$ = "MainPage"
846         .label$ = "Play"
847         if recordedSound$ <> ""
848                 call play_sound 'sgc.recordedSound'
849                 mainPage.play = 0
850         endif
851         te.buttonPressValue = mainPage.play
852 endproc
854 procedure Set_Play_Button
855         mainPage.play = -1
856         if recordedSound$ <> ""
857                 mainPage.play = 0
858     endif       
859         call Draw_button MainPage Play 'mainPage.play'
860 endproc
862 procedure processMainPageRecord .clickX .clickY .pressed$
863         call count_syllables
864         .recordingTime = recordingTime
865         if count_syllables.number > 2
866                 .recordingTime = recordingTime + 1.0*ceiling((count_syllables.number - 2)/2)
867         endif
868     call record_sound '.recordingTime'
869     call recognizeTone
870         mainPage.play = 0
871         call Set_Play_Button
873     # Wipe screen
874     call wipeArea 'wipeContourArea$'
875    
876     call draw_tone_contour
877     # Write text (again)
878     call display_word_list_name
879     call display_text Black
880         call add_feedback_to_toneevaluation Feedback
881     call write_feedback Feedback
882         select Table Feedback
883         Remove
884         
885         # Do not exercise words that are going well (autoSelect)
886     if add_feedback_to_toneevaluation.result > 0
887                 if config.adaptiveLists > 0 and sgc.failedAttempts < 2
888                         # Deselect current word
889                         select sgc.currentWordlist
890                         .i = Search column: "Pinyin", sgc.pinyin$
891                         if .i > 0
892                                 Set string value: .i, "Show", "-"
893                         endif
894                 endif
895                 sgc.failedAttempts = 0
896     else
897                 sgc.failedAttempts += 1
898     endif
899 endproc
902 ###############################################################
904 # Miscelaneous supporting code
906 ###############################################################
908 # The example
909 procedure generate_example
910         select sgc.currentWordlist
911         if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
912                 select sgc.currentWordlist
913                 .sound$ = Get value... 'sgc.currentWord' Sound
914                 call readPinyin 'sgc.currentWord'
915                 sgc.pinyin$ = readPinyin.pinyin$
916                 sgc.character$ = readPinyin.character$
917                 if .sound$ = "-" or .sound$ = ""
918                         .sound$ = sgc.pinyin$+".wav"
919                 endif
920                 if index_regex(.sound$, "^(/|~/|[A-Z]:\\)") > 0
921                         .soundFilePath$ = .sound$
922                 else
923                         .soundFilePath$ = localWordlistDir$+"/"+wordlistName$+"/"+.sound$
924                         .wordlistDirectory$ = ""
925                         if localWordlistDir$ <> "" and fileReadable("'localWordlistDir$'/'wordlistName$'")
926                                 .wordlistDirectory$ = "'localWordlistDir$'/'wordlistName$'"
927                         elsif sgc2wordlists$ <> "" and fileReadable("'sgc2wordlists$'/'wordlistName$'")
928                                 .wordlistDirectory$ = "'sgc2wordlists$'/'wordlistName$'"
929                         elsif globalwordlists$ <> "" and fileReadable("'globalwordlists$'/'wordlistName$'")
930                                 .wordlistDirectory$ = "'globalwordlists$'/'wordlistName$'"
931                         endif
932                         if .wordlistDirectory$ <> ""
933                                 .audioExampleList = Create Strings as file list... AudioList '.wordlistDirectory$'/'sgc.pinyin$'.*
934                                 .number_of_examples = Get number of strings
935                                 if .number_of_examples > 0
936                                         Randomize
937                                         .sound$ = Get string... 1
938                                         .soundFilePath$ = "'.wordlistDirectory$'/'.sound$'"
939                                 endif
940                                 Remove
941                         endif
942                 endif
943                 if fileReadable(.soundFilePath$) and config.useSoundExample
944                         .tmp = -1
945                         .tmp = nocheck Read from file... '.soundFilePath$'
946                         if .tmp != undefined and .tmp > 0
947                                 call play_sound '.tmp'
948                                 select .tmp
949                                 Remove
950                         endif
951                 elsif config.synthesis$ <> "" and config.synthesis$ <> "_DISABLED_"
952                         call synthesize_sound "'sgc.pinyin$'" "'sgc.character$'"
953                 else
954                         call humToneContour 'sgc.pinyin$' 'config.register'
955                         call reset_viewport
956                 endif
957         endif
958         demoShow()
959 endproc
961 # Draw a tone contour
962 procedure draw_tone_contour
963         select sgc.currentWordlist
964         if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
965                 .sound$ = Get value... 'sgc.currentWord' Sound
966                 call readPinyin 'sgc.currentWord'
967                 sgc.pinyin$ = readPinyin.pinyin$
968                 sgc.character$ = readPinyin.character$
969                 call drawToneContour 'sgc.pinyin$' 'config.register'
970                 call reset_viewport
971                 
972                 if te.recordedPitch > 0
973                         call drawSourceToneContour te.recordedPitch
974                 endif
975         endif
977 endproc
979 procedure recognizeTone
980         select sgc.currentWordlist
981         if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
982                 .strict = 0
983                 if index_regex(config.strict$, "[^0-9]") <= 0
984                         .strict = ('config.strict$' >= sgc.highestLevel)
985                 endif
986                         
987                 .sound$ = Get value... 'sgc.currentWord' Sound
988                 call readPinyin 'sgc.currentWord'
989                 sgc.pinyin$ = readPinyin.pinyin$
990                 sgc.character$ = readPinyin.character$
991                 call align_recordedSound 'sgc.pinyin$'
992         call sgc_ToneProt 'recordedSound$' 'sgc.pinyin$' 'config.register' '.strict' 'config.language$'
993         # sgc_ToneProt manipulates the sound given. Reconnect
994         select Sound 'recordedSound$'
995         sgc.recordedSound = selected("Sound")
996                 call reset_viewport
997         endif
998 endproc
1000 procedure write_feedback .table$
1001     select Table '.table$'
1002     .line1$ = Get value... 1 Text
1003     .line2$ = Get value... 2 Text
1004     .label$ = Get value... 3 Text
1006         # convert numbers to Pinyin if needed
1007         if not config.displayNumbers
1008                 call numbers2pinyin '.line1$'
1009                 .line1$ = numbers2pinyin.pinyin$
1010         endif
1012     .color$ = "Red"
1013     if index(.line1$, "???") > 0
1014         .color$ = "Black"
1015     elsif .label$ = "Correct"
1016         .color$ = "Green"
1017         elsif config.strict$ = "'sgc.highestLevel'"
1018                 .line2$ = .line2$ + " *"
1019     endif
1021         .currentFeedbackFontSize = 14
1022         .maxHeight = 21 - 17
1023         call adjustFontSizeOnHeight 'defaultFont$' '.currentFeedbackFontSize' '.maxHeight'
1024         .currentFeedbackFontSize = adjustFontSizeOnHeight.newFontSize
1025         
1026         call wipeArea 'wipeFeedbackArea$'
1027     call set_font_size '.currentFeedbackFontSize'
1028     demo '.color$'
1029     demo Text... 50 Centre 21 Bottom '.line1$'
1030     demo Text... 50 Centre 17 Bottom '.line2$'
1031         demoShow()
1032         demo 'defaultFont$'
1033     call set_font_size 'defaultFontSize'
1034 endproc
1036 # Text display
1037 procedure display_text .color$
1038         select sgc.currentWordlist
1039         if sgc.currentWord < 0 or sgc.currentWord > sgc.numberOfWords+1
1040                 call clean_up_sound
1041         if config.shuffleLists
1042                     Randomize rows
1043         endif
1044                 if sgc.currentWord < 0
1045                         sgc.currentWord = sgc.numberOfWords
1046                 else
1047                         sgc.currentWord = 1
1048                 endif
1049         endif
1050         
1051         .changeCJKstyle = 0
1052         if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
1053                 .displayText$ = ""
1054                 call readDisplayPinyin 'sgc.currentWord'
1055                 .displayPinyin$ = readDisplayPinyin.pinyin$
1056                 .displayChar$ = Get value... 'sgc.currentWord' Character
1057                 .displayTrans$ = Get value... 'sgc.currentWord' Translation
1058                 if .displayPinyin$ <> "-" and (config.displayPinyin or sgc.writeAll)
1059                         if not config.displayNumbers
1060                                 call numbers2pinyin '.displayPinyin$'
1061                                 .displayPinyin$ = numbers2pinyin.pinyin$
1062                         endif
1063                         # Insert u umlaut
1064                         .displayPinyin$ = replace_regex$(.displayPinyin$, "v", "\\u\X22", 0)
1065                         .displayText$ = .displayText$ + .displayPinyin$
1066                 endif
1067                 if .displayChar$ <> "-" and (config.displayChar or sgc.writeAll)
1068                         .displayText$ = .displayText$ + "  "+ .displayChar$
1069                         .changeCJKstyle = 1
1070                 endif
1071                 if .displayTrans$ <> "-" and (config.displayTrans or sgc.writeAll)
1072                         .displayText$ = .displayText$ + "  \s{%%"+ .displayTrans$ + "%}"
1073                 endif
1074         elsif sgc.currentWord = 0 or sgc.currentWord = sgc.numberOfWords+1
1075                 call clean_up_sound
1076                 .displayText$ = "---"
1077         endif
1079         # Adapt font size
1080         call adjustFontSizeOnHeight 'defaultFont$' 24 15
1081         .currentFontSize = adjustFontSizeOnHeight.newFontSize
1082         call adjustFontSizeOnWidth 'defaultFont$' '.currentFontSize' 95 '.displayText$'
1083         .currentFontSize = adjustFontSizeOnWidth.newFontSize
1085         # Clear the writing area
1086         call wipeArea 'wipePinyinArea$'
1087         # Switch back to Chinese style CJK when in Japanese language mode
1088         if .changeCJKstyle and config.language$ = "JA"
1089                 CJK font style preferences: "Chinese"
1090         endif
1091         # Actually display text
1092         demo '.color$'
1093         call set_font_size '.currentFontSize'
1094         demo Text... 50 Centre 26 Bottom '.displayText$'
1095         demoShow()
1096         demo Black
1097         demo 'defaultFont$'
1098         call set_font_size 'defaultFontSize'
1099         if .changeCJKstyle and config.language$ = "JA"
1100                 if config.language$ = "JA"
1101                         CJK font style preferences: "Japanese"
1102                 elsif config.language$ = "ZH"
1103                         CJK font style preferences: "Chinese"
1104                 endif
1105         endif
1106         # Switch back to Japanese style CJK when in Japanese language mode
1107         if .changeCJKstyle and config.language$ = "JA"
1108                 CJK font style preferences: "Japanese"
1109         endif
1110 endproc
1112 procedure numbers2pinyin .numberstext$
1113         .intermediatePinyin$ = .numberstext$
1114         # Add a `-quote between vowels
1115         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])([aeuiov])", "\1\2'\3", 0)
1116         # Move numbers to the nucleus vowel
1117         # To the vowel
1118         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([^aeuiov0-9]*)([0-9])", "\1\3\2", 0)
1119         # Either a/e
1120         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([ae])([aeuiov]*)([0-9])", "\1\3\2", 0)
1121         # Or the Oo in /ou/
1122         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(ou)([0-9])", "o\2u", 0)
1123         # or the second vowel
1124         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([uiov][aeuiov])([uiov])([0-9])", "\1\3\2", 0)
1125         
1126         # Convert all tones to special characters
1127         # Tone 1
1128         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a1", "ā", 0)
1129         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e1", "ē", 0)
1130         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u1", "ū", 0)
1131         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i1", "ī", 0)
1132         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o1", "ō", 0)
1133         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v1", "ǖ", 0)
1134         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "1", "\\-^", 0)
1135         
1136         # Tone 2
1137         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v2", "ǘ", 0)
1138         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])2", "\\\1'", 0)
1139         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "2", "\\'^", 0)
1140         
1141         # Tone 3
1142         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a3", "ǎ", 0)
1143         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e3", "ě", 0)
1144         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u3", "ǔ", 0)
1145         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i3", "ǐ", 0)
1146         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o3", "ǒ", 0)
1147         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v3", "ǚ", 0)
1148         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "3", "\\N^", 0)
1150         # Tone 4
1151         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v4", "ǜ", 0)
1152         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])4", "\\\1`", 0)
1153         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "4", "\\`^", 0)
1154         
1155         # Tone 0
1156         # Remove tone 0 symbol completely
1157         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "", 0)
1158         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a0", "å", 0)
1159         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e0", "e̊", 0)
1160         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u0", "ů", 0)
1161         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i0", "i̊", 0)
1162         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o0", "o̊", 0)
1163         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v0", "ü̊", 0)
1164         #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "\\0^", 0)
1165         
1166         # Pick best vowel symbols available in cases not caught before
1167         # Ugly clutch to get the 1, 3, 0 tone diacritics at least in the neighbourhood
1168         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i(\\[-N0]\^)", "i\\s{_ }\1", 0)
1169         # Insert u umlaut
1170         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v", "\\u\X22", 0)
1172         .pinyin$ = .intermediatePinyin$
1173 endproc
1175 # NEEDS WORK AND TESTING!!
1176 # Convert unicode Pinyin into tone numbers
1177 procedure pinyin2numbers .pinyin$
1178         .intermediatePinyin$ = .pinyin$
1179         # Convert all special characters to numbers
1180         # Tone 1
1181         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iā)([iaeouü]*)", "a\11", 0)
1182         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iē)([iaeouü]*)", "e\11", 0)
1183         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iū)([iaeouü]*)", "u\11", 0)
1184         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iī)([iaeouü]*)", "i\11", 0)
1185         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iō)([iaeouü]*)", "o\11", 0)
1186         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǖ)([iaeouü]*)", "v\11", 0)
1187         
1188         # Tone 2
1189         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iá)([iaeouü]*)", "a\12", 0)
1190         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ié)([iaeouü]*)", "e\12", 0)
1191         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iú)([iaeouü]*)", "u\12", 0)
1192         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ií)([iaeouü]*)", "i\12", 0)
1193         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ió)([iaeouü]*)", "o\12", 0)
1194         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǘ)([iaeouü]*)", "v\12", 0)
1195         
1196         # Tone 3
1197         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǎ)([iaeouü]*)", "a\13", 0)
1198         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iě)([iaeouü]*)", "e\13", 0)
1199         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǔ)([iaeouü]*)", "u\13", 0)
1200         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǐ)([iaeouü]*)", "i\13", 0)
1201         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǒ)([iaeouü]*)", "o\13", 0)
1202         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǚ)([iaeouü]*)", "v\13", 0)
1204         # Tone 4
1205         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ià)([iaeouü]*)", "a\14", 0)
1206         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iè)([iaeouü]*)", "e\14", 0)
1207         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iù)([iaeouü]*)", "u\14", 0)
1208         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iì)([iaeouü]*)", "i\14", 0)
1209         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iò)([iaeouü]*)", "o\14", 0)
1210         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǜ)([iaeouü]*)", "v\14", 0)
1211         
1212         # Tone 0
1213         # Add tone 0
1214         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iå)([iaeouü]*)", "a\10", 0)
1215         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e̊([iaeouü]*)", "e\10", 0)
1216         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iů)([iaeouü]*)", "u\10", 0)
1217         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i̊([iaeouü]*)", "i\10", 0)
1218         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o̊([iaeouü]*)", "o\10", 0)
1219         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ü̊([iaeouü]*)", "v\10", 0)
1221         # Syllables without a tone symbol are tone 0
1222         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov]+)([^0-9aeuiov]|\W|$)", "\10\2", 0)
1224         # Move numbers to the end of the syllable.
1225         # Syllables ending in n and start with g. Note that a syllable cannot start with an u or i
1226         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(n)(g[aeuiov])", "\1\3\2\4", 0)
1227         # Syllables ending in (ng?) followed by something that is not a valid vowel 
1228         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(ng?)([^aeuiov]|\W|$)", "\1\3\2\4", 0)
1229         # Syllables ending in r
1230         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(r)([^aeuiov]|\W|$)", "\1\3\2\4", 0)
1231         # Remove quotes etc
1232         #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "[\\'\\`]", "", 0)
1233         
1234         .numberstext$ = .intermediatePinyin$
1235 endproc
1237 procedure readDisplayPinyin .currentWord
1238         select sgc.currentWordlist
1239         .pinyin$ = Get value... '.currentWord' Pinyin
1240         .character$ = Get value... '.currentWord' Character
1241         # Everything to lowercase
1243         if index_regex(.pinyin$, "[0-9]") <= 0
1244                 call pinyin2numbers '.pinyin$'
1245                 .pinyin$ = pinyin2numbers.numberstext$
1246         endif 
1247 endproc
1249 procedure readPinyin .currentWord
1250         call readDisplayPinyin '.currentWord'
1251         .character$ = readDisplayPinyin.character$
1252         .pinyin$ = replace_regex$(readDisplayPinyin.pinyin$, ".+", "\L&", 0)
1253         .pinyin$ = replace_regex$(.pinyin$, "[\\'\\` ]", "", 0)
1254         # Remove anything that is objectionable
1255         .pinyin$ = replace_regex$(.pinyin$, "[^\w']", "", 0)
1256 endproc
1258 # Includes
1259 include ToneProt/SGC_ToneProt.praat
1260 include ToneProt/DrawToneContour.praat
1261 include ToneProt/HumToneContour.praat
1262 include ToneProt/ToneRecognition.praat
1263 include ToneProt/ToneScript.praat
1264 include ToneProt/ToneRules.praat