text:
KENT STATE AUTHOR DONATES FREE EBOOKS TO STUDENTS, FACULTY MEMBERS, AND ALUMNI
By Guest Columnist, cleveland.com
This post originally appeared on the op-ed page of the March 6, 2020 Cleveland Plain Dealer.
LOS ANGELES -- Even though I received some of the best reviews of any book about the May 4, 1970, killings at Kent State University, I have been repeatedly prevented from speaking on the campus. Every time my original publisher or I tried to schedule a speaking engagement, it was made clear to me that I was, in the words of a sociology professor, "not welcome" at Kent State.
The reasons are varied and include the fact that I exposed some abominable behavior by some of the tragedy's best-known characters, including that professor, who was laden with multiple conflicts of interest. Also, as far as the May 4 Task Force is concerned (the student group supposedly in charge of keeping alive the memory of May 4 ), I am much too respectable and middle class. That group, by the way, also blocked other May 4 authors from speaking at Kent, including Philip Caputo, a distinguished Pulitzer-Prize-winning author.
As an exercise in "creative revenge," I decided that in 2020, during Kent State's yearlong 50th anniversary commemoration of the shootings, I would donate the updated ebook version of my book, "Four Dead in Ohio," to any student, faculty member, and alumnus or alumna who is interested. I figured that If the university was going to repeatedly censor me, I would make it impossible for KSU to prevent its students from discovering what I had to say.
I do not expect many students to take me up on the offer because, let us face it, the university still has not provided today's students with a good reason to even remember May 4. If we were to be brutally honest about it, we would stipulate that May 4 (as it is called in shorthand) has very little to do with anything going on in the world today. The people who want to keep its memory alive are mostly the stuck-in-the-'60s protesters who want to be remembered as heroes of the anti-Vietnam War movement.
For this year's commemoration, Kent State's administration has been conned into honoring several not-so-former radicals who either have not been truthful about their own roles in the tragedy, or who still champion violent protest.
I have been particularly disturbed by the claims of two of Kent State's "honorees," wounded student Alan Canfora and his sister Chic, that they represent the views of the parents of the four students killed. As someone who actually worked with those parents in an attempt to get some semblance of justice, I can tell you they were, more often than not, not on the same page, particularly when the parents sought a federal grand jury investigation.
Kent's "honorees" actually opposed a full investigation because they feared that they would be criminally prosecuted themselves instead of the Ohio National Guardsmen. In fact, another "honoree," wounded survivor Thomas Grace, whose book "Kent State" is essentially a "love letter" to the defunct Students for a Democratic Society, disparaged the parents' struggle for justice, telling fellow student Paul Keane that "the only way to get justice is to pick up a gun."
The parents of those killed May 4 would never have approved of this behavior, nor wanted their "search for the truth" and "the struggle for justice" obliterated from KSU's official history. Unfortunately, that is what Grace and his friends primarily accomplished when they served as consultants for Kent's May 4 Visitors Center.
The reason May 4 deserves to be remembered is not because it single-handedly ended the war in Vietnam (although it obviously played some part), but because it quietly morphed into one of the greatest injustices in modern American history. The country may have grown weary of the war, but it had also lost its patience with the protesters who, in the name of peace, committed violence. In fact, the unpopularity of the victims was exactly why it was so easy to cover up the real story of the May 4 shootings.
Perhaps if Kent State had a law school instead of a sociology department, someone there might have recognized what transpired right in front of their eyes. If nothing else, I hope the donation of my book will help point Kent State's scholars in the direction of the debate around these questions: Why did the Guardsmen fire? Why was no one held accountable in the courts?
And perhaps it might help students better understand why I and others who examined the hard, cold physical evidence concluded that murder may have been committed at Kent State.
William A. Gordon is a 1973 Kent State University graduate and the author of "Four Dead in Ohio" and three other books.
Rocks. Rocks. What Rocks?: A Damning Photograph Confirms Kent State Shootings Were Unnecessary
A brief write-up of Moments of Truth: A Photographer's Experience at Kent State, 1970. (Kent State University Press: 2019 ($34.95).
Howard Ruffner did something very clever in his just-published collection of photographs taken at Kent State just before and during the May 4, 1970 killings. Ruffner, a photographer and stringer for Life magazine (where some of his photographs originally appeared), enhanced his famous photograph of the Guardsmen turning and preparing to fire on the students. As Ruffner notes, his enhanced photographs show a complete absence of rocks by the feet of the Ohio National Guardsmen.
For those who are old enough to remember the campus killings, Ruffner's photographs just demolish the Ohio National Guards' claims that they were pelted with rocks and other objects before they fired to protect themselves from a lemming-like crowd of crazed students. Ruffner's photographs may be the most damning evidence that the Guardsmen did not tell the truth and the four fatalities did not deserve to be killed.
The rest of Ruffner's photographic memoir consists of a brief retelling of his background, a review of how he became one of the most important witness for the victims during both the criminal proceedings and a civil trial alleging wrongful death and injury. He also provides other photographs taken both before the shootings, and in its immediate aftermath, and in the four days following President Richard Nixon's announcement that he was sending combat troops into Cambodia, which many students considered to be an expansion of a hated war.
Ruffner's book is a welcome addition to the literature on the tragedy, and reminds us that while there might be plenty of "moments of truth," we still do not why a faraway war came home to America's campuses.
The Alan Canfora Story: The World's Oldest Living Student Radical (Part One)
After a 13-year lull, Alan Canfora has revived his campaign to damage my reputation and dissuade people from reading my book on the 1970 Kent State shootings. Not only is he trying to undermine my expertise, but he is also trying to intimidate me into silence. In doing so, he only succeeds in reminding us that he is his own worst enemy.
My book seems to infuriate him for a number of reasons, including the fact I am not on board with his attempts to wholly rewrite the history of the Kent State murders. As I see it, far from being a hero or a patriot (as he has variously described himself), Canfora was one of the bad actors who stupidly tested the limits of the National Guard's patience. He was the one person who emerged from the crowd of protestors, walked within 100 feet of the Guardsmen, and provocatively waved what his sister has described as a "black flag of anarchy," much like a bullfighter in a ring. While Canfora remains proud of his actions, there is little question that his recklessness put himself and his fellow students in danger. Perhaps not mortal danger (the Scranton Commission, after all, determined the shootings were "unnecessary, unwarranted and inexcusable"), but he made it much easier for the troops to pull the triggers, resulting in the deaths of four students and the wounding of nine others, including Canfora, who received a minor wound when was shot in the wrist.
My book also undoubtedly infuriates Canfora because I do not give a crap about what he repeatedly refers to as "our revolt." Like many college students at the time, I was opposed to the war in Vietnam but I certainly never joined a group advocating violence to end violence like Canfora's Students for a Democratic Society (SDS). I believe that if you commit a crime you should be prepared to do the time, and that everyone who committed crimes at Kent State (students and Guardsmen alike) should have been brought to justice.
If new evidence is to be believed, Canfora may have even participated in the destruction of the university's Army ROTC building two nights before the shootings. A new book, Fortney Road, devotes a chapter to Canfora's close buddy Thomas "Aquinas" Miller, a Kent State dropout, local drug dealer, and fellow member of the SDS offshoot "the Kent Krazies." The book reports that Miller told his brother John that he helped burn down Kent's ROTC building. Since Canfora and Miller seemed practically joined at the hip on May 4 (both waved the anarchist flags), it is not unreasonable to ask if Canfora joined his friend in the repeated attempts to burn down the building.
Canfora is no doubt also upset that I've been the first author to expose his four-decades-long record of either outright lying and/or deceiving the press and the public about all kinds of matters pertaining to May 4. No one else at the university dares to challenge or correct him whenever he starts propagandandizing, lest they receive the same treatment he has given me and numerous other people involved in the Kent State case.
In the recently released expanded e-book edition of Four Dead in Ohio I wrote:
"COMPULSIVE, HABITUAL OR PATHOLOGICAL?: Alan Canfora's disproven claim that the words, "Right here. Get set. Point. Fire," appear on the tape of the shooting was hardly the only time Canfora misled the public . . .
Another untrue statement Canfora made came under oath at the 1975 wrongful death and injury trial, when he testified he was never an activist or member of the SDS (Krause vs. Rhodes, Vol. 16, pgs. 3719 and 3727) . Canfora has since proudly admitted publicly that both of these claims are true.
In a January 18, 1982 interview for this book, he admitted to me that he lied to the FBI (again while under oath) when he told them that he was 50-75 feet farther away from the soldiers then he actually was. Canfora told me the reason he lied was because he was worried about being indicted by the state grand jury (which he ultimately was).
He also testified at the trial that he did not participate in the ROTC fire and only watched it from a distance of 400 feet (Krause v. Rhodes, page 3653). Canfora later referred to "our original crowd" (ProActivist.com, June 24, 1999), as if he were a leader, and [wrote] how "we were thrilled that about 2,000 students left their dorms and joined our anti-war march." In 2000 Canfora was even quoted by Erin Kosnac, a reporter for the the campus yearbook, the Burr, as saying he was in the "thick of things" during the pre-shooting protests, and that he was relieved that he was only indicted for second degree rioting. ("The Human Side of History," Burr, Spring 2000, p. 41). That admission strongly suggests he is still covering up his involvement in more serious crimes . . .
Canfora's lack of truthfulness at the 1975 wrongful death and injury trial so concerned Arthur Krause, the father of slain co-ed Allison Krause, that he confided to friends that he feared losing the case "because of Canfora's lying."
That is not all. Years later, Canfora conned William Canterbury, a reporter for the Akron Beacon Journal, into writing a front-page story that Universal Studios would, in 1997, make a major motion picture about his life ("Kent State tragedy heads for silver screen," Akron Beacon Journal, February 12, 1996). It turned out that all Universal did was option the rights to his still unpublished book, which he has claimed to have worked on since at least 1984 and which he has yet to produce. The proposed movie never went beyond the initial development stage and was abandoned by Universal long before Canfora eventually conceded the movie would not be made.
While Canfora had told reporters all he wanted was to find the truth about the shootings, and that he was not interested in revenge, he proved otherwise by establishing a web site, "Kent May 4th Central," on the 30th anniversary of the killings.
"Kent State May 4th Central also included a telltale link to his so-called "charity," the "Kent May 4th Center." Although Canfora denies any involvement in the establishment of the site, one does not have to be a linguist to recognize that "Kent May 4th Central" used language identical to what Canfora wrote in his other postings. "Kent May 4th Central" also included two telltale links: one back to Canfora's personal website and the other to his so-called "charity," the "Kent May 4th Center."
"Kent May 4th Central" published the names, home addresses, and in some instances the telephone numbers of the Guardsmen who were on Blanket Hill on May 4 and urged his fellow activists to visit these men at their homes, ask them questions, and take their pictures. It was essentially an invitation to harass the soldiers a full 30 years after the fact.
Canfora removed the site after a few days, presumably so the site's existence would not be traced back to him. However, as most readers know by now, once something appears on the Internet, it never can be completely erased.
Canfora was caught in yet another lie when he told reporters that as the "charity"'s director, he was volunteering his services for free. At the same time he made this declaration Canfora submitted a budget to the IRS (later made available to this author) indicating he intended to pay himself a salary of $30,000 a year.
Canfora also pretended to be a spokesman for the parents of the dead students and the other wounded survivors. While all of the parents wanted the soldiers who killed their children to be held accountable, none of them, as far as I can tell, gave a damn about his "revolt" or his glorification of student protest . . .
Canfora also fabricated out of whole cloth claims that I was "the National Guardsmen's best friend," despite the fact I did more than he did to get the soldiers prosecuted. He also falsely claimed on his website that I was in cahoots with the author of another book on May 4, Pulitzer Prize-winning author Philip Caputo (whom I've had no contact with). And he maliciously repeats his fabricated claim that I was a disruptive person and was thrown out of meetings between the victims and their attorneys during the 1975 civil trial. It never happened. While it is true that I had attended earlier strategy meetings before the litigation started, I never attended any of the attorney-client trial meetings Canfora referred to. Moreover, I have never been thrown out of a meeting in my life or been involved in a disruptive event. I am simply not that type of person.
The "disruptive" tag, however, fit Canfora himself like a glove, and I have long noticed how he projects his own worst qualities onto others whenever he fights with them.
(Part One of Canfora at the bottom of the page)
Firefox https://outlook.office.com/mail/inbox/id/AAMkAGQxNjkyMTRlLT...
5 of 6 9/23/2022, 4:38 PM
POSTSCRIPT: When Canfora claimed the words "Right here. Get set. Point. Fire," were on the tape of the shootings, he deceived reporters by claiming those words were confirmed by an acquaintance of his, Ian MacKaye of the rock band Fugazi. MacKaye had enhanced the tape as a favor for Canfora, using his band's sound equipment, not the more sophisticated state-of-the-art tools later used by Stuart Allen. Mackaye later told me never heard the words Canfora attributed to MacKaye, which means Canfora's so-called "discovery" was either wishful thinking on his part or an outright purposeful hoax. After Canfora's death in 2019, the university subsequently honored Canfora for his activism. Poor Kent State. It never figured out that it had been conned.
(End of Part One. Part Two to follow.)
Kent State Audio Experts Allege FBI Lab's Analysis of Tape Based on 'Beyond antiquated' software
 The FBI has finally released a summary of its report showing how it tested the tape of the Kent State shootings, and the summary confirms that the tests used to dispute two audio experts' claims that there was a "prepare to fire" order were based on technology that is "beyond antiquated."
That is what audio forensics expert Stuart Allen told me after I read to him the summary the FBI report made available after numerous Freedom of Information Act requests. The report states that the FBI used RAP-R 2, SoundForge3, AvidPro Tools, AdobeAudition3, and ES-4 as opposed to SoundForge10 and the more advanced Russian S.I.S. Sound Cleaner. Allen's fellow forensics expert Tom Owen similarly dismissed the FBI's tools as "off the shelf vendor stuff" that cannot replicate the results Allen and Owen obtained.
At issue here is whether or not a command "prepare to fire" was issued by someone in the Ohio National Guard shortly before the troops fired into a crowd of protestors at Kent State on May 4, 1970, killing four students and wounding nine others. The soldiers denied under oath at the 1975 civil trial that any such orders were issued, and if Allen and Owen's interpretations are correct, it means at a minimum there was extensive perjury at the trials. Some survivors of the May 4, 1970 tragedy believe that it also proves the Guard committed murder. A presidential commission in 1970 concluded the shootings were "unnecessary, unwarranted, and inexcusable."
Although most of the contributing causes of the May 4, 1970 killings have been identified, the precipitating cause remains the subject of debate. The controversies surrounding the killings are not acknowledged in the university's new May 4 Visitors Center, which will be celebrated this Saturday, the 43rd anniversary of the killings, with panel discussions and a speech by filmmaker Oliver Stone.
Professor Jerry M. Lewis: The Saboteur of Kent State Tries to Discredit a May 4, 1970 Victims And Rivals Alike
There is a professor at Kent State who has a rather nasty habit of sabotaging anyone he perceives as a professional threat. Although he does not dare say anything publicly, he has been quietly trying to discredit his competitors by claiming their work is riddled with errors.
For example, in 1990, when American History Illustrated published a 20th anniversary article he wrote, he tried to convince Geneva Politzer, the magazine's editor, not to publish an accompanying article by freelance writer Lesley Wischmann. The professor vehemently claimed her article contained numerous errors of fact. Politzer then asked Lewis to prove his claim by itemizing these supposed mistakes. When push came to shove the professor had to back down and admit he could not even cite one single example. Wischmann's article was subsequently published and, would not you know it? Neither I nor anyone else found any errors or problems with anything she wrote.
Word also reached me that the professor emeritus, Jerry M. Lewis, has been conducting a whispering campaign against my book, making the same unsubstantiated charges. Again, he would only talk in generalities and could not cite one single example. It was, of course, deliberate slander, pure and simple.
One of the reasons Lewis' lies infuriated me is that I take great pride in my journalism. In the 22 years since my book was originally published, no one--not a single scholar, journalist, or groupie--has ever identified any error of fact, either significant or nitpicking. No one has ever claimed I misquoted them or did not accurately report what was in any historical documents. No one has ever suggested that I was less than conscientious with the mountains upon mountains of raw material that attorneys deliberately created and preserved for historians to study. And, of course, I am still the only chronicler of this event who has actually studied and written about them.
The failure to find errors in my book is something that cannot be said about most other books about the killings, including books by two Pulitzer Prize winners, James Michener and Philip Caputo. Kent State professors, fellow journalists, and attorneys for the defendants found numerous problems with Michener's reporting, and Caputo committed a few sloppy errors that his more radical critics blew out of proportion because he was not one of them.
I have no problem with people disagreeing with my conclusions. May 4 certainly was not a black-and-white case, and disagreements are to be expected any time a writer tackles a highly controversial cause celebre. But as far as my basic reporting is concerned, I feel I deserve to be commended for treating an enormous body of evidence in such a conscientious manner. Instead, I found myself the subject of a smear campaign, and I do not like it one bit.
A few things need to be said here. First, Lewis has several reasons to be unhappy with my book. Not only did I not praise his scholarship, but I skewered his tortured subdisciplinary reasoning for recommending the main campus memorial be built. While others felt the memorial was needed because four students were killed in a tragedy a presidential commission called "unnecessary, unwarranted, and inexcusable," Lewis felt a memorial was needed because it "sensitized America to regimented lines of communication and authority. May 4 changed forever how future demonstrations--peaceful or otherwise--must be perceived, analyzed, understood. and settled nonviolently."
I also ridiculed him and his colleagues for their obstinate refusal to acknowledge the real debate. I also did not feed his supersized ego. One year Jerry, apparently confusing himself with a celebrity, actually gave his students a handout of his schedule of his upcoming TV appearances.
And perhaps most importantly, my book contains some highly embarrassing revelations about the ethically challenged professor. On pages 256 and 257 of the paperback edition, the book reveals how, in just a matter of a few days, Lewis politically shapeshifted from a champion of campus radicals who opposed a federal grand jury investigation, to someone who voluntarily became a secret informant against the victims. Jerry briefed then KSU President Glenn A. Olds about a confidential meeting among the victims in which their legal strategy was discussed. Four Dead in Ohio discloses a document I discovered in the archives which demonstrated this happened at a time when the victims were suing the university. It was akin to someone infiltrating a legal defense. Jerry did this after he spoke out in defense of the radicals who opposed the grand jury investigation (which the victims sought), and was roundly humiliated by Arthur Krause, the father of slain student Allison Krause, who exploded: "Jerry, that is the stupidest thing I've ever heard!" Lewis kept quiet for the rest of the meeting, but he later retaliated against Krause by briefing Olds and again later by telling me that Krause was crying on cue during a television interview, as if Krause was faking his grief.
And, of course, Jerry has also been threatened by my research. I did not quite understand why he urged me so strongly to give up seeking publication until the president of a U.S.-Canadian textbook distribution company told me that my book was perfect for classes in "Social Problems." That happens to be Lewis' field of expertise. Incidentally, he assigned his own May 4 textbook in that class. Jerry will not be happy to hear that my book has been adopted for classes at nine or ten universities.
I hope there are a few professors at Kent who are wise enough to challenge Lewis the next time he pulls this crap. As far as I am concerned, he is shamelessly intellectually dishonest. And an absolute disgrace to his profession.
My recommendation for a new word in The American Heritage and other dictionaries:
to "jerrylewis" someone
Definition: To sabotage one's competitor, especially one who has far surpassed his own work.
Yes, he wants to be the leading expert on the Kent State shootings so badly that I am going to oblige him. I intend to make him into a household name.
The FBI Disputes The Claim There Was an Order to Fire at Kent State
The Plain Dealer published another front-page story today, and this one threw cold water on the audio experts' claim that they could discern an order to fire on the tape of the Kent State shootings. Apparently the Justice Department quietly asked the FBI to re-examine the Terry Strubbe tape, even though it already closed the case almost two years earlier. The FBI's experts supported Justice's decision by referrng to the previous evaluation of the tape conducted 38 years ago. That earlier analysis concluded that rather than demonstrating a clear order to fire, the voices on the tape were unintelligible. The FBI's analysis also conveniently exonerated FBI informant Terry Norman by claiming the sounds that Stuart Allen concluded were gunfire were actually the closing of doors in Strubbe's dorm room.
Almost immediately after the story hit the papers, Cleveland Congressman Dennis Kucinich asked the Justice Department to release the FBI's complete report on the tape so it could be determined whether the FBI used the same advanced technology that Stuart Allen and Tom Owen used when it reached completely opposite conclusions. Allen denounced the FBI's conclusion as beyond ludicrous and there seems to be some question as to whether or not the FBI, in analyzing the tape, relied on the outdated 1974 study. In other words, we do not know whether the FBI compared apples to apples or apples to oranges.
I will have more on this latest development once the details of this FBI analysis is released. In the meantime, John Mangels' story in the Plain Dealer can be found at:
www.cleveland.com/science/index.ssf/2012/04/justice_department_wont_re-ope.html
A Plain Dealer editorial arguing for the need for "a full and proper investigation of the tape's contents" can be found at:
www.cleveland.com/opinion/index.ssf/2012/04/close_official_examination_of.html
Kent State Shooting Developments: A Few Odds and Ends
After I wrote the article about Stuart Allen, saying he detected a second and actual order to fire (which no newspaper in the country, including the Daily Kent Stater, covered) I heard from John Mangels, the Plain Dealer's science reporter. Mangels was the author of the three front-page stories that gave rise to the calls for a new investigation. That made him, as far as I am concerned, one of the unsung heroes of May 4. He reminded me that he interviewed Captain Ron Snyder for his initial story on May 9, 2010, and that Snyder (like Captain Martin and Sergeant Matthew McManus) challenged Allen's finding, claiming the preliminary order did not sound like an order someone in the military would give.
That had completely slipped my mind, probably because Ron "Cynanide" Snyder is not a source I ever gave much credence to. That is partially because Snyder was not even among the squad that opened fire that day and thus, was not in a position to know what really happened. His unit was on the other side of Taylor Hall when the shootings broke, and the building completely blocked his view.
Also, I still cannot get out of my head something said about Snyder after he originally told author James Michener, the Akron Beacon Journal, and a state grand jury that he confiscated a gun and brass knuckles off the body of slain student Jeffrey Miller. Snyder subsequently admitted he fabricated this claim because he wanted to make the victims seem dangerous, thereby making the shootings look justifiable. Snyder decided to come clean after the Justice Department started investigating this claim. I saw papers on Judge Frank Battisti's law clerk's desk suggesting the Justice Department seriously considered indicting him for perjury before the original state grand jury.
I once had a beer with the editor who directed the ABJ's coverage, and he told me: "If he told me his name was Snyder, I still would not believe him."
Snyder, incidentally, once guest lectured to my class in criminal justice at Kent in the spring of 1973. In a case of bad timing, I only found out about it afterwards. I had played hooky that day . . .
Another interesting but not exactly earthshattering item: A few weeks ago I received a letter from the Justice Department's Freedom of Information office in response to an appeal I made for any records showing that the Justice Department did anything when they were asked to reinvestigate the new evidence. The Department's appeals division ignored part of my request and claimed they had no records of any such requests for reinvestigation, even though Justice Department officials met with a wounded survivor, other former students, and their attorney in May 2010. The Department's position--that there never were any calls for reinvestigation, and that no records ever were kept of this meeting, sounded highly suspicious to me.
If the Department was telling the truth, that meant that all the public calls for a new investigation were made for publicity purposes, not to get the investigation. The wounded survivor I mentioned used to repeatedly get headlines by calling for additional investigations. Should not have he have made a formal request in writing? And did he and the others already understand that the only statute that still could be used to prosecute the Guardsmen--homicide--is a state, not a federal crime? The truth is there was not anything the Justice Department could have done anyway, save perhaps ask the National Academy of Sciences to review the tape and provide a second opinion . . .
Finally, I recently received an e-mail out of the blue from a former Colorado National Guardsmen. He sharhed that that, after watching a film about riot control just before the campuses blew up in May 1970, "we all agreed that, if faced with a riot, we would set our M-16s on rock & roll (full automatic) and mow the protestors down."
This dovetailed very closely with a story that a then Kent State student, told the FBI a year after the tragedy. The student claimed he hitched a ride from someone who told him he was one of the soldiers that fired at the students and that the troops had discussed shooting students before it actually happened. Unfortunately, the hitchhiker was only able to provide the FBI with very sketchy information about the soldier and his car. The FBI never was able to identify him, and that line of inquiry was never pursued by the attorneys who filed wrongful death claims against the Guardsmen.
The letter at least reminded me of the mindset of many of those upholding the law--as well as many in the general public--in May 1970. The war and Kent State divided the country more deeply than any other time since the Civil War. As Time magazine reported even a year before the shootings , there was a sentiment throughout the country that when it came to the antiwar demonstrations, "enough is enough."
The Kent State Shootings: As Another Anniversary Approaches, Kent State Does Something Right . . . While Making Another Dopey Move
Recently, when I returned to Ohio and spent half a day in Kent, I was pleasantly surprised to find the new markers for the May 4 walking tour. The markers showed visitors how the events of May 4, 1970 unfolded and acknowledged what the university could not bring it itself to say for almost 40 years: that the killings were "unnecessary, unwarranted, and inexcusable." That was the principal conclusion of The President's Commission on Campus Unrest, and probably the most significant piece of information that today's students and visitors to the campus should know. Previously, that conclusion only appeared on a state of Ohio plaque erected 37 years after the fact. I suspect the only reason that came about was because I wrote several op-ed columns for Cleveland's Plain Dealer scolding the university for not previously acknowledging that no one should have been killed.
I also felt the new markers, spread out around the perimeter of Taylor Hall, were a major improvement over Kent State's official memorial, which bears only a platitude: "Inquire, learn reflect." Kudos to faculty members Laura Davis and whoever arranged for the markers to be built. The markers were mostly overlooked during last year's 40th anniversary coverage, and it was about time that the KSU faculty did something worthwhile to preserve the memory of May 4 . . .
Unfortunately, the university appears to be on the verge of committing another blunder by demonstrating that after all these years, it still does not have a very good handle on what the tragedy was all about. When I was in Kent, I saw the tentative plans for the proposed May 4 Visitors Center. Even though parts of it looked promising and well thought through, the university appears to be still ignoring the victims' decade-long struggle for justice for those killed. I have long felt that the university was trying to negate everything the victims worked for by acting as if the issues of justice, accountability, and getting clearer answers to the central question of why the triggers were pulled, were of little or no consequence. Those issues may not have been important to the university faculty and administration, but personally I think those were the primary reasons to even remember May 4. The tragedy turned into one of the most sustained injustices in modern American history. No one was ever held accountable for the many crimes committed at Kent.
There is also a room discussing the historical context of the killings, centering around the theme: "Kent State raised awareness about the Vietnam War." That has to be one the dopiest things anyone has ever said or written about May 4. There are professional historians on the Visitors Center committee, and one wonders why none of them pointed out that the war was so unpopular two years earlier, that President Lyndon Baines Johnson decided he could never be elected for a second term. Or that Bobby Kennedy and Eugene McCarthy competed for the Democratic presidential nomination, both basing their campaigns on their opposition to the war. Even Richard Nixon ran and won the presidency with a promise that he had a "secret plan" to end the war; which, of course, he did not.
Not only that, the historians must have completely forgotten about the riots at the 1968 Democratic Convention in Chicago, and the huge antiwar anti-war protest in Washington, D.C. in fall of 1969, and all the previous protests on campuses. To say that Kent State "raised consciousness" about the war is to trivialize every single major historical event that preceded it. America did not need Kent State to learn about the war. It was already the front and center national issue for more than two years.
To avoid looking foolish, the university needs to go back to the drawing board. Why cannot it just say "Kent State brought the war home"? At least it has the virtue of being a fact.
Next Entry August 10, 2011


text:
This is how the Air Force prevented a coronavirus outbreak at basic military training
By Meghann Myers
JOINT BASE SAN ANTONIO, Texas ― It was early April and the mlitary services had a choice to make: Do we shut down initial entry training and risk our end strength numbers for years to come, or do we power through the COVID-19 pandemic and try to keep these close-quarters hordes of young people as safe and healthy as possible?
At Air and Education Training Command, officials decided to take a week to shut down and reset, then come back, nearly full-steam ahead with some key modifications.
"We directed our [military training instructors] to graduate a class one week early. They trained through the weekend, they met training objectives," Maj. Gen. Andrea Tullos, who commands 2nd Air Force, told Defense Secretary Mark Esper on Tuesday at Lackland Air Force Base. "At the same time, we told the recruiters: Don't ship."
The modified BMT went from about 800 trainees per flight to between 400 and 480, allowing for smaller groups in classroom instruction and some room to space out in housing bays with about 40 trainees, rather than 60. The service has instituted deep-cleaning protocols, mandatory mask usage and cots arranged with pillows alternating on the left or right, so no one is in each other's breathing radius while in bed.
Defense Secretary Mark Esper is shown Air Force trainees' sleeping area. The head of the cots alternate so recruits can avoid each other's breathing space as much as possible. (Meghann Myers/Staff)
BMT also streamlined the uniform issue process. Rather than moving trainees through indoor stations to get each piece of clothing and pair of shoes, they are shuffled outside to pick up a pre-packed bag of items according to their sizes
After two weeks, the "restriction of movement" phase ends and they can get into more training around the base, including preparing for Basic Expeditionary Skills Training, in which a field test is required to graduate.
For extra space, as well as quarantine facilities, a tent city went up in a parking lot on base. There, trainees who tested positive, and their close contacts, could spend two weeks in isolation. But otherwise, Air Force indoctrination went mostly as normal, with less down time and some sections shortened, like time spent on military drill and ceremony.
The first two cohorts that went through BMT after mid-March had five confirmed cases of coronavirus, Maj. Gen. John DeGoes, head of the 59th Medical Wing, told Military Times. At that point, tests were only available for symptomatic trainees who could confirm close contact with a diagnosed case.
Since that point, and post-reset, there have been 30 more positive trainees, 29 of whom were asymptomatic at the time they were tested. That's about a 0.5 percent infection rate in the 3,500 trainees who have gone through BMT since the beginning of the pandemic.
Testing protocols have evolved, from symptomatic-only to pre-graduation testing, to now arrival testing as well.
This is different from how some of the other services have approached it. For example, Marine Corps Recruit Depot Parris Island, South Carolina, puts trainees into full isolation for the first two weeks, focusing mostly on training that can be done via reading and virtual instruction.
Chief Master Sgt. Ramón "CZ" Colón-López (left), senior enlisted advisor to the chairman of the Joint Chiefs, and Defense Secretary Mark Esper (right) are briefed by Maj. Gen. Andrea Tullos, 2nd Air Force commander, at Joint Base San Antonio-Lackland, Texas, June 16. Esper met with Air Education and Training Command leaders to see how Basic Military Training is fighting through COVID-19 with health protection measures and by operational adaptations. (Sarayuth Pinthong/Air Force)
They are then tested and sent into their regular facilities if cleared. If not, it's back into isolation for two more weeks, along with their close contacts, like roommates.
At Parris Island, with between one and three cases per 200- to 300-person cohort ― Marine Corps officials have declined to give an exact number ― the infection rate is roughly, 0.6 percent. on par with the numbers nationwide.
Building a better boot camp: How to make Marines during a pandemic, and beyond
The coronavirus pandemic might've permanently changed the way the military molds new recruits.
At Lackland, DeGoes said, the last symptomatic trainee reported on April 7, but didn't show any symptoms until April 20. Since then, early screening and quarantine have caught any cases, and there has been no community spread, either to other trainees or to MTIs.
"I think the secret to our success … the testing before and after helps, but what really prevents an outbreak from occurring is the training instructors having a safety approach," DeGoes said.
And by that, he means MTIs imploring trainees to speak up if they are feeling the least bit sick.
"Traditionally it was, cooperate and graduate," he said, meaning that trainees with a sore throat or sniffles might be encouraged to power through, lest they be held back and recycled.
Now, they are warned that their symptoms might not just hold up their own careers, but could mean quarantines and illnesss spread for their fellow trainees.
About Meghann Myers
Meghann Myers is the Pentagon bureau chief at Military Times. She covers operations, policy, personnel, leadership and other issues affecting service members.
Air Force Basic Military Trainingmilitary recruit trainingLackland Air Force BaseJOINT BASE SAN ANTONIOAir Education and Training CommandCOVID-19Chief Master Sgt. Ramón "CZ" Colón-LópezDefense Secretary Mark EsperMaj. Gen. Andrea Tullos2nd Air Force

redpajama_set_name: RedPajamaCommonCrawl


Theatre challenges, questions and inspires. What better reason to take to the stage than to want to make a difference? Theatre can be a powerful tool used to communicate an important message.
Every performer loves to take to the stage for a final number. Theatre is a brilliant way to boost confidence and self-esteem in children and adults alike, and dance is probably one of the most expressive elements of performance.
Who wouldn't want to deliver unforgettable text and perform in timeless classics? From William Shakespeare to Arthur Miller, there have been so many different and wonderful playwrights over the years, each with their own strengths and style. The theatre is a never-ending playground, and being able to be able to deliver lines from some of history's greatest lyricists is something worth celebrating.
The theatre boasts a never-ending array of characters to play; characters that make us laugh and cry, holler and jeer, and every time you get a new script, you get the opportunity to explore an exciting new character. What could possibly be better than that?
We just can't get enough of it! From the roar of the audience to the smell of the greasepaint, there is nothing else in the world like the theatre and we love it.
For more information on Jigsaw's weekend drama, singing and dance classes or to book a two week trial, visit www.jigsaw-arts.co.uk or call 020 8447 4530.


Historic moments in Florida's outdoor recreation history, from the building and opening of trails to the founding of parks and public lands.
At Spanish Point, scents hang heavy in the morning air: a moonflower in the act of closing for the day, the sweetness of citrus blossoms, the purple morning-glory clambering over mangroves, the brush of salt breezes.
National Trails photographer Bart Smith is poised to wrap up 16 years of hiking ALL of the National Scenic Trails in America, and with that feat, launch a new website to tell his story through his photos.


text:
Not so Different
Haseeb Abbasi
Before the age of 8, Haseeb was non-verbal and did not respond when called. In school, he often sat alone, avoided eye contact, struggled to communicate, and had meltdowns. At 12 years old, he was diagnosed with autism. It was then that his mother enrolled him in a special education school where he passed his secondary school examinations and secured a scholarship.
He was introduced to the world of sports by a Special Olympics Pakistan coach. He also spoke publicly for the first time at a Special Olympics event and has not looked back since. In 2013, he competed in the SOAP Regional Games held in Australia. After his victory on the track, he picked up road cycling and trains regularly with professional coaches.
Haseeb's achievements have gone beyond the world of sports. At 17, he made it to the TEDx stage, where he earned a standing ovation. He recently published a book chronicling stories of people with intellectual disabilities and has been visiting schools across Pakistan to share these stories. He is also the host of two TV shows in Pakistan where he advocates for people with intellectual disabilities and fights for a more inclusive community. He is now in the midst of completing his diploma in special education.
Brina Kei Maxino
Jasmine Sharif
Hanako Sawayama
Aliyah Hidayah
Isabela Dominique (Sashi) Montaña
Syeda Eraj Batool Zaidi
Jack Green
Simran Sahni
Satyananda Kusuma
Benjamin Haack
Read more about us:
Copyright © 2020 Special Olympics Asia Pacific


text:
Tractor Trailer Smashed to Pieces by Train
Dylan Cautela | January 25, 2017
A cruiser for the North Salt Lake Police Department captured dash cam footage of a passenger train barreling through a tractor trailer midway through crossing some train tracks during yesterdays snowstorm. The trailer behind the truck was smashed in half with boxes strewn all over the scene. Fortunately, neither of the drivers in the truck were injured nor were any of the 82 passengers and crew of the train.
Utah Transit Authority (UTA) released results of their preliminary investigation today. They state that the railroad crossing gates and arms were up and not flashing during the time of the incident. Reports of power outages and severe icing had occurred in the area prior to the incident with the UTA responding to fix the problems because of traffic backups. Shortly after the crews arrival to the scene the crossing gates went up and that was when the accident occurred.
"The agency has never had an accident like this before, and UTA is investigating why and how it happened to ensure it doesn't occur again."
–Utah Transit Authority
Terrifying accident, which fortunately didn't cause any injuries. Source; ABC News.
One thought on "Tractor Trailer Smashed to Pieces by Train"
Alpine Jeff says:
What is this crap? Has Snowbrains been sold? Just because there is snow on the ground doesn't mean we want to see this shit. What's the deal?
This site has taken a turn for the worse. Miles did you sell the site? Why is Snowbrains posting junk News stories? It really seems like this site is mirroring Unofficial Networks now. Good luck
Dylan Cautela
Born and raised in the state of Maine, sculpted from ice and built to rip! When I'm not at work playing in the dirt or braaaappping the old chainsaw I enjoy hiking, biking, skiing, and the general great outdoors. There is ample beauty to be explored in my great home state (and all around the east) but most days I find myself yearning for the adventure of the wild wild west and foreign countries unknown, which happen to be my winter playgrounds.


After the big Super Bowl party it seemed like the whole house needed a good cleaning. Such fun with family and friends, but parties seem to take over the entire house. As I was cleaning, I though it was time to change a couple of things.
I am totally in love with my new DIY Painting Makeover. I loved the art that my daughter loaned me, but I am so happy I found this piece and was able to do a little makeover to make the colors perfect for my home.
It is so light and fresh for this space.
This huge cloche always makes such a fabulous statement.
I sometimes like to have the table set for dining and then sometimes I like it with just a simple centerpiece of candles and flowers. I especially love the wheat and large candlesticks.
Since I borrowed the large candlesticks from the coffee table I needed something to replace it with. I thought my Thinking Man was perfect. He's studying the chess game.
Do you switch things up every time you clean too?
ha...i love that thinking man and how you have him strategically placed near the chess board.
What paint did you use on your painting? Can you see any difference in the sheen?
I used several colors of craft paint I had on hand. I didn't cover huge areas of the painting, just the places that had a lot of blue. No, I can't tell any difference in the sheen.
You are so talented at mixing traditional, vintage and modern. The painting is beautiful, you really made it your own work!
Looks great, Marty! Yes, I am always switching things around...which is probably why I am always losing things! lol. Have a great day!
I have a gold basket similar to the one on you foyer table. Do you ever put anything in yours? I haven't like much in mine except Christmas ornaments and greenery.
I did have some ornaments at Christmas, but that's about it. I love seeing it empty, such a pretty design.
Sounds like you hosted a fabulous party, my friend. I am so incredibly obsessed with your artwork. So gorgeous!
How clever! I love your spaces, so bright and inviting.
I have been on the hunt for a tall cloche for a while and ne re can find one. Your thinking man does look like he's watching the chess game.
Love the entryway makeover. I like the glass cloche, gold bowl and the candlesticks added by the lamp. Your dining table looks lovely and I really like the thinking man staring at the chess set!
I do the same thing when I give the house a good cleaning! Just swapping in/out different accents, throw pillows, throws can often give a room a whole different feel!
I love changing up things I have to give a room a whole new look too. I like to do a deep cleaning closer to Spring. Feels good when you can fling open windows here in the midwest and clean everything. Have a great rest of the week.
I like it all but especially the abstract art in the entry. I'm curious as to what you did to make it over.
The painting had several different places with blue in it and some of the brown was really dark, so I took some craft paints and painted over it with a mix of colors to make it fit my color scheme. I did a complete post about it.
How elegantly you have styled the vignette within.
for me it is more with each Season of the Year.
I do admire the change on your dining room table.
I don't switch things up EVERY time I clean, but sometimes when I do a deep clean of a room, I do. It's funny that I don't really like cleaning all that much, but I actually LOVE deep cleaning! ha I love that entry table--the gold is stunning.
Marty, I love your refresh! The large cloche is truly a statement piece as well as the thinking man! I don't change things as often as I used to.
So nice Marty!I love the old books under the glass cloche and the Thinker statue with the chess game!


The measurement of the intensity of a wave propagating in a random medium results in a random signal response, the statistical properties of which are functions of the radiation wavelength and the ratio between the characteristic scale of the spatial intensity pattern and the size of the receiver aperture. In this paper, using multiscale solutions for high-frequency random propagators, we construct expressions for the integral intensity correlation measures that allow us to obtain the spectral intensity correlation characteristics and to analyze their variations as functions of wavelength separation and detector aperture. Numerical results are presented for a plane wave propagating in random media that are characterized by a Gaussian spectrum and by a power-law spectrum of the refractive-index fluctuations.


Sort of. Well the weather has been pretty odd for the last year at least. It was warm during the winter (for Hamamatsu), and then the first couple of days of March were downright cold! But now the rain has come and with it a bit warmer weather. I've seen cherry blossoms blooming here and there, and my ears were filled with birdsong early this morning. I think it's a sign of warmer days ahead.


text:
The original item was published from 6/16/2022 11:39:16 AM to 8/6/2022 5:05:04 PM.
[ARCHIVED] Areas of Coconino and Kaibab national forests to close this weekend
Areas of Coconino and Kaibab national forests
to close this weekend
FLAGSTAFF, Ariz., June 16, 2022 – Coconino and Kaibab national forests will temporarily close certain areas to public access beginning Friday and Saturday due to fire danger and for public safety, while all other parts of the national forests outside of the closure areas remain in Stage 2 fire restrictions.
On the Kaibab National Forest, the area of Bill Williams Mountain will be closed beginning Friday, June 17 at 8 a.m. Specifically, public access will be prohibited on all National Forest System lands, roads, and trails within the closure area, generally located between County Road (CR) 73, Old Route 66 in the City of Williams, Forest Road (FR) 122, FR 108, and I-40. This includes Benham Trail, Bixler Saddle Trail, Bill Williams Mountain Trail, Bill Williams Connector Trail, Buckskinner Trail, City of Williams Link Trail, Devil Dog Loop Trail, and Clover Spring Loop Trail. Forest Road 122 will also be closed. FR 108 will remain drivable; however, motorists cannot park off the road.
On the Coconino National Forest, the areas of Pumphouse Wash/Kelly Canyon and Fisher Point/Walnut Canyon will be closed beginning Saturday, June 18 at 8 a.m. This includes Pumphouse Wash Dispersed Camping Area, Forest Road (FR) 237 and other roads within the Pumphouse Wash closure area. In the Fisher Point/Walnut Canyon closure area, all forest roads and recreation sites within the area will be closed. This includes Fisher Point, Marshal Lake, portions of the Arizona National Scenic Trail, Canyon Vista Campground, Sandys Canyon Trail No. 137, and more.
These area closures are in addition to the already-implemented emergency closure of most of the Coconino National Forest north of Interstate 40. For the official Closure Order and a map of this area, please see the official Closure Order.
With regards to both national forests, those with private inholdings will be allowed to access their property via a Forest Service Road but are prohibited from entering the surrounding National Forest lands. Exemptions will be issued for critical activities such as road work and surveys that are vital to continuing restoration operations, time-sensitive utilities and communications site work, and emergency response.
Forest managers consider several factors before implementing restrictions or closures, including current fire danger and fire activity, local, regional and national fire preparedness levels, expected weather conditions, availability of firefighting resources, and the economic impacts to businesses and communities. All northern Arizona national forests coordinate fire restrictions and forest closures with federal, state, tribal and local partners.
Closures are generally the last resort for land managers, who take many other steps to reduce the potential for human-caused fires and often consider closing only the most critical areas before a full forest closure. As such, additional area closures or even full forest closures could be forthcoming if conditions warrant.
Closures and restrictions will be in effect until hot, dry conditions are no longer forecast to continue and the forests receives enough widespread precipitation to lower fire danger.
For details and maps of these specific closure areas and their boundaries, visit the following pages online:
Coconino National Forest closure area- Pumphouse Wash/Kelly Canyon
Coconino National Forest closure area- Fisher Point/Walnut Canyon
Kaibab National Forest closure area- Bill Williams Mountain
Forest Service personnel will make every effort to notify anyone in these areas to vacate before the closure is implemented.
Violating closures and fire restrictions carries a mandatory appearance in federal court, punishable as a Class B misdemeanor with a fine of up to $5,000 for an individual or $10,000 for an organization, or up to six months in prison, or both.
For information on all Arizona state and federal fire restrictions, including an interactive map, visit wildlandfire.az.gov/fire-restrictions. Additional information about the stages of fire restrictions, Forest Orders, and general forest conditions can be found at fs.usda.gov/kaibab and fs.usda.gov/coconino.
USDA is an equal opportunity provider, employer and lender.
Other News in Schultz/Pipeline Flood Area
Coconino County Flood Control District Approved For $90 Million in Federal Funding


As President of RBS and RBS Evolution, Greg shares responsibility with the CEO for the development, growth, and management of both companies as well as our radiation oncology centers. Greg has over 20 years of administration and leadership experience in the healthcare industry.
He most recently served as President and Chief Operating Officer of Radiation Oncology Services of America, a joint venture company with 17 freestanding radiation oncology centers owned in partnership with physicians. Greg holds a Bachelor of Business Administration degree from Appalachian State University, and an MBA and MSHA from University of Alabama at Birmingham.


Address: pune, Ahirwade, Pune, Maharashtra, India.
This Broker Profile page for "Tarik Real Estate" has been created by PropertyWala.com. "Tarik Real Estate" is not endorsed by or affiliated with PropertyWala.com. For questions regarding Broker Profiles on PropertyWala.com please contact us.


text:
//  ---------------------------------------------------------------------------
//
//  @file       TwOpenGLCore.cpp
//  @author     Philippe Decaudin
//  @license    This file is part of the AntTweakBar library.
//              For conditions of distribution and use, see License.txt
//
//  ---------------------------------------------------------------------------

/*
#pragma warning GL3             //// used for development
#define GL3_PROTOTYPES 1        ////
#include <GL3/gl3.h>            ////
#define ANT_OGL_HEADER_INCLUDED ////
*/

#if defined ANT_OSX
#   include <OpenGL/gl3.h>
#   define ANT_OGL_HEADER_INCLUDED
#endif
#include "TwPrecomp.h"
#include "LoadOGLCore.h"
#include "TwOpenGLCore.h"
#include "TwMgr.h"

using namespace std;

extern const char *g_ErrCantLoadOGL;
extern const char *g_ErrCantUnloadOGL;

//  ---------------------------------------------------------------------------

#ifdef _DEBUG
    static void CheckGLCoreError(const char *file, int line, const char *func)
    {
        int err=0;
        char msg[256];
        while( (err=_glGetError())!=0 )
        {
            sprintf(msg, "%s(%d) : [%s] GL_CORE_ERROR=0x%x\n", file, line, func, err);
            #ifdef ANT_WINDOWS
                OutputDebugString(msg);
            #endif
            fprintf(stderr, msg);
        }
    }
#   ifdef __FUNCTION__
#       define CHECK_GL_ERROR CheckGLCoreError(__FILE__, __LINE__, __FUNCTION__)
#   else
#       define CHECK_GL_ERROR CheckGLCoreError(__FILE__, __LINE__, "")
#   endif
#else
#   define CHECK_GL_ERROR ((void)(0))
#endif

//  ---------------------------------------------------------------------------

static GLuint BindFont(const CTexFont *_Font)
{
    GLuint TexID = 0;
    _glGenTextures(1, &TexID);
    _glBindTexture(GL_TEXTURE_2D, TexID);
    _glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
    _glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
    _glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    _glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
    _glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
    _glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    _glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, _Font->m_TexWidth, _Font->m_TexHeight, 0, GL_RED, GL_UNSIGNED_BYTE, _Font->m_TexBytes);
    _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    _glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    _glBindTexture(GL_TEXTURE_2D, 0);

    return TexID;
}

