Rebuild creaky voice detector for third tones
[sgc2.git] / MainPage.praat
blob48c1adefafd5358e593b8f33ce91a41b78d12a96
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         # Get help text
294         call findLabel '.table$' '.label$'
295         .row = findLabel.row
296         select Table '.table$'
297         .helpText$ = Get value... '.row' Helptext
298         call convert_praat_to_latin1 '.helpText$'
299         .helpText$ = convert_praat_to_latin1.text$
300    
301     # Implement Cancel
302     select sgc.currentWordlist
303     .tmpOriginalWordlist = Copy: "Original_'wordlist$'"
305         # Remove current list from All wordlists table
306         select sgc.allWordLists
307         .rowNum = Search column: "Name", wordlistName$
308         if .rowNum > 0
309                 .numRows = Get number of rows
310                 if .numRows > 1
311                         Remove row: .rowNum
312                 else
313                         Set string value: 1, "Name", "---"
314                 endif
315         endif
316     
317     # Set current word
318         select sgc.currentWordlist
319         sgc.numberOfWords = Get number of rows
320     .currentWord = sgc.currentWord
321     if .currentWord <= 0 or .currentWord > sgc.numberOfWords or config.shuffleLists
322                 .currentWord = 1
323         endif
324     
325         # The texts
326         call get_feedback_text 'config.language$' SelectWordlist
327         call convert_praat_to_latin1 'get_feedback_text.text$'
328         .selectWordlistText$ = convert_praat_to_latin1.text$
329         call get_feedback_text 'config.language$' AddWordlist
330         call convert_praat_to_latin1 'get_feedback_text.text$'
331         .wordlistText$ = convert_praat_to_latin1.text$
332         call get_feedback_text 'config.language$' Part
333         call convert_praat_to_latin1 'get_feedback_text.text$'
334         .partText$ = convert_praat_to_latin1.text$
335         call get_feedback_text 'config.language$' Tones
336         call convert_praat_to_latin1 'get_feedback_text.text$'
337         .toneText$ = convert_praat_to_latin1.text$
338         call get_feedback_text 'config.language$' Cancel
339         call convert_praat_to_latin1 'get_feedback_text.text$'
340         .cancelText$ = convert_praat_to_latin1.text$
341         call get_feedback_text 'config.language$' Clear
342         call convert_praat_to_latin1 'get_feedback_text.text$'
343         .clearText$ = convert_praat_to_latin1.text$
344         call get_feedback_text 'config.language$' All
345         call convert_praat_to_latin1 'get_feedback_text.text$'
346         .allText$ = convert_praat_to_latin1.text$
347         call get_feedback_text 'config.language$' Apply
348         call convert_praat_to_latin1 'get_feedback_text.text$'
349         .applySelection$ = convert_praat_to_latin1.text$
350         call get_feedback_text 'config.language$' Next
351         call convert_praat_to_latin1 'get_feedback_text.text$'
352         .nextWord$ = convert_praat_to_latin1.text$
353         call get_feedback_text 'config.language$' Continue
354         call convert_praat_to_latin1 'get_feedback_text.text$'
355         .continueText$ = convert_praat_to_latin1.text$
356         call get_feedback_text 'config.language$' Show
357         call convert_praat_to_latin1 'get_feedback_text.text$'
358         .showText$ = convert_praat_to_latin1.text$
360         call get_evaluation_text 'config.language$' Pinyin
361         .pinyinText$ = get_evaluation_text.text$
362         
363         call get_evaluation_text 'config.language$' Character
364         .characterText$ = get_evaluation_text.text$
365         
366         call get_evaluation_text 'config.language$' Example
367         .exampleText$ = get_evaluation_text.text$
368         
369         call get_evaluation_text 'config.language$' Translation
370         .translationText$ = get_evaluation_text.text$
371         
372         call get_evaluation_text 'config.language$' ManualEntry
373         .manualEntryText$ = get_evaluation_text.text$
374         
375         # Get lesson names
376         select sgc.currentWordlist
377         .lessonCol = Get column index: "Lesson"
378         if .lessonCol <= 0
379                 Append column: "Lesson"
380                 .lessonCol = Get column index: "Lesson"
381                 .numRows = Get number of rows
382                 for .w to .numRows
383                         Set string value: .w, "Lesson", "-"
384                 endfor
385         endif
387         # All shown keeps track whether all words are shown
388         # If so, selecting a lesson is preceded by a Clear All
389         .allShown = 0
390         
391         clicked = -1
392         .numWordsPerScreen = 15
393         while clicked <> 6 and clicked <> 1
394                 .lessonSelected = -1
395                 .toneSelected = -1
396                 .firstShown = -1
397                 
398                 # A new list might have been added!
399                 .lessonList$ = tab$
400                 .numLessons = 0
401                 .lessonName$ = ""
402                 # Get lesson names
403                 select sgc.currentWordlist
404                 .lessonCol = Get column index: "Lesson"
405                 if .lessonCol <= 0
406                         Append column: "Lesson"
407                         .lessonCol = Get column index: "Lesson"
408                         .numRows = Get number of rows
409                         for .w to .numRows
410                                 Set string value: .w, "Lesson", "-"
411                         endfor
412                 endif
413                 .lessonList$ = tab$
414                 .numLessons = 0
415                 .lessonName$ = ""
416                 # All shown keeps track whether all words are shown
417                 # If so, selecting a lesson is preceded by a Clear All
418                 .allShown = 0
419                 # Sort words for consistent selection interface
420                 if config.shuffleLists
421                         # Allow subdivision in lessons
422                         if .lessonCol > 0
423                                 Sort rows... Lesson Pinyin
424                         else
425                                 Sort rows... Pinyin
426                         endif
427                 endif           
428                 if .lessonCol > 0
429                         for .i to sgc.numberOfWords
430                                 .currentLesson$ = Get value: .i, "Lesson"
431                                 .matchLesson$ = tab$+.currentLesson$+tab$
432                                 if .currentLesson$ <> "" and .currentLesson$ <> "-" and .currentLesson$ <> "?" and index(.lessonList$, .matchLesson$) <= 0
433                                         .lessonList$ = .lessonList$ + .currentLesson$ + tab$
434                                         .numLessons += 1
435                                         .lessonName$['.numLessons'] = .currentLesson$
436                                 endif
437                                 .shown$ = Get value: .i, "Show"
438                                 if .shown$ = "-"
439                                         .allShown = 0
440                                 endif
441                         endfor
442                 endif
445                 # Sort words for consistent selection interface (watch out, List can be changed)
446         if config.shuffleLists
447                         # Allow subdivision in lessons
448                         if .numLessons > 1
449                                 Sort rows... Lesson Pinyin
450                         else
451                                 Sort rows... Pinyin
452                         endif
453         endif           
454                 .max = .numWordsPerScreen - 1
455                 if .currentWord + .max > sgc.numberOfWords
456                         .max = sgc.numberOfWords - .currentWord
457                 endif
458                 for .i from 0 to .numWordsPerScreen - 1
459                         if .i <= .max
460                                 .currentPinyin$ = Get value: .currentWord+.i, "Pinyin"
461                                 if index_regex(.currentPinyin$, "[0-9]") <= 0
462                                         call pinyin2numbers '.currentPinyin$'
463                                         .currentPinyin$ = replace_regex$(pinyin2numbers.intermediatePinyin$, ".+", "\l&", 0)
464                                         .currentPinyin$ = replace_regex$(.currentPinyin$, "[^a-zA-Z0-9]", "", 0)
465                                 endif
466                                 .pinyin$[.i] = .currentPinyin$
468                                 .character$[.i] = Get value: .currentWord+.i, "Character"
469                                 .lessonNum$[.i] = ""
470                                 if .numLessons > 1
471                                         .lessonNum$[.i] = Get value: .currentWord+.i, "Lesson"
472                                         .lessonNum$[.i] = " : " + .lessonNum$[.i]
473                                 endif
474                                 .showText$[.i] = .pinyin$['.i']
475                                 if .character$['.i'] <> "-"
476                                         .showText$[.i] = .pinyin$['.i']+" ("+.character$['.i']+.lessonNum$['.i']+")"
477                                 elsif .lessonNum$['.i'] <> ""
478                                         .showText$[.i] = .pinyin$['.i']+" ( -"+.lessonNum$['.i']+")"
479                                 endif
480                                 .showValueText$[.i] = Get value: .currentWord+.i, "Show"
481                                 if .showValueText$[.i] = "-"
482                                         .showValue[.i] = 0
483                                 else
484                                         .showValue[.i] = 1
485                                 endif
486                                 .showVariable$[.i] = .pinyin$[.i]
487                                 # This prevents some nasty attempts to use language elements as variables
488                                 if index_regex(.showVariable$[.i], "[^0-9r]$") or index_regex(.showVariable$[.i], "[0-9]") <= 0 
489                                         .showVariable$[.i] = .pinyin$[.i]+"0"
490                                 endif
491                                 .tmp$ = replace_regex$(.showVariable$[.i], "^(.+)$", "\l\1", 0)
492                                 .tmp$ = replace_regex$(.tmp$, "\s", "_", 0)
493                                 '.tmp$' = .showValue[.i]
494                         else
495                                 .showText$[.i] = "-"
496                                 .showValue[.i] = 0
497                         endif
498                 endfor
500                 # The user text input window (beginPause .... endPause)
501                 beginPause(.helpText$)
502                         if sgc.allWordLists > 0
503                                 select sgc.allWordLists
504                                 .numWordlists = Get number of rows
505                                 optionMenu: .selectWordlistText$, 1
506                                         option: "---"
507                                         for .w to .numWordlists
508                                                 select sgc.allWordLists
509                                                 .wordListName$ = Get value: .w, "Name"
510                                                 option: .wordListName$
511                                         endfor
512                                         # Open Empty list?
513                                         # option: "*"
514                         endif
515                         
516                         if sgc.allWordLists > 0
517                                 select sgc.allWordLists
518                                 .numWordlists = Get number of rows
519                                 optionMenu: .wordlistText$, 1
520                                         option: "---"
521                                         for .w to .numWordlists
522                                                 select sgc.allWordLists
523                                                 .wordListName$ = Get value: .w, "Name"
524                                                 option: .wordListName$
525                                         endfor
526                                         option: "*"+.manualEntryText$+"*"
527                         endif
528                         
529                         boolean (.showText$[0], .showValue[0])
530                         boolean (.showText$[1], .showValue[1])
531                         boolean (.showText$[2], .showValue[2])
532                         boolean (.showText$[3], .showValue[3])
533                         boolean (.showText$[4], .showValue[4])
534                         boolean (.showText$[5], .showValue[5])
535                         boolean (.showText$[6], .showValue[6])
536                         boolean (.showText$[7], .showValue[7])
537                         boolean (.showText$[8], .showValue[8])
538                         boolean (.showText$[9], .showValue[9])
539                         boolean (.showText$[10], .showValue[10])
540                         boolean (.showText$[11], .showValue[11])
541                         boolean (.showText$[12], .showValue[12])
542                         boolean (.showText$[13], .showValue[13])
543                         boolean (.showText$[14], .showValue[14])
544                         
545                         .selectMenu$ = .toneText$
546                         if .numLessons > 0
547                                 .selectMenu$ = .selectMenu$ + " " + .partText$
548                         endif
549                         optionMenu: .selectMenu$, 1
550                                 option: .toneText$
551                                 option: "0"
552                                 option: "1"
553                                 option: "2"
554                                 option: "3"
555                                 option: "4"
556                         
557                         # Display Lesson text if available
558                         if .numLessons > 0
559                                 option: "---"
560                                 .j = 0
561                                 for .j to .numLessons
562                                         option: .partText$+": "+.lessonName$['.j']
563                                 endfor
564                         endif
565                 clicked = endPause ("'.cancelText$'", "'.clearText$'", "'.allText$'", "'.applySelection$'", "'.nextWord$'", "'.continueText$'", 6, 1)
566                 
567                 select sgc.currentWordlist
568                 if clicked = 2
569                         for .i to sgc.numberOfWords
570                                 Set string value: .i, "Show", "-"
571                         endfor
572                         .allShown = 0
573                 elsif clicked = 3
574                         for .i to sgc.numberOfWords
575                                 Set string value: .i, "Show", "+"
576                         endfor
577                         .allShown = 1
578                 elsif clicked != 1
579                         # Switch to new wordlist
580                         .tmp$ = replace_regex$(.selectWordlistText$, "^(.)", "\l\1", 0)
581                         .tmp$ = replace_regex$(.tmp$, "\s", "_", 0)
582                         .tmp$ = '.tmp$'$
583                         if .tmp$ <> "---" and sgc.allWordLists > 0
584                                 # Existing lessons
585                                 select sgc.allWordLists
586                                 .wordlistNum = Search column: "Name", .tmp$
587                                 if .wordlistNum > 0
588                                         wordlistName$ = .tmp$
589                                         call load_word_list "'localWordlistDir$'" 0
590                                         call init_window
591                                         .currentWord = 1
592                                         
593                                         goto NEXTSELECTWORDLOOP
594                                 endif
595                                 
596                         endif
597                         
598                         # Handle added word lists
599                         .tmp$ = replace_regex$(.wordlistText$, "^(.)", "\l\1", 0)
600                         .tmp$ = replace_regex$(.tmp$, "\s", "_", 0)
601                         .tmp$ = '.tmp$'$
602                         if .tmp$ <> "---" and sgc.allWordLists > 0
603                                 select sgc.currentWordlist
604                                 # Add current wordlist name as  a lesson name
605                                 .originalWordList = -1
606                                 .numRows = Get number of rows
607                                 for .w to .numRows
608                                         select sgc.currentWordlist
609                                         .currentLesson$ = Get value: .w, "Lesson"
610                                         if .currentLesson$ = "" or .currentLesson$ = "-"
611                                                 Set string value: .w, "Lesson", wordlist$
612                                         endif
613                                 endfor
614                                 
615                                 # Get and merge the selected list
616                                 # Enter words by hand
617                                 if .tmp$ = "*"+.manualEntryText$+"*"
618                                         .man_clicked = 3
619                                         .currentFilePath$ = .exampleText$
620                                         .manualText$ = .manualEntryText$
621                                         .manPinyin$ = .pinyinText$
622                                         .manCharacter$ = .characterText$
623                                         .manTranslation$ = .translationText$
624                                         .manSound$ = .currentFilePath$
625                                         .manLesson$ = .manualText$
626                                         while .man_clicked > 1
627                                                 beginPause: .manualEntryText$
628                                                         text: .pinyinText$, .manPinyin$
629                                                         text: .characterText$, .manCharacter$ 
630                                                         text: .translationText$, .manTranslation$ 
631                                                         text: .exampleText$, .manSound$
632                                                         text: .manualText$, .manualText$
633                                                 .man_clicked = endPause("'.cancelText$'", "'.exampleText$'", "'.continueText$'", 3, 1)
634                                                 if .man_clicked > 1
635                                                         .tmp$ = replace_regex$(.pinyinText$, "\s", "_", 0)
636                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
637                                                         if '.tmp$'$ <> .pinyinText$ 
638                                                                 .manPinyin$ = '.tmp$'$
639                                                         else
640                                                                 # Quit
641                                                                 .man_clicked = 0
642                                                         endif
644                                                         .tmp$ = replace_regex$(.characterText$, "\s", "_", 0)
645                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
646                                                         if '.tmp$'$ <> .characterText$ 
647                                                                 .manCharacter$ = '.tmp$'$
648                                                         else
649                                                                 .manCharacter$ = ""
650                                                         endif
651                                                         
652                                                         .tmp$ = replace_regex$(.translationText$, "\s", "_", 0)
653                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
654                                                         if '.tmp$'$ <> .translationText$ 
655                                                                 .manTranslation$ = '.tmp$'$
656                                                         else
657                                                                 .manTranslation$ = ""
658                                                         endif
659                                                         
660                                                         .tmp$ = replace_regex$(.exampleText$, "\s", "_", 0)
661                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
662                                                         if '.tmp$'$ <> .characterText$ and '.tmp$'$ <> ""
663                                                                 .manSound$ = '.tmp$'$
664                                                         endif
665                                                         
666                                                         .tmp$ = replace_regex$(.manualText$, "\s", "_", 0)
667                                                         .tmp$ = replace_regex$(.tmp$, "^(.+)$", "\l\1", 0)
668                                                         .manLesson$ = '.tmp$'$
669                                                         
670                                                         if .man_clicked = 2
671                                                                 .manSound$ = chooseReadFile$(.exampleText$);
672                                                         elsif .man_clicked = 3
673                                                                 # Clean up input string
674                                                                 .manPinyin$ = replace_regex$(.manPinyin$, "^[^a-z]+", "", 0)
675                                                                 .manPinyin$ = replace_regex$(.manPinyin$, "[^\w']", "", 0)
676                                                                 
677                                                                 select sgc.currentWordlist
678                                                                 Append row
679                                                                 .numRows = Get number of rows
680                                                                 if .manPinyin$ <> ""
681                                                                         Set string value: .numRows, "Pinyin", .manPinyin$
682                                                                         Set string value: .numRows, "Character", .manCharacter$
683                                                                         Set string value: .numRows, "Translation", .manTranslation$
684                                                                         Set string value: .numRows, "Sound", .manSound$
685                                                                         Set string value: .numRows, "Lesson", .manLesson$
686                                                                         Set string value: .numRows, "Show", "+"
687                                                                 endif
688                                                                 .manualText$ = .manualEntryText$
689                                                                 .manPinyin$ = .pinyinText$
690                                                                 .manCharacter$ = .characterText$
691                                                                 .manTranslation$ = .translationText$
692                                                                 .manSound$ = .currentFilePath$
693                                                                 .manLesson$ = .manualText$                                                      
694                                                         endif
695                                                 endif
696                                         endwhile                                        
697                                 else
698                                         # Existing lessons
699                                         select sgc.allWordLists
700                                         .wordlistNum = Search column: "Name", .tmp$
701                                         if .wordlistNum > 0
702                                                 .wordlistPath$ = Get value: .wordlistNum, "Directory"
703                                                 .wordlistPath$ = replace_regex$(.wordlistPath$, "[ ]", "&", 0)
704                                                 call read_wordlist "'.tmp$'" '.wordlistPath$'
705                                                 .newList = read_wordlist.wordlistID
706                                                 call merge_into_wordlist '.newList' '.tmp$'
707                                                 select .newList
708                                                 Remove
709                                                 # Add wordlistname to Lesson column
710                                                 select sgc.allWordLists
711                                                 .numRows = Get number of rows
712                                                 if .numRows > 1
713                                                         Remove row: .wordlistNum
714                                                 else
715                                                         Set string value: 1, "Name", "---"
716                                                 endif
717                                         endif
718                                 endif
719                                 # Gather Lesson names
720                                 select sgc.currentWordlist
721                                 Sort rows... Lesson Pinyin
722                                 if .lessonCol > 0
723                                         sgc.numberOfWords = Get number of rows
724                                         .lessonList$ = tab$
725                                         .numLessons = 0
726                                         .lessonName$ = ""
727                                         for .i to sgc.numberOfWords
728                                                 .currentLesson$ = Get value: .i, "Lesson"
729                                                 .matchLesson$ = tab$+.currentLesson$+tab$
730                                                 if .currentLesson$ <> "" and .currentLesson$ <> "-" and .currentLesson$ <> "?" and index(.lessonList$, .matchLesson$) <= 0
731                                                         .lessonList$ = .lessonList$ + .currentLesson$ + tab$
732                                                         .numLessons += 1
733                                                         .lessonName$['.numLessons'] = .currentLesson$
734                                                 endif
735                                                 .shown$ = Get value: .i, "Show"
736                                                 if .shown$ = "-"
737                                                         .allShown = 0
738                                                 endif
739                                         endfor
740                                 endif
741                         else                    
742                                 for .i from 0 to .max
743                                         .tmp$ = replace_regex$(.showVariable$['.i'], "^(.*)$", "\l\1", 0)
744                                         .tmp$ = replace_regex$(.tmp$, "\s", "_", 0)
745                                         
746                                         .showValue['.i'] = '.tmp$'
747                                         .showWord$['.i'] = "-"
748                                         if .showValue['.i'] <> 0
749                                                 .showWord$['.i'] = "+"
750                                         endif
751                                         Set string value: .currentWord+.i, "Show", .showWord$['.i']
752                                 endfor
753                         endif
754                         
755                         select sgc.currentWordlist
756                         .tmp$ = replace_regex$(.selectMenu$, "^(.)", "\l\1", 0)
757                         .tmp$ = replace_regex$(.tmp$, "\s", "_", 0)
758                         .toneSelected = '.tmp$' - 2
759                         if .toneSelected >= 0 and .toneSelected < 5
760                                 select sgc.currentWordlist
761                                 for .i to sgc.numberOfWords
762                                         .currentPinyin$ = Get value: .i, "Pinyin"
763                                         if index_regex(.currentPinyin$, "[0-9]") <= 0
764                                                 call pinyin2numbers '.currentPinyin$'
765                                                 .currentPinyin$ = replace_regex$(pinyin2numbers.intermediatePinyin$, ".+", "\l&", 0)
766                                                 .currentPinyin$ = replace_regex$(.currentPinyin$, "[^a-zA-Z0-9]", "", 0)
767                                         endif
768                                         .tmp$ = Get value: .i, "Show"
769                                         if .tmp$ <> "-" and index(.currentPinyin$, "'.toneSelected'") > 0
770                                                 Set string value: .i, "Show", "+"
771                                         else
772                                                 Set string value: .i, "Show", "-"
773                                                 .allShown = 0
774                                         endif
775                                 endfor
776                         elsif .toneSelected > 5
777                                 # .toneSelected = 5 is the Part text
778                                 .lessonSelected = .toneSelected - 5
779                                 if .lessonSelected > 0
780                                         .allShown = 1
781                                         .firstShown = -1
782                                         select sgc.currentWordlist
783                                         for .i to sgc.numberOfWords
784                                                 # Keep track of whether all are shown
785                                                 .shown$ = Get value: .i, "Show"
786                                                 if .shown$ = "-"
787                                                         .allShown = 0
788                                                 endif
789                                         endfor
791                                         for .i to sgc.numberOfWords
792                                                 # Lessons
793                                                 .currentLesson$ = Get value: .i, "Lesson"
794                                                 if .currentLesson$ = .lessonName$['.lessonSelected']
795                                                         Set string value: .i, "Show", "+"
796                                                 elsif .allShown = 1
797                                                         Set string value: .i, "Show", "-"
798                                                 endif
799                                         endfor
800                                         for .i to sgc.numberOfWords
801                                                 # Keep track of whether all are shown
802                                                 .shown$ = Get value: .i, "Show"
803                                                 if .firstShown <=0 and .shown$ <> "-"
804                                                         .firstShown = .i
805                                                 endif
806                                         endfor
807                                 endif
808                         endif
809                         
810                         if clicked = 4
811                                 if .currentWord <= 0
812                                         .currentWord = (sgc.numberOfWords div .numWordsPerScreen) * .numWordsPerScreen + 1
813                                 endif
814                         elsif clicked = 5
815                                 if .firstShown > 0
816                                         .currentWord = (.firstShown div .numWordsPerScreen) * .numWordsPerScreen + 1
817                                 endif
818                                 .currentWord += .numWordsPerScreen
819                                 if .currentWord > sgc.numberOfWords
820                                         .currentWord = 1
821                                 endif
822                         endif
823                 endif
824                 # Reset and go to the first selected word (can shuffle list)
825                 if clicked = 6
826                         sgc.currentWord = -1
827                         call next_word
828                         call init_window
829                 endif
830                 
831                 label NEXTSELECTWORDLOOP
832         endwhile
833         
834     # Implement Cancel
835     if clicked = 1
836                 select sgc.currentWordlist
837                 Remove
838                 select .tmpOriginalWordlist
839                 Copy: wordlist$
840                 sgc.currentWordlist = selected()
841         else
842                 # Set the values of the number of words shown   
843                 select sgc.currentWordlist
844                 .numWords = Get number of rows
845                 sgc.currentWordNum = 1
846                 sgc.numberOfDisplayedWords = 0
847                 sgc.currentWord = 0
848                 for .i to .numWords
849                         .show$ = Get value: .i, "Show"
850                         if .show$ = "+"
851                                 if sgc.currentWord < 1
852                                         sgc.currentWord = .i
853                                 endif
854                                 sgc.numberOfDisplayedWords += 1
855                         endif
856                 endfor
857         endif
858         select .tmpOriginalWordlist
859         Remove
861         label SELECTWORDSFAIL
862         
863     call Draw_button '.table$' '.label$' 0
864 endproc
866 ###############################################################
868 # Obligatory button Processing Routines
870 # These MUST be defined
872 ###############################################################
874 procedure processMainPageQuit .clickX .clickY .pressed$
875         call end_program
876 endproc
878 procedure processMainPageRefresh .clickX .clickY .pressed$
879         call clean_up_sound
880         call init_window
881 endproc
883 procedure processMainPageConfig .clickX .clickY .pressed$
884         call config_page
885 endproc
887 procedure processMainPageHelp .clickX .clickY .pressed$
888         call help_loop 'buttons$' init_window
889 endproc
891 procedure processMainPagePlay .clickX .clickY .pressed$
892         .table$ = "MainPage"
893         .label$ = "Play"
894         if recordedSound$ <> ""
895                 call play_sound 'sgc.recordedSound'
896                 mainPage.play = 0
897         endif
898         te.buttonPressValue = mainPage.play
899 endproc
901 procedure Set_Play_Button
902         mainPage.play = -1
903         if recordedSound$ <> ""
904                 mainPage.play = 0
905     endif       
906         call Draw_button MainPage Play 'mainPage.play'
907 endproc
909 procedure processMainPageRecord .clickX .clickY .pressed$
910         call count_syllables
911         .recordingTime = recordingTime
912         if count_syllables.number > 2
913                 .recordingTime = recordingTime + 1.0*ceiling((count_syllables.number - 2)/2)
914         endif
915     call record_sound '.recordingTime'
916     call recognizeTone
917         mainPage.play = 0
918         call Set_Play_Button
920     # Wipe screen
921     call wipeArea 'wipeContourArea$'
922    
923     call draw_tone_contour
924     # Write text (again)
925     call display_word_list_name
926     call display_text Black
927         call add_feedback_to_toneevaluation Feedback
928     call write_feedback Feedback
929         select Table Feedback
930         Remove
931         
932         # Do not exercise words that are going well (autoSelect)
933     if add_feedback_to_toneevaluation.result > 0
934                 if config.adaptiveLists > 0 and sgc.failedAttempts < 2
935                         # Deselect current word
936                         select sgc.currentWordlist
937                         .i = Search column: "Pinyin", sgc.pinyin$
938                         if .i > 0
939                                 Set string value: .i, "Show", "-"
940                         endif
941                 endif
942                 sgc.failedAttempts = 0
943     else
944                 sgc.failedAttempts += 1
945     endif
946 endproc
949 ###############################################################
951 # Miscelaneous supporting code
953 ###############################################################
955 # The example
956 procedure generate_example
957         select sgc.currentWordlist
958         if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
959                 select sgc.currentWordlist
960                 .sound$ = Get value... 'sgc.currentWord' Sound
961                 call readPinyin 'sgc.currentWord'
962                 sgc.pinyin$ = readPinyin.pinyin$
963                 sgc.character$ = readPinyin.character$
964                 if .sound$ = "-" or .sound$ = ""
965                         .sound$ = sgc.pinyin$+".wav"
966                 endif
967                 if index_regex(.sound$, "^(/|~/|[A-Z]:\\)") > 0
968                         .soundFilePath$ = .sound$
969                 else
970                         .soundFilePath$ = localWordlistDir$+"/"+wordlistName$+"/"+.sound$
971                         .wordlistDirectory$ = ""
972                         if localWordlistDir$ <> "" and fileReadable("'localWordlistDir$'/'wordlistName$'")
973                                 .wordlistDirectory$ = "'localWordlistDir$'/'wordlistName$'"
974                         elsif sgc2wordlists$ <> "" and fileReadable("'sgc2wordlists$'/'wordlistName$'")
975                                 .wordlistDirectory$ = "'sgc2wordlists$'/'wordlistName$'"
976                         elsif globalwordlists$ <> "" and fileReadable("'globalwordlists$'/'wordlistName$'")
977                                 .wordlistDirectory$ = "'globalwordlists$'/'wordlistName$'"
978                         endif
979                         if .wordlistDirectory$ <> ""
980                                 .audioExampleList = Create Strings as file list... AudioList '.wordlistDirectory$'/'sgc.pinyin$'.*
981                                 .number_of_examples = Get number of strings
982                                 if .number_of_examples > 0
983                                         Randomize
984                                         .sound$ = Get string... 1
985                                         .soundFilePath$ = "'.wordlistDirectory$'/'.sound$'"
986                                 endif
987                                 Remove
988                         endif
989                 endif
990                 if fileReadable(.soundFilePath$) and config.useSoundExample
991                         .tmp = -1
992                         .tmp = nocheck Read from file... '.soundFilePath$'
993                         if .tmp != undefined and .tmp > 0
994                                 call play_sound '.tmp'
995                                 select .tmp
996                                 Remove
997                         endif
998                 elsif config.synthesis$ <> "" and config.synthesis$ <> "_DISABLED_"
999                         call synthesize_sound "'sgc.pinyin$'" "'sgc.character$'"
1000                 else
1001                         call humToneContour 'sgc.pinyin$' 'config.register'
1002                         call reset_viewport
1003                 endif
1004         endif
1005         demoShow()
1006 endproc
1008 # Draw a tone contour
1009 procedure draw_tone_contour
1010         select sgc.currentWordlist
1011         if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
1012                 .sound$ = Get value... 'sgc.currentWord' Sound
1013                 call readPinyin 'sgc.currentWord'
1014                 sgc.pinyin$ = readPinyin.pinyin$
1015                 sgc.character$ = readPinyin.character$
1016                 call drawToneContour 'sgc.pinyin$' 'config.register'
1017                 call reset_viewport
1018                 
1019                 if te.recordedPitch > 0
1020                         call drawSourceToneContour te.recordedPitch
1021                 endif
1022         endif
1024 endproc
1026 procedure recognizeTone
1027         select sgc.currentWordlist
1028         if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
1029                 .strict = 0
1030                 if index_regex(config.strict$, "[^0-9]") <= 0
1031                         .strict = ('config.strict$' >= sgc.highestLevel)
1032                 endif
1033                         
1034                 .sound$ = Get value... 'sgc.currentWord' Sound
1035                 call readPinyin 'sgc.currentWord'
1036                 sgc.pinyin$ = readPinyin.pinyin$
1037                 sgc.character$ = readPinyin.character$
1038                 call align_recordedSound 'sgc.pinyin$'
1039         call sgc_ToneProt 'recordedSound$' 'sgc.pinyin$' 'config.register' '.strict' 'config.language$'
1040         # sgc_ToneProt manipulates the sound given. Reconnect
1041         select Sound 'recordedSound$'
1042         sgc.recordedSound = selected("Sound")
1043                 call reset_viewport
1044         endif
1045 endproc
1047 procedure write_feedback .table$
1048     select Table '.table$'
1049     .line1$ = Get value... 1 Text
1050     .line2$ = Get value... 2 Text
1051     .label$ = Get value... 3 Text
1053         # convert numbers to Pinyin if needed
1054         if not config.displayNumbers
1055                 call numbers2pinyin '.line1$'
1056                 .line1$ = numbers2pinyin.pinyin$
1057         endif
1059     .color$ = "Red"
1060     if index(.line1$, "???") > 0
1061         .color$ = "Black"
1062     elsif .label$ = "Correct"
1063         .color$ = "Green"
1064         elsif config.strict$ = "'sgc.highestLevel'"
1065                 .line2$ = .line2$ + " *"
1066     endif
1068         .currentFeedbackFontSize = 14
1069         .maxHeight = 21 - 17
1070         call adjustFontSizeOnHeight 'defaultFont$' '.currentFeedbackFontSize' '.maxHeight'
1071         .currentFeedbackFontSize = adjustFontSizeOnHeight.newFontSize
1073         call wipeArea 'wipeFeedbackArea$'
1074     call set_font_size '.currentFeedbackFontSize'
1075     demo '.color$'
1076     demo Text... 50 Centre 21 Bottom '.line1$'
1077     demo Text... 50 Centre 17 Bottom '.line2$'
1078         demoShow()
1079         demo 'defaultFont$'
1080     call set_font_size 'defaultFontSize'
1081 endproc
1083 procedure write_grade .pinyin$
1084         if sgc2.performanceTable > 0 and .pinyin$ <> ""
1085                 select sgc2.performanceTable
1086                 call getGrade '.pinyin$'
1087                 if getGrade.grade > 0
1088                         call get_evaluation_text 'config.language$' 'getGrade.grade'
1089                         .currentGrade$ = get_evaluation_text.text$
1090                     .line1$ = .currentGrade$
1091                 
1092                     .color$ = "Blue"            
1093                         .currentFeedbackFontSize = 40
1094                         .maxHeight = 2* (21 - 17 - 1)
1095                         call adjustFontSizeOnHeight 'defaultFont$' '.currentFeedbackFontSize' '.maxHeight'
1096                         .currentFeedbackFontSize = adjustFontSizeOnHeight.newFontSize
1097                         
1098                         call wipeArea 'wipeFeedbackArea$'
1099                     call set_font_size '.currentFeedbackFontSize'
1100                     demo '.color$'
1101                     demo Text... 50 Centre 17 Bottom '.line1$'
1102                         demoShow()
1103                         demo 'defaultFont$'
1104                     call set_font_size 'defaultFontSize'
1105             endif
1106     endif
1107 endproc
1109 # Text display
1110 procedure display_text .color$
1111         select sgc.currentWordlist
1112         if sgc.currentWord < 0 or sgc.currentWord > sgc.numberOfWords+1
1113                 call clean_up_sound
1114         if config.shuffleLists
1115                     Randomize rows
1116         endif
1117                 if sgc.currentWord < 0
1118                         sgc.currentWord = sgc.numberOfWords
1119                 else
1120                         sgc.currentWord = 1
1121                 endif
1122         endif
1123         
1124         .changeCJKstyle = 0
1125         if sgc.currentWord > 0 and sgc.currentWord <= sgc.numberOfWords
1126                 .displayText$ = ""
1127                 call readDisplayPinyin 'sgc.currentWord'
1128                 .displayPinyin$ = readDisplayPinyin.pinyin$
1129                 .displayChar$ = Get value... 'sgc.currentWord' Character
1130                 .displayTrans$ = Get value... 'sgc.currentWord' Translation
1131                 if .displayPinyin$ <> "-" and (config.displayPinyin or sgc.writeAll)
1132                         if not config.displayNumbers
1133                                 call numbers2pinyin '.displayPinyin$'
1134                                 .displayPinyin$ = numbers2pinyin.pinyin$
1135                         endif
1136                         # Insert u umlaut
1137                         .displayPinyin$ = replace_regex$(.displayPinyin$, "v", "\\u\X22", 0)
1138                         .displayText$ = .displayText$ + .displayPinyin$
1139                 endif
1140                 if .displayChar$ <> "-" and (config.displayChar or sgc.writeAll)
1141                         .displayText$ = .displayText$ + "  "+ .displayChar$
1142                         .changeCJKstyle = 1
1143                 endif
1144                 if .displayTrans$ <> "-" and (config.displayTrans or sgc.writeAll)
1145                         .displayText$ = .displayText$ + "  \s{%%"+ .displayTrans$ + "%}"
1146                 endif
1147         elsif sgc.currentWord = 0 or sgc.currentWord = sgc.numberOfWords+1
1148                 call clean_up_sound
1149                 .displayText$ = "---"
1150         endif
1152         # Adapt font size
1153         call adjustFontSizeOnHeight 'defaultFont$' 24 15
1154         .currentFontSize = adjustFontSizeOnHeight.newFontSize
1155         call adjustFontSizeOnWidth 'defaultFont$' '.currentFontSize' 95 '.displayText$'
1156         .currentFontSize = adjustFontSizeOnWidth.newFontSize
1158         # Clear the writing area
1159         call wipeArea 'wipePinyinArea$'
1160         # Switch back to Chinese style CJK when in Japanese language mode
1161         if .changeCJKstyle and config.language$ = "JA"
1162                 CJK font style preferences: "Chinese"
1163         endif
1164         # Actually display text
1165         demo '.color$'
1166         call set_font_size '.currentFontSize'
1167         demo Text... 50 Centre 26 Bottom '.displayText$'
1168         demoShow()
1169         demo Black
1170         demo 'defaultFont$'
1171         call set_font_size 'defaultFontSize'
1172         if .changeCJKstyle and config.language$ = "JA"
1173                 if config.language$ = "JA"
1174                         CJK font style preferences: "Japanese"
1175                 elsif config.language$ = "ZH"
1176                         CJK font style preferences: "Chinese"
1177                 endif
1178         endif
1179         # Switch back to Japanese style CJK when in Japanese language mode
1180         if .changeCJKstyle and config.language$ = "JA"
1181                 CJK font style preferences: "Japanese"
1182         endif
1183 endproc
1185 procedure numbers2pinyin .numberstext$
1186         .intermediatePinyin$ = .numberstext$
1187         # Add a `-quote between vowels
1188         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])([aeuiov])", "\1\2'\3", 0)
1189         # Move numbers to the nucleus vowel
1190         # To the vowel
1191         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([^aeuiov0-9]*)([0-9])", "\1\3\2", 0)
1192         # Either a/e
1193         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([ae])([aeuiov]*)([0-9])", "\1\3\2", 0)
1194         # Or the Oo in /ou/
1195         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(ou)([0-9])", "o\2u", 0)
1196         # or the second vowel
1197         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([uiov][aeuiov])([uiov])([0-9])", "\1\3\2", 0)
1198         
1199         # Convert all tones to special characters
1200         # Tone 1
1201         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a1", "ā", 0)
1202         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e1", "ē", 0)
1203         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u1", "ū", 0)
1204         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i1", "ī", 0)
1205         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o1", "ō", 0)
1206         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v1", "ǖ", 0)
1207         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "1", "\\-^", 0)
1208         
1209         # Tone 2
1210         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v2", "ǘ", 0)
1211         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])2", "\\\1'", 0)
1212         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "2", "\\'^", 0)
1213         
1214         # Tone 3
1215         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a3", "ǎ", 0)
1216         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e3", "ě", 0)
1217         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u3", "ǔ", 0)
1218         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i3", "ǐ", 0)
1219         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o3", "ǒ", 0)
1220         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v3", "ǚ", 0)
1221         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "3", "\\N^", 0)
1223         # Tone 4
1224         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v4", "ǜ", 0)
1225         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([iaeou])4", "\\\1`", 0)
1226         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "4", "\\`^", 0)
1227         
1228         # Tone 0
1229         # Remove tone 0 symbol completely
1230         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "", 0)
1231         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "a0", "å", 0)
1232         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e0", "e̊", 0)
1233         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "u0", "ů", 0)
1234         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i0", "i̊", 0)
1235         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o0", "o̊", 0)
1236         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v0", "ü̊", 0)
1237         #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "0", "\\0^", 0)
1238         
1239         # Pick best vowel symbols available in cases not caught before
1240         # Ugly clutch to get the 1, 3, 0 tone diacritics at least in the neighbourhood
1241         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i(\\[-N0]\^)", "i\\s{_ }\1", 0)
1242         # Insert u umlaut
1243         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "v", "\\u\X22", 0)
1245         .pinyin$ = .intermediatePinyin$
1246 endproc
1248 # NEEDS WORK AND TESTING!!
1249 # Convert unicode Pinyin into tone numbers
1250 procedure pinyin2numbers .pinyin$
1251         .intermediatePinyin$ = .pinyin$
1252         # Convert all special characters to numbers
1253         # Tone 1
1254         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iā)([iaeouü]*)", "a\11", 0)
1255         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iē)([iaeouü]*)", "e\11", 0)
1256         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iū)([iaeouü]*)", "u\11", 0)
1257         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iī)([iaeouü]*)", "i\11", 0)
1258         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iō)([iaeouü]*)", "o\11", 0)
1259         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǖ)([iaeouü]*)", "v\11", 0)
1260         
1261         # Tone 2
1262         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iá)([iaeouü]*)", "a\12", 0)
1263         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ié)([iaeouü]*)", "e\12", 0)
1264         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iú)([iaeouü]*)", "u\12", 0)
1265         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ií)([iaeouü]*)", "i\12", 0)
1266         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ió)([iaeouü]*)", "o\12", 0)
1267         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǘ)([iaeouü]*)", "v\12", 0)
1268         
1269         # Tone 3
1270         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǎ)([iaeouü]*)", "a\13", 0)
1271         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iě)([iaeouü]*)", "e\13", 0)
1272         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǔ)([iaeouü]*)", "u\13", 0)
1273         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǐ)([iaeouü]*)", "i\13", 0)
1274         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǒ)([iaeouü]*)", "o\13", 0)
1275         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǚ)([iaeouü]*)", "v\13", 0)
1277         # Tone 4
1278         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?ià)([iaeouü]*)", "a\14", 0)
1279         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iè)([iaeouü]*)", "e\14", 0)
1280         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iù)([iaeouü]*)", "u\14", 0)
1281         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iì)([iaeouü]*)", "i\14", 0)
1282         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iò)([iaeouü]*)", "o\14", 0)
1283         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iǜ)([iaeouü]*)", "v\14", 0)
1284         
1285         # Tone 0
1286         # Add tone 0
1287         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iå)([iaeouü]*)", "a\10", 0)
1288         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "e̊([iaeouü]*)", "e\10", 0)
1289         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "(?iů)([iaeouü]*)", "u\10", 0)
1290         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "i̊([iaeouü]*)", "i\10", 0)
1291         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "o̊([iaeouü]*)", "o\10", 0)
1292         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "ü̊([iaeouü]*)", "v\10", 0)
1294         # Syllables without a tone symbol are tone 0
1295         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov]+)([^0-9aeuiov]|\W|$)", "\10\2", 0)
1297         # Move numbers to the end of the syllable.
1298         # Syllables ending in n and start with g. Note that a syllable cannot start with an u or i
1299         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(n)(g[aeuiov])", "\1\3\2\4", 0)
1300         # Syllables ending in (ng?) followed by something that is not a valid vowel 
1301         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(ng?)([^aeuiov]|\W|$)", "\1\3\2\4", 0)
1302         # Syllables ending in r
1303         .intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "([aeuiov])([0-9])(r)([^aeuiov]|\W|$)", "\1\3\2\4", 0)
1304         # Remove quotes etc
1305         #.intermediatePinyin$ = replace_regex$(.intermediatePinyin$, "[\\'\\`]", "", 0)
1306         
1307         .numberstext$ = .intermediatePinyin$
1308 endproc
1310 procedure readDisplayPinyin .currentWord
1311         select sgc.currentWordlist
1312         .pinyin$ = Get value... '.currentWord' Pinyin
1313         .character$ = Get value... '.currentWord' Character
1314         # Everything to lowercase
1316         if index_regex(.pinyin$, "[0-9]") <= 0
1317                 call pinyin2numbers '.pinyin$'
1318                 .pinyin$ = pinyin2numbers.numberstext$
1319         endif 
1320 endproc
1322 procedure readPinyin .currentWord
1323         call readDisplayPinyin '.currentWord'
1324         .character$ = readDisplayPinyin.character$
1325         .pinyin$ = replace_regex$(readDisplayPinyin.pinyin$, ".+", "\L&", 0)
1326         .pinyin$ = replace_regex$(.pinyin$, "[\\'\\` ]", "", 0)
1327         # Remove anything that is objectionable
1328         .pinyin$ = replace_regex$(.pinyin$, "[^\w']", "", 0)
1329 endproc
1331 # Includes
1332 include ToneProt/SGC_ToneProt.praat
1333 include ToneProt/DrawToneContour.praat
1334 include ToneProt/HumToneContour.praat
1335 include ToneProt/ToneRecognition.praat
1336 include ToneProt/ToneScript.praat
1337 include ToneProt/ToneRules.praat