kernel32/profile: Add a few NULL checks (Coverity).
[wine] / dlls / infosoft / wordbreaker.c
1 /*
2  *    Word splitter Implementation
3  *
4  * Copyright 2006 Mike McCormack
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define COBJMACROS
22
23 #include "config.h"
24
25 #include <stdarg.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winreg.h"
31 #include "ole2.h"
32 #include "indexsrv.h"
33 #include "wine/unicode.h"
34 #include "wine/debug.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(infosoft);
37
38 typedef struct tag_wordbreaker_impl
39 {
40     const IWordBreakerVtbl *lpVtbl;
41     LONG ref;
42 } wordbreaker_impl;
43
44 static HRESULT WINAPI wb_QueryInterface( IWordBreaker *iface,
45         REFIID riid, LPVOID *ppvObj)
46 {
47     wordbreaker_impl *This = (wordbreaker_impl *)iface;
48
49     TRACE("(%p)->(%s)\n",This,debugstr_guid(riid));
50
51     *ppvObj = NULL;
52
53     if (IsEqualIID(riid, &IID_IUnknown) ||
54         IsEqualIID(riid, &IID_IWordBreaker))
55     {
56         *ppvObj = This;
57         return S_OK;
58     }
59
60     TRACE("-- E_NOINTERFACE\n");
61     return E_NOINTERFACE;
62 }
63
64 static ULONG WINAPI wb_AddRef( IWordBreaker *iface )
65 {
66     wordbreaker_impl *This = (wordbreaker_impl *)iface;
67     return InterlockedIncrement(&This->ref);
68 }
69
70 static ULONG WINAPI wb_Release(IWordBreaker *iface)
71 {
72     wordbreaker_impl *This = (wordbreaker_impl *)iface;
73     LONG refcount;
74
75     refcount = InterlockedDecrement(&This->ref);
76     if (!refcount)
77         HeapFree(GetProcessHeap(), 0, This);
78
79     return refcount;
80 }
81
82 static HRESULT WINAPI wb_Init( IWordBreaker *iface,
83         BOOL fQuery, ULONG ulMaxTokenSize, BOOL *pfLicense )
84 {
85     TRACE("%d %u\n", fQuery, ulMaxTokenSize);
86     *pfLicense = FALSE;
87     return S_OK;
88 }
89
90 static HRESULT call_sink( IWordSink *pWordSink, TEXT_SOURCE *ts, UINT len )
91 {
92     HRESULT r;
93
94     if (!len)
95         return S_OK;
96
97     TRACE("%d %s\n", len, debugstr_w(&ts->awcBuffer[ts->iCur]));
98
99     r = IWordSink_PutWord( pWordSink, len, &ts->awcBuffer[ts->iCur], len, ts->iCur );
100     ts->iCur += len;
101
102     return r;
103 }
104
105 static HRESULT WINAPI wb_BreakText( IWordBreaker *iface,
106          TEXT_SOURCE *ts, IWordSink *pWordSink, IPhraseSink *pPhraseSink)
107 {
108     UINT len, state = 0;
109     WCHAR ch;
110
111     TRACE("%p %p %p\n", ts, pWordSink, pPhraseSink);
112
113     if (pPhraseSink)
114         FIXME("IPhraseSink won't be called\n");
115
116     do
117     {
118         len = 0;
119         while ((ts->iCur + len) < ts->iEnd)
120         {
121             ch = ts->awcBuffer[ts->iCur + len];
122
123             switch (state)
124             {
125             case 0: /* skip spaces and punctuation */
126
127                 if (!ch || ispunctW(ch) || isspaceW(ch))
128                     ts->iCur ++;
129                 else
130                     state = 1;
131                 break;
132
133             case 1: /* find the end of the word */
134
135                 if (ch && !ispunctW(ch) && !isspaceW(ch))
136                     len++;
137                 else
138                 {
139                     call_sink( pWordSink, ts, len );
140                     len = 0;
141                     state = 0;
142                 }
143                 break;
144
145             }
146         }
147         call_sink( pWordSink, ts, len );
148
149     } while (S_OK == ts->pfnFillTextBuffer( ts ));
150
151     return S_OK;
152 }
153
154 static HRESULT WINAPI wb_ComposePhrase( IWordBreaker *iface,
155          const WCHAR *pwcNoun, ULONG cwcNoun,
156          const WCHAR *pwcModifier, ULONG cwcModifier,
157          ULONG ulAttachmentType, WCHAR *pwcPhrase, ULONG *pcwcPhrase)
158 {
159     FIXME("%p %u %p %u %u %p %p\n", pwcNoun, cwcNoun,
160           pwcModifier, cwcModifier, ulAttachmentType, pwcPhrase, pcwcPhrase);
161     return S_OK;
162 }
163
164 static HRESULT WINAPI wb_GetLicenseToUse( IWordBreaker *iface, const WCHAR **ppwcsLicense )
165 {
166     FIXME("%p\n", ppwcsLicense);
167     *ppwcsLicense = NULL;
168     return S_OK;
169 }
170
171 static const IWordBreakerVtbl wordbreaker_vtbl =
172 {
173     wb_QueryInterface,
174     wb_AddRef,
175     wb_Release,
176     wb_Init,
177     wb_BreakText,
178     wb_ComposePhrase,
179     wb_GetLicenseToUse,
180 };
181
182 HRESULT WINAPI wb_Constructor(IUnknown* pUnkOuter, REFIID riid, LPVOID *ppvObject)
183 {
184     wordbreaker_impl *This;
185     IWordBreaker *wb;
186
187     TRACE("%p %s %p\n", pUnkOuter, debugstr_guid(riid), ppvObject);
188
189     This = HeapAlloc(GetProcessHeap(), 0, sizeof *This);
190     if (!This)
191         return E_OUTOFMEMORY;
192
193     This->ref = 1;
194     This->lpVtbl = &wordbreaker_vtbl;
195
196     wb = (IWordBreaker*) This;
197
198     return IWordBreaker_QueryInterface(wb, riid, ppvObject);
199 }