static void UnbindFont(GLuint _FontTexID)
{
    if( _FontTexID>0 )
        _glDeleteTextures(1, &_FontTexID);
}

//  ---------------------------------------------------------------------------

static GLuint CompileShader(GLuint shader)
{
    _glCompileShader(shader); CHECK_GL_ERROR;

    GLint status;
    _glGetShaderiv(shader, GL_COMPILE_STATUS, &status); CHECK_GL_ERROR;
    if (status == GL_FALSE)
    {
        GLint infoLogLength;
        _glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); CHECK_GL_ERROR;

        GLchar strInfoLog[256];
        _glGetShaderInfoLog(shader, sizeof(strInfoLog), NULL, strInfoLog); CHECK_GL_ERROR;
#ifdef ANT_WINDOWS
        OutputDebugString("Compile failure: ");
        OutputDebugString(strInfoLog);
        OutputDebugString("\n");
#endif
        fprintf(stderr, "Compile failure: %s\n", strInfoLog);
        shader = 0;
    }

    return shader;
}

static GLuint LinkProgram(GLuint program)
{
    _glLinkProgram(program); CHECK_GL_ERROR;

    GLint status;
    _glGetProgramiv(program, GL_LINK_STATUS, &status); CHECK_GL_ERROR;
    if (status == GL_FALSE)
    {
        GLint infoLogLength;
        _glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength); CHECK_GL_ERROR;

        GLchar strInfoLog[256];
        _glGetProgramInfoLog(program, sizeof(strInfoLog), NULL, strInfoLog); CHECK_GL_ERROR;
#ifdef ANT_WINDOWS
        OutputDebugString("Linker failure: ");
        OutputDebugString(strInfoLog);
        OutputDebugString("\n");
#endif
        fprintf(stderr, "Linker failure: %s\n", strInfoLog);
        program = 0;
    }

    return program;
}

//  ---------------------------------------------------------------------------

void CTwGraphOpenGLCore::ResizeTriBuffers(size_t _NewSize)
{
    m_TriBufferSize = _NewSize;

    _glBindVertexArray(m_TriVArray);

    _glBindBuffer(GL_ARRAY_BUFFER, m_TriVertices);
    _glBufferData(GL_ARRAY_BUFFER, m_TriBufferSize*sizeof(Vec2), 0, GL_DYNAMIC_DRAW);

    _glBindBuffer(GL_ARRAY_BUFFER, m_TriUVs);
    _glBufferData(GL_ARRAY_BUFFER, m_TriBufferSize*sizeof(Vec2), 0, GL_DYNAMIC_DRAW);

    _glBindBuffer(GL_ARRAY_BUFFER, m_TriColors);
    _glBufferData(GL_ARRAY_BUFFER, m_TriBufferSize*sizeof(color32), 0, GL_DYNAMIC_DRAW);

    CHECK_GL_ERROR;
}

//  ---------------------------------------------------------------------------

#ifdef ANT_OSX
#define _glShaderSource glShaderSource
#endif

int CTwGraphOpenGLCore::Init()
{
    m_Drawing = false;
    m_FontTexID = 0;
    m_FontTex = NULL;

    if( LoadOpenGLCore()==0 )
    {
        g_TwMgr->SetLastError(g_ErrCantLoadOGL);
        return 0;
    }

    // Create line/rect shaders
    const GLchar *lineRectVS[] = {
        "#version 150 core\n"
        "in vec3 vertex;"
        "in vec4 color;"
        "out vec4 fcolor;"
        "void main() { gl_Position = vec4(vertex, 1); fcolor = color; }"
    };
    m_LineRectVS = _glCreateShader(GL_VERTEX_SHADER);
    _glShaderSource(m_LineRectVS, 1, lineRectVS, NULL);
    CompileShader(m_LineRectVS);

    const GLchar *lineRectFS[] = {
        "#version 150 core\n"
        "precision highp float;"
        "in vec4 fcolor;"
        "out vec4 outColor;"
        "void main() { outColor = fcolor; }"
    };
    m_LineRectFS = _glCreateShader(GL_FRAGMENT_SHADER);
    _glShaderSource(m_LineRectFS, 1, lineRectFS, NULL);
    CompileShader(m_LineRectFS);

    m_LineRectProgram = _glCreateProgram();
    _glAttachShader(m_LineRectProgram, m_LineRectVS);
    _glAttachShader(m_LineRectProgram, m_LineRectFS);
    _glBindAttribLocation(m_LineRectProgram, 0, "vertex");
    _glBindAttribLocation(m_LineRectProgram, 1, "color");
    LinkProgram(m_LineRectProgram);

    // Create line/rect vertex buffer
    const GLfloat lineRectInitVertices[] = { 0,0,0, 0,0,0, 0,0,0, 0,0,0 };
    const color32 lineRectInitColors[] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
    _glGenVertexArrays(1, &m_LineRectVArray);
    _glBindVertexArray(m_LineRectVArray);
    _glGenBuffers(1, &m_LineRectVertices);
    _glBindBuffer(GL_ARRAY_BUFFER, m_LineRectVertices);
    _glBufferData(GL_ARRAY_BUFFER, sizeof(lineRectInitVertices), lineRectInitVertices, GL_DYNAMIC_DRAW);
    _glGenBuffers(1, &m_LineRectColors);
    _glBindBuffer(GL_ARRAY_BUFFER, m_LineRectColors);
    _glBufferData(GL_ARRAY_BUFFER, sizeof(lineRectInitColors), lineRectInitColors, GL_DYNAMIC_DRAW);

    // Create triangles shaders
    const GLchar *triVS[] = {
        "#version 150 core\n"
        "uniform vec2 offset;"
        "uniform vec2 wndSize;"
        "in vec2 vertex;"
        "in vec4 color;"
        "out vec4 fcolor;"
        "void main() { gl_Position = vec4(2.0*(vertex.x+offset.x-0.5)/wndSize.x - 1.0, 1.0 - 2.0*(vertex.y+offset.y-0.5)/wndSize.y, 0, 1); fcolor = color; }"
    };
    m_TriVS = _glCreateShader(GL_VERTEX_SHADER);
    _glShaderSource(m_TriVS, 1, triVS, NULL);
    CompileShader(m_TriVS);

    const GLchar *triUniVS[] = {
        "#version 150 core\n"
        "uniform vec2 offset;"
        "uniform vec2 wndSize;"
        "uniform vec4 color;"
        "in vec2 vertex;"
        "out vec4 fcolor;"
        "void main() { gl_Position = vec4(2.0*(vertex.x+offset.x-0.5)/wndSize.x - 1.0, 1.0 - 2.0*(vertex.y+offset.y-0.5)/wndSize.y, 0, 1); fcolor = color; }"
    };
    m_TriUniVS = _glCreateShader(GL_VERTEX_SHADER);
    _glShaderSource(m_TriUniVS, 1, triUniVS, NULL);
    CompileShader(m_TriUniVS);

    m_TriFS = m_TriUniFS = m_LineRectFS;

    m_TriProgram = _glCreateProgram();
    _glAttachShader(m_TriProgram, m_TriVS);
    _glAttachShader(m_TriProgram, m_TriFS);
    _glBindAttribLocation(m_TriProgram, 0, "vertex");
    _glBindAttribLocation(m_TriProgram, 1, "color");
    LinkProgram(m_TriProgram);
    m_TriLocationOffset = _glGetUniformLocation(m_TriProgram, "offset");
    m_TriLocationWndSize = _glGetUniformLocation(m_TriProgram, "wndSize");

    m_TriUniProgram = _glCreateProgram();
    _glAttachShader(m_TriUniProgram, m_TriUniVS);
    _glAttachShader(m_TriUniProgram, m_TriUniFS);
    _glBindAttribLocation(m_TriUniProgram, 0, "vertex");
    _glBindAttribLocation(m_TriUniProgram, 1, "color");
    LinkProgram(m_TriUniProgram);
    m_TriUniLocationOffset = _glGetUniformLocation(m_TriUniProgram, "offset");
    m_TriUniLocationWndSize = _glGetUniformLocation(m_TriUniProgram, "wndSize");
    m_TriUniLocationColor = _glGetUniformLocation(m_TriUniProgram, "color");

    const GLchar *triTexFS[] = {
        "#version 150 core\n"
        "precision highp float;"
        "uniform sampler2D tex;"
        "in vec2 fuv;"
        "in vec4 fcolor;"
        "out vec4 outColor;"
// texture2D is deprecated and replaced by texture with GLSL 3.30 but it seems
// that on Mac Lion backward compatibility is not ensured.
#if defined(ANT_OSX) && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1070)
        "void main() { outColor.rgb = fcolor.bgr; outColor.a = fcolor.a * texture(tex, fuv).r; }"
#else
        "void main() { outColor.rgb = fcolor.bgr; outColor.a = fcolor.a * texture2D(tex, fuv).r; }"
#endif
    };
    m_TriTexFS = _glCreateShader(GL_FRAGMENT_SHADER);
    _glShaderSource(m_TriTexFS, 1, triTexFS, NULL);
    CompileShader(m_TriTexFS);

    const GLchar *triTexVS[] = {
        "#version 150 core\n"
        "uniform vec2 offset;"
        "uniform vec2 wndSize;"
        "in vec2 vertex;"
        "in vec2 uv;"
        "in vec4 color;"
        "out vec2 fuv;"
        "out vec4 fcolor;"
        "void main() { gl_Position = vec4(2.0*(vertex.x+offset.x-0.5)/wndSize.x - 1.0, 1.0 - 2.0*(vertex.y+offset.y-0.5)/wndSize.y, 0, 1); fuv = uv; fcolor = color; }"
    };
    m_TriTexVS = _glCreateShader(GL_VERTEX_SHADER);
    _glShaderSource(m_TriTexVS, 1, triTexVS, NULL);
    CompileShader(m_TriTexVS);

    const GLchar *triTexUniVS[] = {
        "#version 150 core\n"
        "uniform vec2 offset;"
        "uniform vec2 wndSize;"
        "uniform vec4 color;"
        "in vec2 vertex;"
        "in vec2 uv;"
        "out vec4 fcolor;"
        "out vec2 fuv;"
        "void main() { gl_Position = vec4(2.0*(vertex.x+offset.x-0.5)/wndSize.x - 1.0, 1.0 - 2.0*(vertex.y+offset.y-0.5)/wndSize.y, 0, 1); fuv = uv; fcolor = color; }"
    };
    m_TriTexUniVS = _glCreateShader(GL_VERTEX_SHADER);
    _glShaderSource(m_TriTexUniVS, 1, triTexUniVS, NULL);
    CompileShader(m_TriTexUniVS);

    m_TriTexUniFS = m_TriTexFS;

    m_TriTexProgram = _glCreateProgram();
    _glAttachShader(m_TriTexProgram, m_TriTexVS);
    _glAttachShader(m_TriTexProgram, m_TriTexFS);
    _glBindAttribLocation(m_TriTexProgram, 0, "vertex");
    _glBindAttribLocation(m_TriTexProgram, 1, "uv");
    _glBindAttribLocation(m_TriTexProgram, 2, "color");
    LinkProgram(m_TriTexProgram);
    m_TriTexLocationOffset = _glGetUniformLocation(m_TriTexProgram, "offset");
    m_TriTexLocationWndSize = _glGetUniformLocation(m_TriTexProgram, "wndSize");
    m_TriTexLocationTexture = _glGetUniformLocation(m_TriTexProgram, "tex");

    m_TriTexUniProgram = _glCreateProgram();
    _glAttachShader(m_TriTexUniProgram, m_TriTexUniVS);
    _glAttachShader(m_TriTexUniProgram, m_TriTexUniFS);
    _glBindAttribLocation(m_TriTexUniProgram, 0, "vertex");
    _glBindAttribLocation(m_TriTexUniProgram, 1, "uv");
    _glBindAttribLocation(m_TriTexUniProgram, 2, "color");
    LinkProgram(m_TriTexUniProgram);
    m_TriTexUniLocationOffset = _glGetUniformLocation(m_TriTexUniProgram, "offset");
    m_TriTexUniLocationWndSize = _glGetUniformLocation(m_TriTexUniProgram, "wndSize");
    m_TriTexUniLocationColor = _glGetUniformLocation(m_TriTexUniProgram, "color");
    m_TriTexUniLocationTexture = _glGetUniformLocation(m_TriTexUniProgram, "tex");

    // Create tri vertex buffer
    _glGenVertexArrays(1, &m_TriVArray);
    _glGenBuffers(1, &m_TriVertices);
    _glGenBuffers(1, &m_TriUVs);
    _glGenBuffers(1, &m_TriColors);
    ResizeTriBuffers(16384); // set initial size

    CHECK_GL_ERROR;
    return 1;
}

//  ---------------------------------------------------------------------------

int CTwGraphOpenGLCore::Shut()
{
    assert(m_Drawing==false);

    UnbindFont(m_FontTexID);

    CHECK_GL_ERROR;

    _glDeleteProgram(m_LineRectProgram); m_LineRectProgram = 0;
    _glDeleteShader(m_LineRectVS); m_LineRectVS = 0;
    _glDeleteShader(m_LineRectFS); m_LineRectFS = 0;

    _glDeleteProgram(m_TriProgram); m_TriProgram = 0;
    _glDeleteShader(m_TriVS); m_TriVS = 0;

    _glDeleteProgram(m_TriUniProgram); m_TriUniProgram = 0;
    _glDeleteShader(m_TriUniVS); m_TriUniVS = 0;

    _glDeleteProgram(m_TriTexProgram); m_TriTexProgram = 0;
    _glDeleteShader(m_TriTexVS); m_TriTexVS = 0;
    _glDeleteShader(m_TriTexFS); m_TriTexFS = 0;

    _glDeleteProgram(m_TriTexUniProgram); m_TriTexUniProgram = 0;
    _glDeleteShader(m_TriTexUniVS); m_TriTexUniVS = 0;

    _glDeleteBuffers(1, &m_LineRectVertices); m_LineRectVertices = 0;
    _glDeleteBuffers(1, &m_LineRectColors); m_LineRectColors = 0;
    _glDeleteVertexArrays(1, &m_LineRectVArray); m_LineRectVArray = 0;

    _glDeleteBuffers(1, &m_TriVertices); m_TriVertices = 0;
    _glDeleteBuffers(1, &m_TriColors); m_TriColors = 0;
    _glDeleteBuffers(1, &m_TriUVs); m_TriUVs = 0;
    _glDeleteVertexArrays(1, &m_TriVArray); m_TriVArray = 0;

    CHECK_GL_ERROR;

    int Res = 1;
    if( UnloadOpenGLCore()==0 )
    {
        g_TwMgr->SetLastError(g_ErrCantUnloadOGL);
        Res = 0;
    }

    return Res;
}

//  ---------------------------------------------------------------------------

void CTwGraphOpenGLCore::BeginDraw(int _WndWidth, int _WndHeight)
{
    CHECK_GL_ERROR;
    assert(m_Drawing==false && _WndWidth>0 && _WndHeight>0);
    m_Drawing = true;
    m_WndWidth = _WndWidth;
    m_WndHeight = _WndHeight;
    m_OffsetX = 0;
    m_OffsetY = 0;

    _glGetIntegerv(GL_VIEWPORT, m_PrevViewport); CHECK_GL_ERROR;
    if( _WndWidth>0 && _WndHeight>0 )
    {
        GLint Vp[4];
        Vp[0] = 0;
        Vp[1] = 0;
        Vp[2] = _WndWidth-1;
        Vp[3] = _WndHeight-1;
        _glViewport(Vp[0], Vp[1], Vp[2], Vp[3]);
    }

    m_PrevVArray = 0;
    _glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&m_PrevVArray); CHECK_GL_ERROR;
    _glBindVertexArray(0); CHECK_GL_ERROR;

    m_PrevLineWidth = 1;
    _glGetFloatv(GL_LINE_WIDTH, &m_PrevLineWidth); CHECK_GL_ERROR;
    _glLineWidth(1); CHECK_GL_ERROR;

    m_PrevLineSmooth = _glIsEnabled(GL_LINE_SMOOTH);
    _glDisable(GL_LINE_SMOOTH); CHECK_GL_ERROR;

    m_PrevCullFace = _glIsEnabled(GL_CULL_FACE);
    _glDisable(GL_CULL_FACE); CHECK_GL_ERROR;

    m_PrevDepthTest = _glIsEnabled(GL_DEPTH_TEST);
    _glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR;

    m_PrevBlend = _glIsEnabled(GL_BLEND);
    _glEnable(GL_BLEND); CHECK_GL_ERROR;

    m_PrevScissorTest = _glIsEnabled(GL_SCISSOR_TEST);
    _glDisable(GL_SCISSOR_TEST); CHECK_GL_ERROR;

    _glGetIntegerv(GL_SCISSOR_BOX, m_PrevScissorBox); CHECK_GL_ERROR;

    _glGetIntegerv(GL_BLEND_SRC, &m_PrevSrcBlend); CHECK_GL_ERROR;
    _glGetIntegerv(GL_BLEND_DST, &m_PrevDstBlend); CHECK_GL_ERROR;
    _glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); CHECK_GL_ERROR;

    m_PrevTexture = 0;
    _glGetIntegerv(GL_TEXTURE_BINDING_2D, &m_PrevTexture); CHECK_GL_ERROR;
    _glBindTexture(GL_TEXTURE_2D, 0); CHECK_GL_ERROR;

    m_PrevProgramObject = 0;
    _glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&m_PrevProgramObject); CHECK_GL_ERROR;
    _glBindVertexArray(0); CHECK_GL_ERROR;
    _glUseProgram(0); CHECK_GL_ERROR;

    m_PrevActiveTexture = 0;
    _glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&m_PrevActiveTexture); CHECK_GL_ERROR;
    _glActiveTexture(GL_TEXTURE0);

    CHECK_GL_ERROR;
}

//  ---------------------------------------------------------------------------

void CTwGraphOpenGLCore::EndDraw()
{
    assert(m_Drawing==true);
    m_Drawing = false;

    _glLineWidth(m_PrevLineWidth); CHECK_GL_ERROR;

    if( m_PrevLineSmooth )
    {
      _glEnable(GL_LINE_SMOOTH); CHECK_GL_ERROR;
    }
    else
    {
      _glDisable(GL_LINE_SMOOTH); CHECK_GL_ERROR;
    }

    if( m_PrevCullFace )
    {
      _glEnable(GL_CULL_FACE); CHECK_GL_ERROR;
    }
    else
    {
      _glDisable(GL_CULL_FACE); CHECK_GL_ERROR;
    }

    if( m_PrevDepthTest )
    {
      _glEnable(GL_DEPTH_TEST); CHECK_GL_ERROR;
    }
    else
    {
      _glDisable(GL_DEPTH_TEST); CHECK_GL_ERROR;
    }

    if( m_PrevBlend )
    {
      _glEnable(GL_BLEND); CHECK_GL_ERROR;
    }
    else
    {
      _glDisable(GL_BLEND); CHECK_GL_ERROR;
    }

    if( m_PrevScissorTest )
    {
      _glEnable(GL_SCISSOR_TEST); CHECK_GL_ERROR;
    }
    else
    {
      _glDisable(GL_SCISSOR_TEST); CHECK_GL_ERROR;
    }

    _glScissor(m_PrevScissorBox[0], m_PrevScissorBox[1], m_PrevScissorBox[2], m_PrevScissorBox[3]); CHECK_GL_ERROR;

    _glBlendFunc(m_PrevSrcBlend, m_PrevDstBlend); CHECK_GL_ERROR;

    _glBindTexture(GL_TEXTURE_2D, m_PrevTexture); CHECK_GL_ERROR;

    _glUseProgram(m_PrevProgramObject); CHECK_GL_ERROR;

    _glBindVertexArray(m_PrevVArray); CHECK_GL_ERROR;

    _glViewport(m_PrevViewport[0], m_PrevViewport[1], m_PrevViewport[2], m_PrevViewport[3]); CHECK_GL_ERROR;

    CHECK_GL_ERROR;
}

//  ---------------------------------------------------------------------------

bool CTwGraphOpenGLCore::IsDrawing()
{
    return m_Drawing;
}

//  ---------------------------------------------------------------------------

void CTwGraphOpenGLCore::Restore()
{
    UnbindFont(m_FontTexID);
    m_FontTexID = 0;
    m_FontTex = NULL;
}

//  ---------------------------------------------------------------------------

static inline float ToNormScreenX(float x, int wndWidth)
{
    return 2.0f*((float)x-0.5f)/wndWidth - 1.0f;
}

static inline float ToNormScreenY(float y, int wndHeight)
{
    return 1.0f - 2.0f*((float)y-0.5f)/wndHeight;
}

//  ---------------------------------------------------------------------------

void CTwGraphOpenGLCore::DrawLine(int _X0, int _Y0, int _X1, int _Y1, color32 _Color0, color32 _Color1, bool _AntiAliased)
{
    CHECK_GL_ERROR;
    assert(m_Drawing==true);

    //const GLfloat dx = +0.0f;
    const GLfloat dx = 0;
    //GLfloat dy = -0.2f;
    const GLfloat dy = -0.5f;
    if( _AntiAliased )
        _glEnable(GL_LINE_SMOOTH);
    else
        _glDisable(GL_LINE_SMOOTH);

    _glBindVertexArray(m_LineRectVArray);

    GLfloat x0 = ToNormScreenX(_X0+dx + m_OffsetX, m_WndWidth);
    GLfloat y0 = ToNormScreenY(_Y0+dy + m_OffsetY, m_WndHeight);
    GLfloat x1 = ToNormScreenX(_X1+dx + m_OffsetX, m_WndWidth);
    GLfloat y1 = ToNormScreenY(_Y1+dy + m_OffsetY, m_WndHeight);
    GLfloat vertices[] = { x0,y0,0,  x1,y1,0 };
    _glBindBuffer(GL_ARRAY_BUFFER, m_LineRectVertices);
    _glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
    _glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 0, NULL);
    _glEnableVertexAttribArray(0);

    color32 colors[] = { _Color0, _Color1 };
    _glBindBuffer(GL_ARRAY_BUFFER, m_LineRectColors);
    _glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(colors), colors);
    _glVertexAttribPointer(1, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
    _glEnableVertexAttribArray(1);

    _glUseProgram(m_LineRectProgram);
    _glDrawArrays(GL_LINES, 0, 2);

    if( _AntiAliased )
        _glDisable(GL_LINE_SMOOTH);

    CHECK_GL_ERROR;
}

//  ---------------------------------------------------------------------------

void CTwGraphOpenGLCore::DrawRect(int _X0, int _Y0, int _X1, int _Y1, color32 _Color00, color32 _Color10, color32 _Color01, color32 _Color11)
{
    CHECK_GL_ERROR;
    assert(m_Drawing==true);

    // border adjustment
    if(_X0<_X1)
        ++_X1;
    else if(_X0>_X1)
        ++_X0;
    if(_Y0<_Y1)
        --_Y0;
    else if(_Y0>_Y1)
        --_Y1;

    _glBindVertexArray(m_LineRectVArray);

    GLfloat x0 = ToNormScreenX((float)_X0 + m_OffsetX, m_WndWidth);
    GLfloat y0 = ToNormScreenY((float)_Y0 + m_OffsetY, m_WndHeight);
    GLfloat x1 = ToNormScreenX((float)_X1 + m_OffsetX, m_WndWidth);
    GLfloat y1 = ToNormScreenY((float)_Y1 + m_OffsetY, m_WndHeight);
    GLfloat vertices[] = { x0,y0,0, x1,y0,0, x0,y1,0, x1,y1,0 };
    _glBindBuffer(GL_ARRAY_BUFFER, m_LineRectVertices);
    _glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
    _glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 0, NULL);
    _glEnableVertexAttribArray(0);

    GLuint colors[] = { _Color00, _Color10, _Color01, _Color11 };
    _glBindBuffer(GL_ARRAY_BUFFER, m_LineRectColors);
    _glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(colors), colors);
    _glVertexAttribPointer(1, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
    _glEnableVertexAttribArray(1);

    _glUseProgram(m_LineRectProgram);
    _glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    CHECK_GL_ERROR;
}

//  ---------------------------------------------------------------------------

void *CTwGraphOpenGLCore::NewTextObj()
{
    return new CTextObj;
}

//  ---------------------------------------------------------------------------

void CTwGraphOpenGLCore::DeleteTextObj(void *_TextObj)
{
    assert(_TextObj!=NULL);
    delete static_cast<CTextObj *>(_TextObj);
}

//  ---------------------------------------------------------------------------

void CTwGraphOpenGLCore::BuildText(void *_TextObj, const std::string *_TextLines, color32 *_LineColors, color32 *_LineBgColors, int _NbLines, const CTexFont *_Font, int _Sep, int _BgWidth)
{
    assert(m_Drawing==true);
    assert(_TextObj!=NULL);
    assert(_Font!=NULL);

    if( _Font != m_FontTex )
    {
        UnbindFont(m_FontTexID);
        m_FontTexID = BindFont(_Font);
        m_FontTex = _Font;
    }
    CTextObj *TextObj = static_cast<CTextObj *>(_TextObj);
    TextObj->m_TextVerts.resize(0);
    TextObj->m_TextUVs.resize(0);
    TextObj->m_BgVerts.resize(0);
    TextObj->m_Colors.resize(0);
    TextObj->m_BgColors.resize(0);

    int x, x1, y, y1, i, Len;
    unsigned char ch;
    const unsigned char *Text;
    color32 LineColor = COLOR32_RED;
    for( int Line=0; Line<_NbLines; ++Line )
    {
        x = 0;
        y = Line * (_Font->m_CharHeight+_Sep);
        y1 = y+_Font->m_CharHeight;
        Len = (int)_TextLines[Line].length();
        Text = (const unsigned char *)(_TextLines[Line].c_str());
        if( _LineColors!=NULL )
            LineColor = (_LineColors[Line]&0xff00ff00) | GLubyte(_LineColors[Line]>>16) | (GLubyte(_LineColors[Line])<<16);

        for( i=0; i<Len; ++i )
        {
            ch = Text[i];
            x1 = x + _Font->m_CharWidth[ch];

            TextObj->m_TextVerts.push_back(Vec2(x , y ));
            TextObj->m_TextVerts.push_back(Vec2(x1, y ));
            TextObj->m_TextVerts.push_back(Vec2(x , y1));
            TextObj->m_TextVerts.push_back(Vec2(x1, y ));
            TextObj->m_TextVerts.push_back(Vec2(x1, y1));
            TextObj->m_TextVerts.push_back(Vec2(x , y1));

            TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV0[ch]));
            TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV0[ch]));
            TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV1[ch]));
            TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV0[ch]));
            TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU1[ch], _Font->m_CharV1[ch]));
            TextObj->m_TextUVs.push_back(Vec2(_Font->m_CharU0[ch], _Font->m_CharV1[ch]));

            if( _LineColors!=NULL )
            {
                TextObj->m_Colors.push_back(LineColor);
                TextObj->m_Colors.push_back(LineColor);
                TextObj->m_Colors.push_back(LineColor);
                TextObj->m_Colors.push_back(LineColor);
                TextObj->m_Colors.push_back(LineColor);
                TextObj->m_Colors.push_back(LineColor);
            }

            x = x1;
        }
        if( _BgWidth>0 )
        {
            TextObj->m_BgVerts.push_back(Vec2(-1        , y ));
            TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y ));
            TextObj->m_BgVerts.push_back(Vec2(-1        , y1));
            TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y ));
            TextObj->m_BgVerts.push_back(Vec2(_BgWidth+1, y1));
            TextObj->m_BgVerts.push_back(Vec2(-1        , y1));

            if( _LineBgColors!=NULL )
            {
                color32 LineBgColor = (_LineBgColors[Line]&0xff00ff00) | GLubyte(_LineBgColors[Line]>>16) | (GLubyte(_LineBgColors[Line])<<16);
                TextObj->m_BgColors.push_back(LineBgColor);
                TextObj->m_BgColors.push_back(LineBgColor);
                TextObj->m_BgColors.push_back(LineBgColor);
                TextObj->m_BgColors.push_back(LineBgColor);
                TextObj->m_BgColors.push_back(LineBgColor);
                TextObj->m_BgColors.push_back(LineBgColor);
            }
        }
    }
}

//  ---------------------------------------------------------------------------

void CTwGraphOpenGLCore::DrawText(void *_TextObj, int _X, int _Y, color32 _Color, color32 _BgColor)
{
    CHECK_GL_ERROR;
    assert(m_Drawing==true);
    assert(_TextObj!=NULL);
    CTextObj *TextObj = static_cast<CTextObj *>(_TextObj);

    if( TextObj->m_TextVerts.size()<4 && TextObj->m_BgVerts.size()<4 )
        return; // nothing to draw

    // draw character background triangles
    if( (_BgColor!=0 || TextObj->m_BgColors.size()==TextObj->m_BgVerts.size()) && TextObj->m_BgVerts.size()>=4 )
    {
        size_t numBgVerts = TextObj->m_BgVerts.size();
        if( numBgVerts > m_TriBufferSize )
            ResizeTriBuffers(numBgVerts + 2048);

        _glBindVertexArray(m_TriVArray);

        _glBindBuffer(GL_ARRAY_BUFFER, m_TriVertices);
        _glBufferSubData(GL_ARRAY_BUFFER, 0, numBgVerts*sizeof(Vec2), &(TextObj->m_BgVerts[0]));
        _glVertexAttribPointer(0, 2, GL_FLOAT, GL_TRUE, 0, NULL);
        _glEnableVertexAttribArray(0);
        _glDisableVertexAttribArray(1);
        _glDisableVertexAttribArray(2);

        if( TextObj->m_BgColors.size()==TextObj->m_BgVerts.size() && _BgColor==0 )
        {
            _glBindBuffer(GL_ARRAY_BUFFER, m_TriColors);
            _glBufferSubData(GL_ARRAY_BUFFER, 0, numBgVerts*sizeof(color32), &(TextObj->m_BgColors[0]));
            _glVertexAttribPointer(1, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
            _glEnableVertexAttribArray(1);

            _glUseProgram(m_TriProgram);
            _glUniform2f(m_TriLocationOffset, (float)_X, (float)_Y);
            _glUniform2f(m_TriLocationWndSize, (float)m_WndWidth, (float)m_WndHeight);
        }
        else
        {
            _glUseProgram(m_TriUniProgram);
            _glUniform4f(m_TriUniLocationColor, GLfloat((_BgColor>>16)&0xff)/256.0f, GLfloat((_BgColor>>8)&0xff)/256.0f, GLfloat(_BgColor&0xff)/256.0f, GLfloat((_BgColor>>24)&0xff)/256.0f);
            _glUniform2f(m_TriUniLocationOffset, (float)_X, (float)_Y);
            _glUniform2f(m_TriUniLocationWndSize, (float)m_WndWidth, (float)m_WndHeight);
        }

        _glDrawArrays(GL_TRIANGLES, 0, (GLsizei)TextObj->m_BgVerts.size());
    }

    // draw character triangles
    if( TextObj->m_TextVerts.size()>=4 )
    {
        _glActiveTexture(GL_TEXTURE0);
        _glBindTexture(GL_TEXTURE_2D, m_FontTexID);
        size_t numTextVerts = TextObj->m_TextVerts.size();
        if( numTextVerts > m_TriBufferSize )
            ResizeTriBuffers(numTextVerts + 2048);

        _glBindVertexArray(m_TriVArray);
        _glDisableVertexAttribArray(2);

        _glBindBuffer(GL_ARRAY_BUFFER, m_TriVertices);
        _glBufferSubData(GL_ARRAY_BUFFER, 0, numTextVerts*sizeof(Vec2), &(TextObj->m_TextVerts[0]));
        _glVertexAttribPointer(0, 2, GL_FLOAT, GL_TRUE, 0, NULL);
        _glEnableVertexAttribArray(0);

        _glBindBuffer(GL_ARRAY_BUFFER, m_TriUVs);
        _glBufferSubData(GL_ARRAY_BUFFER, 0, numTextVerts*sizeof(Vec2), &(TextObj->m_TextUVs[0]));
        _glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
        _glEnableVertexAttribArray(1);

        if( TextObj->m_Colors.size()==TextObj->m_TextVerts.size() && _Color==0 )
        {
            _glBindBuffer(GL_ARRAY_BUFFER, m_TriColors);
            _glBufferSubData(GL_ARRAY_BUFFER, 0, numTextVerts*sizeof(color32), &(TextObj->m_Colors[0]));
            _glVertexAttribPointer(2, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
            _glEnableVertexAttribArray(2);

            _glUseProgram(m_TriTexProgram);
            _glUniform2f(m_TriTexLocationOffset, (float)_X, (float)_Y);
            _glUniform2f(m_TriTexLocationWndSize, (float)m_WndWidth, (float)m_WndHeight);
            _glUniform1i(m_TriTexLocationTexture, 0);
        }
        else
        {
            _glUseProgram(m_TriTexUniProgram);
            _glUniform4f(m_TriTexUniLocationColor, GLfloat((_Color>>16)&0xff)/256.0f, GLfloat((_Color>>8)&0xff)/256.0f, GLfloat(_Color&0xff)/256.0f, GLfloat((_Color>>24)&0xff)/256.0f);
            _glUniform2f(m_TriTexUniLocationOffset, (float)_X, (float)_Y);
            _glUniform2f(m_TriTexUniLocationWndSize, (float)m_WndWidth, (float)m_WndHeight);
            _glUniform1i(m_TriTexUniLocationTexture, 0);
        }

        _glDrawArrays(GL_TRIANGLES, 0, (GLsizei)TextObj->m_TextVerts.size());
    }

    CHECK_GL_ERROR;
}

//  ---------------------------------------------------------------------------

void CTwGraphOpenGLCore::ChangeViewport(int _X0, int _Y0, int _Width, int _Height, int _OffsetX, int _OffsetY)
{
    // glViewport impacts the NDC; use glScissor instead
    m_OffsetX = _X0 + _OffsetX;
    m_OffsetY = _Y0 + _OffsetY;
    SetScissor(_X0, _Y0, _Width, _Height);
}

//  ---------------------------------------------------------------------------

void CTwGraphOpenGLCore::RestoreViewport()
{
    m_OffsetX = m_OffsetY = 0;
    SetScissor(0, 0, 0, 0);
}

//  ---------------------------------------------------------------------------

void CTwGraphOpenGLCore::SetScissor(int _X0, int _Y0, int _Width, int _Height)
{
    if( _Width>0 && _Height>0 )
    {
        _glScissor(_X0-1, m_WndHeight-_Y0-_Height, _Width-1, _Height);
        _glEnable(GL_SCISSOR_TEST);
    }
    else
        _glDisable(GL_SCISSOR_TEST);
}

//  ---------------------------------------------------------------------------

void CTwGraphOpenGLCore::DrawTriangles(int _NumTriangles, int *_Vertices, color32 *_Colors, Cull _CullMode)
{
    assert(m_Drawing==true);

    const GLfloat dx = +0.0f;
    const GLfloat dy = +0.0f;

    // Backup states
    GLint prevCullFaceMode, prevFrontFace;
    _glGetIntegerv(GL_CULL_FACE_MODE, &prevCullFaceMode);
    _glGetIntegerv(GL_FRONT_FACE, &prevFrontFace);
    GLboolean prevCullEnable = _glIsEnabled(GL_CULL_FACE);
    _glCullFace(GL_BACK);
    _glEnable(GL_CULL_FACE);
    if( _CullMode==CULL_CW )
        _glFrontFace(GL_CCW);
    else if( _CullMode==CULL_CCW )
        _glFrontFace(GL_CW);
    else
        _glDisable(GL_CULL_FACE);

    _glUseProgram(m_TriProgram);
    _glBindVertexArray(m_TriVArray);
    _glUniform2f(m_TriLocationOffset, (float)m_OffsetX+dx, (float)m_OffsetY+dy);
    _glUniform2f(m_TriLocationWndSize, (float)m_WndWidth, (float)m_WndHeight);
    _glDisableVertexAttribArray(2);

    size_t numVerts = 3*_NumTriangles;
    if( numVerts > m_TriBufferSize )
        ResizeTriBuffers(numVerts + 2048);

    _glBindBuffer(GL_ARRAY_BUFFER, m_TriVertices);
    _glBufferSubData(GL_ARRAY_BUFFER, 0, numVerts*2*sizeof(int), _Vertices);
    _glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, NULL);
    _glEnableVertexAttribArray(0);

    _glBindBuffer(GL_ARRAY_BUFFER, m_TriColors);
    _glBufferSubData(GL_ARRAY_BUFFER, 0, numVerts*sizeof(color32), _Colors);
    _glVertexAttribPointer(1, GL_BGRA, GL_UNSIGNED_BYTE, GL_TRUE, 0, NULL);
    _glEnableVertexAttribArray(1);

    _glDrawArrays(GL_TRIANGLES, 0, (GLsizei)numVerts);

    // Reset states
    _glCullFace(prevCullFaceMode);
    _glFrontFace(prevFrontFace);
    if( prevCullEnable )
        _glEnable(GL_CULL_FACE);
    else
        _glDisable(GL_CULL_FACE);

    CHECK_GL_ERROR;
}

//  ---------------------------------------------------------------------------

redpajama_set_name: RedPajamaGithub


text:
TV Stars
May 05, 1995 Taurus
Who was born on this day?
Bethlehem, Pennsylvania, USA
singer, YouTuber, Internet celebrity
Who's Gabi DeMartino?
Who are Gabi DeMartino's parents?
YouTube career
Is Gabi DeMartino in a relationship?
How much is Gabi DeMartino's net worth?
Gabriella DeMartino who was born on May 5, 1995 is an American YouTube celebrity, vlogger and pop singer. She rose to fame for the collaborative YouTube channel titled Niki and Gabi, which she launched with her twin sister Niki. Gabi is also known for 00RemakeGirls sketch comedy channel that she and Niki run with their older sister Alessandra.
Niki DeMartino with Gabi DeMartino / Instagram
The star hails from Bethlehem, Pennsylvania. Her parents' names are Jeffrey and Nelida and they both work in the healthcare industry. Nelida met and fell in love with Jeffrey after she received a job offer from the dental clinic where he worked. Gabi also has three siblings.
Gabi and Niki created their YouTube channel in 2012 and initially planned to dedicate it to beauty and fashion-related content. As the popularity of their channel grew, the sisters also started to upload challenges, lifestyle and music videos. As of August 2022, they had accumulated an insane number of 9 million subscribers. In 2015, the DeMartino sisters released their first single, "It". Gabi also started a solo pop singer career in 2016, when her debut single "Ever After" came out. Besides YouTube, she is active on Instagram, where she shares stunning photos of herself with her 4.5 million fans. Gabi also has over 1 million followers on Twitter.
Gabi is currently single. From 2010 until 2011, she dated a man named Brandon Grube. Gabi and Brandon even started a YouTube channel together, but it became inactive after their split. In 2015, the star began a relationship with actor, singler and YouTuber Collin Vogt. The couple got engaged in 2020, but broke up in the summer of 2022.
Gabi DeMartino with Collin Vogt / Instagram
The YouTube sensation's net worth is approximately estimated at around $1.5 million as of 2022.
She is 6 minutes younger than Niki.
Gabi's song "Immaculate" was inspired by the negative and abusive comments people left on her social media.
She has eight tattoos.
Gabi is a huge fan of Ariana Grande and appeared in the music video for her hit song "Thank U, Next."
YouTuber Chris Chann
YouTuber Nick Bean
YouTuber Danny Duncan
YouTuber ZexyZek
© «world-celebs.com», 2019


text:
Published on EmpowHER - Women's Health Online (https://www.empowher.com)
Home > Charcot-Marie-Tooth Disease: A Neurological Disorder
Charcot-Marie-Tooth Disease: A Neurological Disorder
By Jody Smith
Created 02/11/2010 - 10:01
Charcot-Marie-Tooth disease is not, as it may appear at first glance, a problem to take to your dentist. It is actually an inherited neurological disorder whose unusual name comes from the two French neurologists, Jean Charcot and Pierre Marie, and the English doctor Howard Henry Tooth, who clinically described it in 1886.
Other names for this condition are Charcot-Marie-Tooth hereditary neuropathy, Charcot-Marie-Tooth syndrome, hereditary motor and sensory neuropathy (HNSN), and Peroneal Muscular Atrophy (PMA).
Charcot-Marie-Tooth disease (CMT) involves muscle weakness and loss of sensation, predominantly in the arms and legs, especially in the calves.
This disease affects the periphery nerves, which control muscles and send messages from the legs and arms to the brain. These messages give us our sense of touch.
The disorder generally makes itself known in childhood or adolescence, though this can happen at any age.
The earliest indicators of CMT are usually clumsiness and weakness in the ankles, feet and legs. The feet may be either extremely arched or extremely flat, and the toes may be curled upwards, into "hammertoes".
Walking is awkward due to weak ankle muscles which causes the individual to step higher than normal, or the toes may drop forward.
Arms and feet become numb. Injuries can occur due to lack of sensation. The lower legs are quite thin, and have been described as "stork legs".
Cramping can occur in the lower legs and forearms, and some of the body's reflexes deteriorate. The hands suffer weakness and atrophy in the muscles, and fine motor ability decreases.
Balance becomes precarious. The spine may curve (scoliosis). There may be some hearing or sight loss.
Symptoms vary widely from individual to individual. Some people will have mild symptoms that do not interfere with their ability to live normal lives. Very often though, numbness and weakness will have far-reaching effects.
While CMT does not affect life expectancy, there is no cure. But treatments are available that can make a difference in quality of life.
Physical therapy can stretch and strengthen the weak muscles. Occupational therapy will help the individual learn new ways to better handle the challenges of daily life.
Orthopedic devices, like braces or splints, or special shoes or inserts, can help the individual to walk more easily.
Thumb splints can cause a return of some dexterity. A back brace may be in order for those with scoliosis. In cases of severe deformity, surgery may be performed.
Learning About Charcot-Marie-Tooth Disease
http://www.genome.gov/11009201
Genetics Home Reference: Charcot-Marie-Tooth disease
http://ghr.nlm.nih.gov/condition=charcotmarietoothdisease
http://emedicine.medscape.com/article/315260-overview
What Is Charcot-Marie-Tooth Disease (CMT)? What Causes Charcot-Marie-Tooth Disease?
http://www.medicalnewstoday.com/articles/172056.php
Charcot-Marie-Tooth Disease Fact Sheet
http://www.ninds.nih.gov/disorders/charcot_marie_tooth/detail_charcot_marie_tooth.htm
Mayo Clinic: Charcot-Marie-Tooth disease
http://www.mayoclinic.com/health/charcot-marie-tooth-disease/DS00557
Visit Jody's website and blog at http://www.ncubator.ca and http://ncubator.ca/blogger
Copyright © 2020 HW, LLC d/b/a EmpowHER Media unless otherwise noted. EmpowHER does not provide medical advice, diagnosis, or treatment.
Source URL (retrieved on 01/18/2020 - 10:11): https://www.empowher.com/charcot-maire-tooth-disease/content/charcot-marie-tooth-disease-neurological-disorder


There's a viral story going around about a hair stylist and the nurse she had in her chair. It's incredibly insprirng.
Reading this story had me heading down memory road. I've had the fortune of spend a LOT of time in hospitals over the years. Mostly for myself, but at time to be next to family members or my wife while she gave birth to our children.
While the doctors involved always seem to get the credit for everything they do... Nurses don't get NEARLY enough credit for their CRITICAL role in the recovery and care of the patients.
So, take a minute today to thank any nurse you see for what they do for us all!